尝试 OpenCV 摄像头 与 Windows 消息机制
OpenCV 的 highgui 提供了简单的界面,然而在 Windows 下,它并未将消息机制封装的足够好,在使用的时候,若不考虑到消息机制,很容易使界面死掉,同时 OpenCV 本身的运转也会出问题。
Windows 下,界面的正常运作需要大量的消息传递与处理,然而 OpenCV 的函数,几乎都与消息无关,目前我只知道 cvWaitKey() 会接收并转发本线程的消息(恕我无知),但只仅限于被调用后的等待时间内,所以并不能完全保证消息机制的正常运作。程序至少需要考虑到主动接收与转发消息,以确保界面的正常运作。(也许这可以解释,为什么许多示例程序中都调用了 cvWaitKey() 函数。)
Windows 下的消息是线程相关的,启动新线程又会引出更多的问题。
下面程序从摄像头获取输入,并在窗口中显示。三个窗口使用一个线程。
我尝试过创建新线程,在新线程中使用 highgui 创建窗口,显示图像,然而,窗口的大小正确,却显示一片灰色(求指教!!)。
附源代码:
由于线程关系,我使用了最朴素的 Win32 API 。
OpenCV 2.1 + VS2010
1
#include
"
resource.h
"
2 #include < Windows.h >
3 #include < highgui.h >
4
5
6 #ifdef _DEBUG
7 /**/ /* debug */
8
9 #pragma comment( lib, " cv210d.lib " )
10 #pragma comment( lib, " cvaux210d.lib " )
11 #pragma comment( lib, " cxcore210d.lib " )
12 #pragma comment( lib, " cxts210d.lib " )
13 #pragma comment( lib, " highgui210d.lib " )
14 #pragma comment( lib, " ml210d.lib " )
15 #pragma comment( lib, " opencv_ffmpeg210d.lib " )
16
17
18 #else
19 /**/ /* release */
20
21 #pragma comment( lib, " cv210.lib " )
22 #pragma comment( lib, " cvaux210.lib " )
23 #pragma comment( lib, " cxcore210.lib " )
24 #pragma comment( lib, " cxts210.lib " )
25 #pragma comment( lib, " highgui210.lib " )
26 #pragma comment( lib, " ml210.lib " )
27 #pragma comment( lib, " opencv_ffmpeg210.lib " )
28
29
30 #endif
31
32
33 HWND ghDlg = NULL;
34 INT gleft = 0 ;
35 INT gright = 0 ;
36 BOOL gexit = FALSE;
37
38
39 void DealAllMsg() {
40 MSG msg;
41 while ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
42 if ( ::IsWindow(ghDlg) && ::IsDialogMessage(ghDlg,&msg) ) {
43 continue;
44 }
45 ::TranslateMessage( &msg );
46 ::DispatchMessage( &msg );
47 }
48}
49
50
51 void DelayTime( DWORD delay ) {
52 DWORD start = ::GetTickCount();
53 do {
54 ::DealAllMsg();
55 ::Sleep( 2 );
56 } while ( (! gexit) && (::GetTickCount() - start < delay) );
57}
58
59
60 INT_PTR CALLBACK DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
61 switch ( uMsg ) {
62 case WM_INITDIALOG :
63 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gleft );
64 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gright );
65 return 1;
66
67 case WM_COMMAND :
68 switch ( LOWORD(wParam) ) {
69 case IDC_RADIO1 :
70 case IDC_RADIO2 :
71 case IDC_RADIO3 :
72 gleft = LOWORD(wParam) - IDC_RADIO1;
73 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gleft );
74 return 1;
75 case IDC_RADIO4 :
76 case IDC_RADIO5 :
77 case IDC_RADIO6 :
78 gright = LOWORD(wParam) - IDC_RADIO4;
79 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gright );
80 return 1;
81 case IDCANCEL :
82 gexit = TRUE;
83 return 1;
84 }
85 break;
86 }
87 return 0;
88}
89
90
91 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmd, INT nShow ) {
92 char *nameleft = "左窗口";
93 char *nameright = "右窗口";
94 CvCapture *cap = NULL;
95 IplImage *imgleft = NULL, *imgright = NULL;
96 int i;
97
98 cap = ::cvCreateCameraCapture( -1 );
99 ::DealAllMsg();
100 if ( NULL == cap ) {
101 ::MessageBox( NULL, TEXT("摄像头错误"), TEXT("错误"), MB_ICONERROR | MB_OK );
102 return 0;
103 }
104
105 ::cvNamedWindow( nameleft );
106 ::DealAllMsg();
107 ::cvNamedWindow( nameright );
108 ::DealAllMsg();
109
110 ghDlg = ::CreateDialogParam( hInst, MAKEINTRESOURCE(IDD_GARAGE_DIALOG), NULL, DlgProc, 0 );
111 ::ShowWindow( ghDlg, SW_SHOW );
112 ::DealAllMsg();
113
114 for ( ; ; ) {
115 for ( i = 0; i < 1; ++i ) {
116 imgleft = ::cvQueryFrame( cap );
117 ::DealAllMsg();
118 if ( NULL == imgleft ) {
119 break;
120 }
121 }
122 if ( NULL == imgleft ) {
123 break;
124 }
125
126 switch ( gleft ) {
127 case 0 :
128 ::cvShowImage( nameleft, imgleft );
129 break;
130 case 1 :
131 break;
132 case 2 :
133 ::cvDestroyWindow( nameleft );
134 break;
135 }
136 ::DealAllMsg();
137 if ( gexit ) {
138 break;
139 }
140
141 imgright = imgleft; // imgright = func( imgleft );
142 ::DealAllMsg();
143
144 switch ( gright ) {
145 case 0 :
146 ::cvShowImage( nameright, imgright );
147 break;
148 case 1 :
149 break;
150 case 2 :
151 ::cvDestroyWindow( nameright );
152 break;
153 }
154 ::DealAllMsg();
155 if ( gexit ) {
156 break;
157 }
158 }
159
160 ::DestroyWindow( ghDlg );
161
162 ::cvDestroyWindow( nameright );
163 ::cvDestroyWindow( nameleft );
164
165 ::cvReleaseCapture( &cap );
166
167 return 0;
168}
169
2 #include < Windows.h >
3 #include < highgui.h >
4
5
6 #ifdef _DEBUG
7 /**/ /* debug */
8
9 #pragma comment( lib, " cv210d.lib " )
10 #pragma comment( lib, " cvaux210d.lib " )
11 #pragma comment( lib, " cxcore210d.lib " )
12 #pragma comment( lib, " cxts210d.lib " )
13 #pragma comment( lib, " highgui210d.lib " )
14 #pragma comment( lib, " ml210d.lib " )
15 #pragma comment( lib, " opencv_ffmpeg210d.lib " )
16
17
18 #else
19 /**/ /* release */
20
21 #pragma comment( lib, " cv210.lib " )
22 #pragma comment( lib, " cvaux210.lib " )
23 #pragma comment( lib, " cxcore210.lib " )
24 #pragma comment( lib, " cxts210.lib " )
25 #pragma comment( lib, " highgui210.lib " )
26 #pragma comment( lib, " ml210.lib " )
27 #pragma comment( lib, " opencv_ffmpeg210.lib " )
28
29
30 #endif
31
32
33 HWND ghDlg = NULL;
34 INT gleft = 0 ;
35 INT gright = 0 ;
36 BOOL gexit = FALSE;
37
38
39 void DealAllMsg() {
40 MSG msg;
41 while ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
42 if ( ::IsWindow(ghDlg) && ::IsDialogMessage(ghDlg,&msg) ) {
43 continue;
44 }
45 ::TranslateMessage( &msg );
46 ::DispatchMessage( &msg );
47 }
48}
49
50
51 void DelayTime( DWORD delay ) {
52 DWORD start = ::GetTickCount();
53 do {
54 ::DealAllMsg();
55 ::Sleep( 2 );
56 } while ( (! gexit) && (::GetTickCount() - start < delay) );
57}
58
59
60 INT_PTR CALLBACK DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
61 switch ( uMsg ) {
62 case WM_INITDIALOG :
63 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gleft );
64 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gright );
65 return 1;
66
67 case WM_COMMAND :
68 switch ( LOWORD(wParam) ) {
69 case IDC_RADIO1 :
70 case IDC_RADIO2 :
71 case IDC_RADIO3 :
72 gleft = LOWORD(wParam) - IDC_RADIO1;
73 ::CheckRadioButton( hDlg, IDC_RADIO1, IDC_RADIO3, IDC_RADIO1+gleft );
74 return 1;
75 case IDC_RADIO4 :
76 case IDC_RADIO5 :
77 case IDC_RADIO6 :
78 gright = LOWORD(wParam) - IDC_RADIO4;
79 ::CheckRadioButton( hDlg, IDC_RADIO4, IDC_RADIO6, IDC_RADIO4+gright );
80 return 1;
81 case IDCANCEL :
82 gexit = TRUE;
83 return 1;
84 }
85 break;
86 }
87 return 0;
88}
89
90
91 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmd, INT nShow ) {
92 char *nameleft = "左窗口";
93 char *nameright = "右窗口";
94 CvCapture *cap = NULL;
95 IplImage *imgleft = NULL, *imgright = NULL;
96 int i;
97
98 cap = ::cvCreateCameraCapture( -1 );
99 ::DealAllMsg();
100 if ( NULL == cap ) {
101 ::MessageBox( NULL, TEXT("摄像头错误"), TEXT("错误"), MB_ICONERROR | MB_OK );
102 return 0;
103 }
104
105 ::cvNamedWindow( nameleft );
106 ::DealAllMsg();
107 ::cvNamedWindow( nameright );
108 ::DealAllMsg();
109
110 ghDlg = ::CreateDialogParam( hInst, MAKEINTRESOURCE(IDD_GARAGE_DIALOG), NULL, DlgProc, 0 );
111 ::ShowWindow( ghDlg, SW_SHOW );
112 ::DealAllMsg();
113
114 for ( ; ; ) {
115 for ( i = 0; i < 1; ++i ) {
116 imgleft = ::cvQueryFrame( cap );
117 ::DealAllMsg();
118 if ( NULL == imgleft ) {
119 break;
120 }
121 }
122 if ( NULL == imgleft ) {
123 break;
124 }
125
126 switch ( gleft ) {
127 case 0 :
128 ::cvShowImage( nameleft, imgleft );
129 break;
130 case 1 :
131 break;
132 case 2 :
133 ::cvDestroyWindow( nameleft );
134 break;
135 }
136 ::DealAllMsg();
137 if ( gexit ) {
138 break;
139 }
140
141 imgright = imgleft; // imgright = func( imgleft );
142 ::DealAllMsg();
143
144 switch ( gright ) {
145 case 0 :
146 ::cvShowImage( nameright, imgright );
147 break;
148 case 1 :
149 break;
150 case 2 :
151 ::cvDestroyWindow( nameright );
152 break;
153 }
154 ::DealAllMsg();
155 if ( gexit ) {
156 break;
157 }
158 }
159
160 ::DestroyWindow( ghDlg );
161
162 ::cvDestroyWindow( nameright );
163 ::cvDestroyWindow( nameleft );
164
165 ::cvReleaseCapture( &cap );
166
167 return 0;
168}
169
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
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)
19 LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
20
21 #ifdef APSTUDIO_INVOKED
22 /**/ /////////////////////////////////////////////////////////////////////////////
23 //
24 // TEXTINCLUDE
25 //
26
27 1 TEXTINCLUDE
28 BEGIN
29 " resource.h\0 "
30 END
31
32 2 TEXTINCLUDE
33 BEGIN
34 " #include "" afxres.h "" \r\n "
35 " \0 "
36 END
37
38 3 TEXTINCLUDE
39 BEGIN
40 " \r\n "
41 " \0 "
42 END
43
44 #endif // APSTUDIO_INVOKED
45
46
47 /**/ /////////////////////////////////////////////////////////////////////////////
48 //
49 // Dialog
50 //
51
52 IDD_GARAGE_DIALOG DIALOGEX 0 , 0 , 266 , 156
53 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
54 EXSTYLE WS_EX_APPWINDOW
55 CAPTION " OpenCV 摄像头 - 尝试 "
56 FONT 8 , " MS Shell Dlg " , 0 , 0 , 0x1
57 BEGIN
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
67 END
68
69
70 /**/ /////////////////////////////////////////////////////////////////////////////
71 //
72 // DESIGNINFO
73 //
74
75 #ifdef APSTUDIO_INVOKED
76 GUIDELINES DESIGNINFO
77 BEGIN
78 IDD_GARAGE_DIALOG, DIALOG
79 BEGIN
80 LEFTMARGIN, 7
81 RIGHTMARGIN, 259
82 TOPMARGIN, 7
83 BOTTOMMARGIN, 149
84 END
85 END
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
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)
19 LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
20
21 #ifdef APSTUDIO_INVOKED
22 /**/ /////////////////////////////////////////////////////////////////////////////
23 //
24 // TEXTINCLUDE
25 //
26
27 1 TEXTINCLUDE
28 BEGIN
29 " resource.h\0 "
30 END
31
32 2 TEXTINCLUDE
33 BEGIN
34 " #include "" afxres.h "" \r\n "
35 " \0 "
36 END
37
38 3 TEXTINCLUDE
39 BEGIN
40 " \r\n "
41 " \0 "
42 END
43
44 #endif // APSTUDIO_INVOKED
45
46
47 /**/ /////////////////////////////////////////////////////////////////////////////
48 //
49 // Dialog
50 //
51
52 IDD_GARAGE_DIALOG DIALOGEX 0 , 0 , 266 , 156
53 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
54 EXSTYLE WS_EX_APPWINDOW
55 CAPTION " OpenCV 摄像头 - 尝试 "
56 FONT 8 , " MS Shell Dlg " , 0 , 0 , 0x1
57 BEGIN
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
67 END
68
69
70 /**/ /////////////////////////////////////////////////////////////////////////////
71 //
72 // DESIGNINFO
73 //
74
75 #ifdef APSTUDIO_INVOKED
76 GUIDELINES DESIGNINFO
77 BEGIN
78 IDD_GARAGE_DIALOG, DIALOG
79 BEGIN
80 LEFTMARGIN, 7
81 RIGHTMARGIN, 259
82 TOPMARGIN, 7
83 BOTTOMMARGIN, 149
84 END
85 END
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