初次尝试,先发个截图,实验用的运动物体是我的鼠标——鼠标线被我提着,从外部操控其运动。
附代码:
1/**//*
2Copyright (C) 2011, coreBugZJ, all rights reserved.
3
4摄像头静止,且光照等环境不变的情况下,捕捉到运动物体,并绘出运动轨迹。
5
6算法:随便写的,太弱了,略之。
7
8VS2010 + OpenCV 2.1 + Win32 API
9*/
10
11
12#include "resource.h"
13#include <Windows.h>
14
15#include <cv.h>
16#include <cvaux.h>
17#include <cvcompat.h>
18#include <cvinternal.h>
19#include <cvtypes.h>
20#include <cvver.h>
21#include <cvwimage.h>
22#include <cxcore.h>
23#include <cxerror.h>
24#include <cxflann.h>
25#include <cxmisc.h>
26#include <cxtypes.h>
27#include <highgui.h>
28#include <ml.h>
29using namespace cv;
30
31#include <vector>
32using namespace std;
33
34#ifdef _DEBUG
35#include <stdio.h>
36#endif
37
38
39#ifdef _DEBUG
40/**//* debug */
41#pragma comment( lib, "cv210d.lib" )
42#pragma comment( lib, "cvaux210d.lib" )
43#pragma comment( lib, "cxcore210d.lib" )
44#pragma comment( lib, "cxts210d.lib" )
45#pragma comment( lib, "highgui210d.lib" )
46#pragma comment( lib, "ml210d.lib" )
47#pragma comment( lib, "opencv_ffmpeg210d.lib" )
48
49#else
50/**//* release */
51#pragma comment( lib, "cv210.lib" )
52#pragma comment( lib, "cvaux210.lib" )
53#pragma comment( lib, "cxcore210.lib" )
54#pragma comment( lib, "cxts210.lib" )
55#pragma comment( lib, "highgui210.lib" )
56#pragma comment( lib, "ml210.lib" )
57#pragma comment( lib, "opencv_ffmpeg210.lib" )
58
59#endif
60
61
62 // 记录轨迹点的数量
63#define POINT_NUM 100000
64 // 摄像头刚启动时,忽略的帧数
65#define FRAME_IGN 40
66 // 离散化单元的宽高,单位 像素
67#define UNIT_LEN 10
68 // 离散化后单元阈值
69#define UNIT_THRES 10
70
71
72HWND ghDlg = NULL;
73INT gWatch = 0;
74INT gNavig = 0;
75BOOL gExit = FALSE;
76
77
78#ifdef _DEBUG
79FILE *gfp = NULL;
80char *nameDebug = "调试窗口";
81#endif
82
83
84void GetImageBk( IplImage **pImgBk, IplImage *imgWatch ) {
85 if ( NULL != (*pImgBk) ) {
86 ::cvReleaseImage( pImgBk );
87 }
88 *pImgBk = ::cvCreateImage( ::cvGetSize(imgWatch), IPL_DEPTH_8U, 1 );
89 ::cvCvtColor( imgWatch, (*pImgBk), CV_BGRA2GRAY );
90#ifdef _DEBUG
91 ::cvShowImage( nameDebug, (*pImgBk) );
92#endif
93}
94
95
96 // 返回是否得到新的点
97 // 会修改 imgWatch
98BOOL GetNavig( IplImage **pImgNavig, IplImage *imgWatch, IplImage *imgBk ) {
99 static CvPoint pointList[ POINT_NUM ];
100 static int pointNum = 0;
101
102#define THRES 129
103#define MAXT 250
104
105 vector< vector< int > > cnt;
106 int cntHeight, cntWidth, cntTot = 0;
107 double sumX = 0, sumY = 0;
108
109 IplImage *imgW = NULL, *imgN = NULL;
110 CvScalar color;
111 BOOL res = FALSE;
112
113 int i, y, x;
114
115 cntHeight = imgWatch->height / UNIT_LEN + 1;
116 cntWidth = imgWatch->width / UNIT_LEN + 1;
117 cnt.resize( cntHeight );
118 for ( y = 0; y < cntHeight; ++y ) {
119 cnt[ y ].resize( cntWidth, 0 );
120 }
121
122 ::GetImageBk( &imgW, imgWatch );
123 ::GetImageBk( &imgN, imgWatch );
124 ::cvAbsDiff( imgW, imgBk, imgN );
125 ::cvThreshold( imgN, imgN, THRES, MAXT, CV_THRESH_BINARY );
126
127 for ( y = 0; y < imgN->height; ++y ) {
128 for ( x = 0; x < imgN->width; ++x ) {
129 color = ::cvGet2D( imgN, y, x );
130 if ( color.val[ 0 ] < THRES ) {
131 continue;
132 }
133 ++(cnt[ y / UNIT_LEN ][ x / UNIT_LEN ]);
134 }
135 }
136
137 for ( y = 0; y < cntHeight; ++y ) {
138 for ( x = 0; x < cntWidth; ++x ) {
139 i = cnt[ y ][ x ];
140 if ( i >= UNIT_THRES ) {
141 cntTot += i;
142 sumX += i * x * UNIT_LEN;
143 sumY += i * y * UNIT_LEN;
144 }
145 }
146 }
147
148 x = (int)(sumX / cntTot);
149 y = (int)(sumY / cntTot);
150
151 if ( POINT_NUM > pointNum ) {
152 pointList[ pointNum ].x = x;
153 pointList[ pointNum ].y = y;
154 ++pointNum;
155 res = TRUE;
156 }
157
158 ::cvReleaseImage( &imgW );
159 ::cvReleaseImage( &imgN );
160
161 *pImgNavig = imgWatch;
162 color.val[ 0 ] = 0;
163 color.val[ 1 ] = 255;
164 color.val[ 2 ] = 255;
165 color.val[ 3 ] = 0;
166 for ( i = 1; i < pointNum; ++i ) {
167 ::cvLine( (*pImgNavig), pointList[ i-1 ], pointList[ i ], color, 8 );
168 }
169
170#ifdef _DEBUG
171 if ( res ) {
172 }
173#endif
174
175 return res;
176}
177
178
179void DealAllMsg() {
180 MSG msg;
181 while ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
182 if ( ::IsWindow(ghDlg) && ::IsDialogMessage(ghDlg,&msg) ) {
183 continue;
184 }
185 ::TranslateMessage( &msg );
186 ::DispatchMessage( &msg );
187 }
188}
189
190
191void DelayTime( DWORD delay ) {
192 DWORD start = ::GetTickCount();
193 do {
194 ::DealAllMsg();
195 ::Sleep( 2 );
196 } while ( (! gExit) && (::GetTickCount() - start < delay) );
197}
198
199
200INT_PTR CALLBACK DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
201 switch ( uMsg ) {
202 case WM_INITDIALOG :
203 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gWatch );
204 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gNavig );
205 return 1;
206
207 case WM_COMMAND :
208 switch ( LOWORD(wParam) ) {
209 case IDC_RADIO1 :
210 case IDC_RADIO2 :
211 case IDC_RADIO3 :
212 gWatch= LOWORD(wParam) - IDC_RADIO1;
213 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gWatch );
214 return 1;
215 case IDC_RADIO4 :
216 case IDC_RADIO5 :
217 case IDC_RADIO6 :
218 gNavig = LOWORD(wParam) - IDC_RADIO4;
219 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gNavig );
220 return 1;
221 case IDCANCEL :
222 gExit = TRUE;
223 return 1;
224 }
225 break;
226 }
227 return 0;
228}
229
230
231INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmd, INT nShow ) {
232 char *nameWatch = "监视窗口";
233 char *nameNavig = "轨迹窗口";
234 CvCapture *cap = NULL;
235 IplImage *imgWatch = NULL, *imgNavig = NULL, *imgBk = NULL;
236 int frame = 0;
237
238 cap = ::cvCreateCameraCapture( -1 );
239 ::DealAllMsg();
240 if ( NULL == cap ) {
241 ::MessageBox( NULL, TEXT("摄像头错误"), TEXT("错误"), MB_ICONERROR | MB_OK );
242 return 0;
243 }
244
245 ::cvNamedWindow( nameWatch);
246 ::DealAllMsg();
247 ::cvNamedWindow( nameNavig );
248 ::DealAllMsg();
249
250 ghDlg = ::CreateDialogParam( hInst, MAKEINTRESOURCE(IDD_GARAGE_DIALOG), NULL, DlgProc, 0 );
251 ::ShowWindow( ghDlg, SW_SHOW );
252 ::DealAllMsg();
253
254#ifdef _DEBUG
255 gfp = ::fopen( "debug.txt", "wt" );
256 ::cvNamedWindow( nameDebug );
257#endif
258
259 for ( ; ; ) {
260 imgWatch= ::cvQueryFrame( cap );
261 ::DealAllMsg();
262 if ( NULL == imgWatch) {
263 break;
264 }
265
266 if ( frame < FRAME_IGN ) {
267 ++frame;
268 }
269 if ( frame == FRAME_IGN ) {
270 ++frame;
271 ::GetImageBk( &imgBk, imgWatch );
272 }
273
274 switch ( gWatch) {
275 case 0 :
276 ::cvShowImage( nameWatch, imgWatch );
277 break;
278 case 1 :
279 break;
280 case 2 :
281 ::cvDestroyWindow( nameWatch );
282 break;
283 }
284 ::DealAllMsg();
285 if ( gExit ) {
286 break;
287 }
288
289 if ( frame <= FRAME_IGN ) {
290 imgNavig = NULL;
291 }
292 else {
293 if ( ::GetNavig( &imgNavig, imgWatch, imgBk ) ) {
294 }
295 }
296
297 switch ( gNavig ) {
298 case 0 :
299 ::cvShowImage( nameNavig, imgNavig );
300 break;
301 case 1 :
302 break;
303 case 2 :
304 ::cvDestroyWindow( nameNavig );
305 break;
306 }
307 ::DealAllMsg();
308 if ( gExit ) {
309 break;
310 }
311 }
312
313 ::cvReleaseImage( &imgBk );
314
315 ::DestroyWindow( ghDlg );
316
317 ::cvDestroyWindow( nameNavig );
318 ::cvDestroyWindow( nameWatch );
319
320 ::cvReleaseCapture( &cap );
321
322#ifdef _DEBUG
323 ::cvDestroyWindow( nameDebug );
324 ::fclose( gfp );
325#endif
326
327 return 0;
328}
329
1//{{NO_DEPENDENCIES}}
2// Microsoft Visual C++ generated include file.
3// Used by Garage.rc
4//
5#define IDD_GARAGE_DIALOG 101
6#define IDC_RADIO1 1001
7#define IDC_RADIO2 1002
8#define IDC_RADIO3 1003
9#define IDC_RADIO4 1004
10#define IDC_RADIO5 1005
11#define IDC_RADIO6 1006
12
13
14// Next default values for new objects
15//
16#ifdef APSTUDIO_INVOKED
17#ifndef APSTUDIO_READONLY_SYMBOLS
18#define _APS_NEXT_RESOURCE_VALUE 102
19#define _APS_NEXT_COMMAND_VALUE 40001
20#define _APS_NEXT_CONTROL_VALUE 1007
21#define _APS_NEXT_SYMED_VALUE 101
22#endif
23#endif
24
1// Microsoft Visual C++ generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/**//////////////////////////////////////////////////////////////////////////////7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/**//////////////////////////////////////////////////////////////////////////////13#undef APSTUDIO_READONLY_SYMBOLS
14
15/**//////////////////////////////////////////////////////////////////////////////16// Chinese (Simplified, PRC) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
19LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
20
21#ifdef APSTUDIO_INVOKED
22/**//////////////////////////////////////////////////////////////////////////////23//
24// TEXTINCLUDE
25//
26
271 TEXTINCLUDE
28BEGIN
29 "resource.h\0"
30END
31
322 TEXTINCLUDE
33BEGIN
34 "#include ""afxres.h""\r\n"
35 "\0"
36END
37
383 TEXTINCLUDE
39BEGIN
40 "\r\n"
41 "\0"
42END
43
44#endif // APSTUDIO_INVOKED
45
46
47/**//////////////////////////////////////////////////////////////////////////////48//
49// Dialog
50//
51
52IDD_GARAGE_DIALOG DIALOGEX 0, 0, 266, 156
53STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
54EXSTYLE WS_EX_APPWINDOW
55CAPTION "运动轨迹捕捉"
56FONT 8, "MS Shell Dlg", 0, 0, 0x1
57BEGIN
58 DEFPUSHBUTTON "退出",IDCANCEL,209,135,50,14
59 CONTROL "播放",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,40,40,32,10
60 CONTROL "暂停",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,40,65,32,10
61 CONTROL "关闭",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,40,90,32,10
62 CONTROL "播放",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON | WS_GROUP,185,40,32,10
63 CONTROL "暂停",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON,185,65,32,10
64 CONTROL "关闭",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON,185,90,32,10
65 GROUPBOX "监视窗口",IDC_STATIC,23,20,65,86
66 GROUPBOX "轨迹窗口",IDC_STATIC,168,20,65,86
67END
68
69
70/**//////////////////////////////////////////////////////////////////////////////71//
72// DESIGNINFO
73//
74
75#ifdef APSTUDIO_INVOKED
76GUIDELINES DESIGNINFO
77BEGIN
78 IDD_GARAGE_DIALOG, DIALOG
79 BEGIN
80 LEFTMARGIN, 7
81 RIGHTMARGIN, 259
82 TOPMARGIN, 7
83 BOTTOMMARGIN, 149
84 END
85END
86#endif // APSTUDIO_INVOKED
87
88#endif // Chinese (Simplified, PRC) resources
89/**//////////////////////////////////////////////////////////////////////////////90
91
92
93#ifndef APSTUDIO_INVOKED
94/**//////////////////////////////////////////////////////////////////////////////95//
96// Generated from the TEXTINCLUDE 3 resource.
97//
98
99
100/**//////////////////////////////////////////////////////////////////////////////101#endif // not APSTUDIO_INVOKED
102
103