MFC对话框初始化时新建线程,调用OPENCV显示视频文件的问题。

我用VS2010新建一个MFC对话框。
新建3个全局变量:IplImage img;CvCapture capture; int m_flag=0。(m_flag用来退出线程。)
在对话框上插入一个图片控件IDC_PTC。

在对话框的初始化函数中插入如下代码

capture=cvCreateCameraCapture(0);
    if(!capture)
    {
        MessageBox(_T("打开摄像头失败!"));
    }
    else
    {
    m_flag=1;
        cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 800);
        cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 800);
        cvSetCaptureProperty(capture, CV_CAP_PROP_FPS, 5);
        HANDLE hThread;
        hThread=CreateThread(NULL,0,FunProc1,(LPVOID)this,0,NULL);
        CloseHandle(hThread);
    }

线程函数如下:

 DWORD WINAPI CtestDlg::FunProc1(LPVOID lp)
{
    CtestDlg* dlg=(CtestDlg*)lp;
    CWnd* wnd=(CWnd*)lp;

    CClientDC dc(wnd&&m_flag);
    RECT rect;
    (wnd->GetDlgItem(IDC_PTC))->GetWindowRect(&rect);
    wnd->ScreenToClient(&rect);
    img=cvQueryFrame(capture);
    CvvImage cvImg;
    while(img&&m_flag)
    {
        cvImg.CopyOf(img);
        cvImg.DrawToHDC(dc,&rect);
        img=cvQueryFrame(capture);
    }
    cvImg.Destroy();
    return 1;
}

那么问题来了:
这样在线程函数开头插入断点"调试运行"对话框显示时就可以看到相机实时采集图像显示在图片控件内。
但是如果直接点“开始执行(不调试)”,目前所知有2种情况:
1、用USB接口相机,图片控件上不显示相机采集的视频。
2、用笔记本自带相机,图片控件上显示相机采集的视频。
这是为什么?还有下面2个问题如下:
3、“调试运行”对话框按正常流程退出。“开始执行(不调试)”对话框时不时的不正常退出(任务管理器可以看到程序在后台运行)。
4、如果把创建线程的函数放入到一个按钮里面,那么2个相机采集的视频都可以正常显示在图片控件里面。
望大神解答一下上面的疑问,我是自己没事自学的,没什么水平。

4个回答

你线程中不要更新界面 而是发送消息主线程 让它来更新界面元素等

hn1smm
初级_学徒 刚才我又在这个程序的基础上加了一个LBUTTONDOWN处理函数,结果又有问题了。加入这个函数后,在编译界面,程序会处理LBUTTONDOWN函数,但是不显示视频。如果直接点击DEBUG模式编译好的可执行文件,会显示视频,但是不处理LBUTTONDOWN消息。真是奇怪额。
3 年多之前 回复
hn1smm
初级_学徒 大神,我试了,让子线程发送消息,主线程处理接受的消息,这种办法在我这个问题上是可行的。但是我还是不太理解其中的原因,望解答。先谢过了。
3 年多之前 回复
oyljerry
oyljerry 回复初级_学徒: 对,发消息给主线程重绘窗口
3 年多之前 回复
hn1smm
初级_学徒 能说一下具体点吗?是发送一个消息给主线程,通知主线程重绘窗口吗?能说具体点吗?我试过在while里调用对话框的onpain函数,结果还是一样。并且显示视频时闪的厉害。我昨天在线程函数进去点休眠2秒就可以了,不过休眠时间短了就不行。不知道为啥。另外初始化时插入定时器去创建线程也不行。
3 年多之前 回复

就是picture控件显示
用USB接口相机 用笔记本自带相机对应的调用接口是不同的
如(网上随便找的代码)
#include "stdafx.h"

#include

#include

#include

int main( int argc, char** argv )

{

//声明IplImage指针

IplImage* pFrame = NULL;

CvCapture* pCapture = cvCreateCameraCapture(-1);

cvNamedWindow("video", 1);

while(1)

{

pFrame=cvQueryFrame( pCapture );

if(!pFrame)break;

cvShowImage("video",pFrame);

char c=cvWaitKey(33);

if(c==27)break;

}

cvReleaseCapture(&pCapture);

cvDestroyWindow("video");

}

这段里面cvCreateCameraCapture后面的数字就是不同的相机 一般为 0 1 -1

hn1smm
初级_学徒 这个我知道,我的0代表被笔记本摄像头。1代表USB摄像头。这个我调试的时候改了摄像头ID的。我昨天也测试出来,进入线程函数如果让线程休眠2秒,当线程再运行时就会显示除相机采集的图片了。
3 年多之前 回复

上面代码有个错误 CClientDC dc(wnd&&m_flag); 这句后面的&&m_flag是多余的。我贴错了。不好意思。

主线程重绘窗口,与在子线程力调用主窗口DC重画主窗口区域有什么不同?望指点,谢谢啊。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问