我正在使用MFC开发GUI,允许使用opencv显示视频。 GUI允许在GUI中自动调整控件的大小。它适用于视频显示。但是,视频打开时我有问题。当视频打开时,我无法单击该GUI中的任何控件或最小化按钮。我也无法在场景中单击或移动该GUI。如果我想关闭GUI,我必须在visual studio中Shift+ F5
。我的代码会发生什么。 youtube中显示了这个问题。我想将我的代码显示如下。感谢
void CDialogResizeDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
cv::VideoCapture cap(0);
//VideoCapture cap("C:/Users/lsf-admin/Pictures/Camera Roll/video000.mp4");
cv::vector<cv::Rect> faces;
cv::Mat frame;
cv::Mat graySacleFrame;
cv::Mat original;
if (!cap.isOpened())
{
return exit(1);
}
while (true)
{
cap >> frame;
if (!frame.empty()){
//clone from original frame
original = frame.clone();
}
CDC* vDC;
vDC = GetDlgItem(IDC_VIDEO)->GetDC();
CRect rect;
GetDlgItem(IDC_VIDEO)->GetClientRect(&rect);
IplImage* image2=cvCloneImage(&(IplImage)original);
DisplayIplImageToPictureBox(image2, vDC, rect); //img is IplImage* variable.
ReleaseDC(vDC);
if (cv::waitKey(30) >= 0) break;
}
}
您可以在here下载我的源代码(visual 2012+ opencv 2.4.10)
答案 0 :(得分:1)
您正在尝试在主应用程序主题中打开视频。这就是为什么您的Window消息处理(WindowProc()
)被阻止而GUI没有响应的原因。您应该在单独的帖子中打开视频。您可以使用AfxBeginThread()
来执行此操作。所以它不会阻止主应用程序线程。另外请不要致电exit(1);
如果您想要关闭GUI应用程序,请拨打WM_QUIT
消息:
::PostQuitMessage(0);
在您的情况下,我只会显示错误消息并返回:
if (!cap.isOpened())
{
AfxMessageBox(_T("Failed to load video file"));
return;
}
答案 1 :(得分:0)
感谢Andrew Komiagin建议解决问题的方法。让我看看我的实现。我希望它可以帮助某人
首先,您必须添加Dlg标头中定义的内容
public:
static UINT StartThread (LPVOID param);
//structure for passing to the controlling function
typedef struct THREADSTRUCT
{
CDialogResizeDlg* _this;
//you can add here other parameters you might be interested on
} THREADSTRUCT;
其次,您将线程功能中的视频显示写为
UINT CDialogResizeDlg::StartThread (LPVOID param)
{
THREADSTRUCT* ts = (THREADSTRUCT*)param;
//here is the time-consuming process
//which interacts with your dialog
AfxMessageBox ("Thread is started!");
// TODO: Add your control notification handler code here
cv::VideoCapture cap(0);
//VideoCapture cap("C:/Users/lsf-admin/Pictures/Camera Roll/video000.mp4");
cv::vector<cv::Rect> faces;
cv::Mat frame;
cv::Mat graySacleFrame;
cv::Mat original;
if (!cap.isOpened())
{
AfxMessageBox(_T("Failed to load video file"));
//return;
//return exit(1);
}
while (true)
{
cap >> frame;
if (!frame.empty()){
//clone from original frame
original = frame.clone();
}
CDC* vDC;
vDC =ts->_this->GetDlgItem(IDC_VIDEO)->GetDC();
CRect rect;
ts->_this->GetDlgItem(IDC_VIDEO)->GetClientRect(&rect);
IplImage* image2=cvCloneImage(&(IplImage)original);
ts->_this->DisplayIplImageToPictureBox(image2, vDC, rect); //img is IplImage* variable.
ts->_this->ReleaseDC(vDC);
if (cv::waitKey(30) >= 0) break;
}
//you can also call AfxEndThread() here
return 1;
}
Finnaly,你在onClick甚至
中调用上述函数void CDialogResizeDlg::OnBnClickedButton1()
{
THREADSTRUCT *_param = new THREADSTRUCT;
_param->_this = this;
AfxBeginThread (StartThread, _param);
}
现在有效。但是,它只能在1分钟内完成。之后,它有如下错误记忆问题
它image2
没有免费。您可以致电cvReleaseImage(&image2);
将其释放。
答案 2 :(得分:0)
为了不使用线程的小目的和快速结果:您可以在 mfc 项目中添加此功能。
bool peek_and_pump(void)
{
MSG msg;
#if defined(_AFX) || defined(_AFXDLL)
while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
if(!AfxGetApp()->PumpMessage())
{
::PostQuitMessage(0);
return false;
}
}
long lIdle = 0;
while(AfxGetApp()->OnIdle(lIdle++))
;
#else
if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
#endif
return true;
}
例如在 while(true){} 中调用此函数。
注意:使用此解决方案,您将在鼠标单击时停止循环。
但值得一试。