opencv在MFC中的使用
MFC通过opencv显示摄像头
开摄像头的按钮,一个关闭摄像头的按钮。
有一个PictureBox的控件。
1.CvCapture* capture;2.CRect rect;3.CDC *pDC;4.HDC hDC;5.CWnd *pwnd;这里特别注意,这些变量一定要是全局变量。
再来看一下这些变量的添加位置:[cpp]view plaincopyprint?1.#include "stdafx.h"2.#include "VideoMFC.h"3.#include "VideoMFCDlg.h"4.#include "afxdialogex.h"5.6.#ifdef _DEBUG7.#define new DEBUG_NEW8.#endif9.10.11.CvCapture* capture;12.CRect rect;13.CDC *pDC;14.HDC hDC;15.CWnd *pwnd;16.17.// CAboutDlg dialog used for App About18.19.class CAboutDlg : public CDialogEx20.{21.public:然后在窗口的初始化函数中进行句柄的初始化:[cpp]view plaincopyprint?1.OnInitDialog()这个函数,BOOL CVideoMFCDlg::OnInitDialog()初始化代码:[cpp]view plaincopyprint?1.// CVideoMFCDlg message handlers2.3.BOOL CVideoMFCDlg::OnInitDialog()4.{5. CDialogEx::OnInitDialog();6.7. // Add "About..." menu item to system menu.8.9. // IDM_ABOUTBOX must be in the system command range.10. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);11. ASSERT(IDM_ABOUTBOX < 0xF000);12.13. CMenu* pSysMenu = GetSystemMenu(FALSE);14. if (pSysMenu != NULL)15. {16.BOOL bNameValid;17. CString strAboutMenu;18. bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);19. ASSERT(bNameValid);20. if (!strAboutMenu.IsEmpty())21. {22. pSysMenu->AppendMenu(MF_SEPARATOR);23. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);24. }25. }26.27.28. // Set the icon for this dialog. The framework does this automatically29. // when the application's main window is not a dialog30. SetIcon(m_hIcon, TRUE); // Set big icon31. SetIcon(m_hIcon, FALSE); // Set small icon32.33. // TODO: Add extra initialization here34. pwnd = GetDlgItem(IDC_ShowImage);35. //pwnd->MoveWindow(35,30,352,288);36. pDC =pwnd->GetDC();37. //pDC =GetDC();38. hDC= pDC->GetSafeHdc();39. pwnd->GetClientRect(&rect);40.41.42.43. return TRUE; // return TRUE unless you set the focus to a control44.}这里的初始化代码只有Todo后面的是自己添加的,目的是获得图像控件的句柄,将来好在上面显示图像。
VS 2010在MFC中用opencv实现对视频中动态目标的追踪
Visual Studio2010在MFC中用opencv实现对视频中动态目标的追踪第二步,建立一个MFC的对话框程序,做两个按钮,一个“打开视频文件”,一个“运动跟踪处理”。
具体操作:1 建立MFC对话框程序的框架:File ->New -> MFC AppWizard(exe),选取工程路径,并取工程名“VideoProcesssing”-> Next -> 选择Dialog based后,去掉使用Unicode库的勾,选择在静态库中使用 MFC,点Finish,点OK.2 添加按钮:直接Delete掉界面默认的两个“确定”“取消”按钮。
然后添加两个button,分别名为“打开视频”,“运动跟踪处理”,其ID分别设为IDC_OPEN_VIDEO,IDC_TRACKING.3 添加消息响应函数:双击按钮“打开视频文件”,自动生成响应函数名OnOpenVideo,点Ok。
然后添加如下代码:CFileDialog dlg(true,"*.avi",NULL,NULL,"*.avi|*.avi||");if (dlg.DoModal()==IDOK){strAviFilePath = dlg.GetPathName();}else{return;}同样,双击“运动跟踪处理”按钮,选择默认的响应函数名,然后添加代码://声明IplImage指针IplImage* pFrame = NULL;IplImage* pFrImg = NULL;IplImage* pBkImg = NULL;CvMat* pFrameMat = NULL;CvMat* pFrMat = NULL;CvMat* pBkMat = NULL;CvCapture* pCapture = NULL;int nFrmNum = 0;//打开AVI视频文件if(strAviFilePath=="") //判断文件路径是否为空{MessageBox("请先选择AVI视频文件!");return;}else{if(!(pCapture = cvCaptureFromFile(strAviFilePath))) {MessageBox("打开AVI视频文件失败!");return;}}//创建窗口cvNamedWindow("Video", 1);cvNamedWindow("Background",1);cvNamedWindow("Foreground",1);//使窗口有序排列,窗口宽330cvMoveWindow("Video", 30, 0);cvMoveWindow("Background", 360, 0);cvMoveWindow("Foreground", 690, 0);//逐帧读取视频while(pFrame = cvQueryFrame( pCapture )){nFrmNum++;//如果是第一帧,需要申请内存,并初始化if(nFrmNum == 1){pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放背景图像(灰度)pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放中间图像(灰度)pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);//转化成单通道图像再处理(灰度)cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);cvConvert(pFrImg, pFrameMat);cvConvert(pFrImg, pFrMat);cvConvert(pFrImg, pBkMat);}else{cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY); //转化成单通道图像再处理(灰度)cvConvert(pFrImg, pFrameMat);//高斯滤波先,以平滑图像//cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);//当前帧跟背景图相减(求背景差并取绝对值)cvAbsDiff(pFrameMat, pBkMat, pFrMat);//二值化前景图(这里采用特定阈值进行二值化)cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);//进行形态学滤波,去掉噪音cvErode(pFrImg, pFrImg, 0, 1);cvDilate(pFrImg, pFrImg, 0, 1);//滑动平均更新背景(求平均)cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);//将背景转化为图像格式,用以显示cvConvert(pBkMat, pBkImg);// 保持原图像的旋转方向pBkImg->origin = pFrImg->origin = pFrame->origin;//显示图像cvShowImage("Video", pFrame);cvShowImage("Background", pBkImg);cvShowImage("Foreground", pFrImg);//如果有按键事件,则跳出循环//此等待也为cvShowImage函数提供时间完成显示//等待时间可以根据CPU速度调整if( cvWaitKey(200) >= 0 )break;}}//销毁窗口cvDestroyWindow("Video");cvDestroyWindow("Background");cvDestroyWindow("Foreground");//释放图像和矩阵cvReleaseImage(&pFrImg);cvReleaseImage(&pBkImg);cvReleaseMat(&pFrameMat);cvReleaseMat(&pFrMat);cvReleaseMat(&pBkMat);cvReleaseCapture(&pCapture);4 选fileview选项卡中VideoProcessingDlg.h,在CVideoProcessingDlg类中添加公有类成员:CString strAviFilePath;5 选fileview选项卡中VideoProcessingDlg.cpp,添加opencv头文件#include "cv.h"#include "highgui.h"#include "cxcore.h"6 编译执行,成功!还可以添加一个”录制视频”的按钮,修改ID号为IDC_RECORD,双击“录制视频”按钮,选择默认的响应函数名,然后添加代码:CvCapture* capture=cvCaptureFromCAM(-1); //打开摄像头CvVideoWriter* video=NULL;IplImage* frame=NULL;int n;if(!capture) //如果不能打开摄像头给出警告{cout<<"Can not open the camera."<<endl;return ;}else{frame=cvQueryFrame(capture); //首先取得摄像头中的一帧video=cvCreateVideoWriter("camera.avi", CV_FOURCC('X', 'V', 'I', 'D'), 25,cvSize(frame->width,frame->height)); //创建CvVideoWriter对象并分配空间//保存的文件名为camera.avi,编码要在运行程序时选择,大小就是摄像头视频的大小,帧频率是32if(video) //如果能创建CvVideoWriter对象则表明成功{cout<<"VideoWriter has created."<<endl;}cvNamedWindow("Camera Video",1); //新建一个窗口int i = 0;while(i <= 200) // 让它循环200次自动停止录取{frame=cvQueryFrame(capture); //从CvCapture中获得一帧if(!frame){cout<<"Can not get frame from the capture."<<endl;break;}n=cvWriteFrame(video,frame); //判断是否写入成功,如果返回的是1,表示写入成功cout<<n<<endl;cvShowImage("Camera Video",frame); //显示视频内容的图片i++;if(cvWaitKey(2)>0)break; //有其他键盘响应,则退出}cvReleaseVideoWriter(&video);cvReleaseCapture(&capture);cvDestroyWindow("Camera Video");}return ;第二步,建立一个编程环境,然后加载opencv的库路径等等。
MFC中opencv读取显示图片
openCV读取、显示、处理图像比较方便,但是整体界面设计以及鼠标、键盘事件响应比较弱。
将MFC这方面的功能和openCV结合起来。
在openCV的C++接口中(2.2及以后),图像都用cv::Mat存储,但是可以使用openCV 已经做好的重载运算符直接转为C版本openCV的图像类型IplImage:cv::Mat mat;IplImage img = mat;而且在上述过程中没有数据拷贝,只是新建了一个IplImage文件头。
创建一个Dialog-Based的MFC窗口作为例子,添加一个Picture Control空间,将其ID修改为IDC_RENDER。
在MFC界面中添加一个按钮用来打开文件窗口选择载入的图片(这比较简单,就不细说了);读取图片当然用的是opencv的接口了。
使用openCV的cv::Mat 读取图片之后,需要在picture control控件中将图片显示出来。
其过程是这样的:将cv::Mat 转换格式为IplImage,然后将IplImage 转换格式为CvvImage,因为CvvImage 类中有函数DrawToHDC(),可以直接完成MFC空间中的绘图。
问题是:在openCV2.2以后,这个类CvvImage 被删掉了。
解决办法,参考一些遇到相同问题的人在论坛里的讨论(网址),将CvvImage 的定义单独抠出来组成.cpp和.h。
问题解决。
最后读取并显示图片的MFC 按钮空间的反馈函数为:// load imagevoid CpicUIDlg::OnBnClickedLoadimage() {string tstring;CString tFileName;CFileDialog tDlg(TRUE);if(tDlg.DoModal() == IDOK) {tFileName = tDlg.GetPathName();tstring = tFileName.GetBuffer(0);}mat = cv::imread(tstring, 1);if(! mat.data) {MessageBox("error", "no image loaded!", MB_OK);return;}CDC* pDC = GetDlgItem(IDC_RENDER)->GetDC();HDC hDC = pDC->GetSafeHdc();IplImage img = mat;CvvImage cimg;cimg.CopyOf( &img );CRect rect;GetDlgItem(IDC_RENDER)->GetClientRect(&rect);cimg.DrawToHDC(hDC, &rect);ReleaseDC( pDC );}CvvImage.cpp和CvvImage.h,参见上面链接的openCV论坛帖子。
基于mfc的opencv中resize
基于mfc的opencv中resize1.引言1.1 概述概述:本文主要介绍基于MFC的OpenCV中Resize的实现原理及其在图像处理中的应用。
首先,我们将简要介绍MFC框架和OpenCV库,包括它们的基本概念和主要功能。
然后,我们将重点探讨Resize函数的原理,该函数是OpenCV库中一个重要的图像缩放函数,可以实现图像的大小调整。
最后,我们将详细介绍如何在基于MFC的应用程序中使用OpenCV 库实现Resize功能,并给出实际代码示例。
通过本文的学习,读者将能够更深入地了解MFC框架和OpenCV库的结合应用,以及如何使用Resize函数对图像进行处理和调整。
在文章的结尾,我们将对本文进行总结,并展望Resize函数在未来的发展和应用前景。
1.2 文章结构文章结构部分主要是对整篇文章进行简要的介绍和概括,包括各个章节的主要内容和组织结构。
在本篇文章中,文章结构可以按照以下方式进行描述:本文主要通过以下几个章节来介绍基于MFC的OpenCV中resize的实现。
第一章是引言部分,概述了文章的研究背景和重要性。
首先介绍了基于MFC的OpenCV中resize的需求和应用场景,然后对文章的结构和内容进行了简单的介绍,最后明确了本文的目的和主要贡献。
第二章是正文部分,主要分为四个小节。
首先是MFC介绍,介绍了MFC的基本概念和用途,以及MFC在图像处理中的应用。
接着是OpenCV 介绍,对OpenCV进行了简要的介绍,包括OpenCV的基本功能和使用方式。
然后是Resize函数原理,对Resize函数的工作原理进行了详细的解释和说明。
最后是基于MFC的OpenCV中resize的实现,详细介绍了基于MFC框架下如何实现resize功能,包括代码示例和实际应用。
第三章是结论部分,主要总结了本文的研究内容和结果,回顾了本文的主要贡献和创新点。
同时,也对基于MFC的OpenCV中resize功能进行了展望,提出了一些待解决的问题和可能的改进方向。
MFC中应用OpenCV教程
在MFC框架快速应用OpenCV版本1,作者:ollydg23日期:11/29/08Contents1创建SDI工程1 2加入OpenCV库支持2 3在Doc类中添加变量3 4添加虚函数3 5View类中添加显示图片代码4 6感谢和后记51创建SDI工程我使用的是Visual C++ 6.0,因此,本教程描述的是在VC6上面演示操作,如果您使用别的版本的VC,我想应该也差不多。
首先,按照VC的向导,产生一个默认的MFC的工程,注意,选择SDI单文档支持的,同时最好选择“use MFC As a static library”1。
1以避免一些MFC中的memory leak的问题1Figure1:VC向导,选择MFC APPWizardFigure2:VC向导,选择single document 就这样子一路下去之后,基本的MFC框架就创建完成了。
2加入OpenCV库支持现在加入openCV必须的头文件和库文件。
如下图所示,我们添加库文件:cxcore.lib cv.lib highgui.lib2Figure3:添加lib文件3在Doc类中添加变量Figure4:加入变量m image并且在开头加上HighGui.h的头文件包含,同时添加一个变量“CImage m image;”。
4添加虚函数添加两个函数,分别用来打开图片文件和保存图片文件,添加过程见下图的右键菜单。
3Figure5:右键添加虚函数如上图所示,添加虚函数,分别添加:Algorithm1打开文件BOOL CSDI OpenCVDoc::OnOpenDocument(LPCTSTR lpszPathName){ if(!CDocument::OnOpenDocument(lpszPathName))return FALSE;//TODO:Add your specialized creation code herem image.Load(lpszPathName);return TRUE;}Algorithm2保存文件BOOL CSDI OpenCVDoc::OnSaveDocument(LPCTSTR lpszPathName){ //TODO:Add your specialized code here and/orcall the base classm image.Save(lpszPathName);return CDocument::OnSaveDocument(lpszPathName);}5View类中添加显示图片代码在View类中间添加必要的图片显示代码,主要是在Ondraw里面。
MFC:CImage显示OpenCV:Mat矩阵图像
MFC:CImage显示OpenCV:Mat矩阵图像自从开始学C++的OpenCV,就想把问题都用一个简单的类来解决。
原来使用VC6.0使用的是StretchDIBits这类函数来画图,一旦画新的图像或者显示多张位图,势必遇到多次对环境的调色板重新加载。
如今都已经VS2010,MFC下的图像显示功能有所加强。
使用MFC下的CImage类(貌似VC2005开始支持)可以很轻松的和快速的在MFC 下显示图像;(到底是不是很快速还需要更多的考证,但把已经存在的Mat矩阵lena图像显示出来,使用getTimeGet函数测得,貌似低于1ms)。
由于网上太多杂乱的内容和很多不够详细的讲解,让我尝试了一天,才把彩色和灰度图像正确显示到界面上。
我这里使用C++的OpenCV,如果你使用c语言的OpenCV一样可以实现出来。
1.读入Mat矩阵(cvMat一样),Mat img=imread("*.*");//cvLoadImage确保转换前矩阵中的数据都是uchar(0~255)类型(不是的话量化到此区间),这样才能显示。
(初学者,包括我经常忘了此事)2.根据矩阵大小创建(CImage::Create)新的的CImage类CImage CI;int w=img.cols;//宽int h=img.rows;//高int chinnels=img.channels();//通道数CI.Destroy();//创建前,最好使用它,防止重复创建,程序崩溃CI.Create(w,h,8*chinnels);3.下来就是对CI进行赋值了,这里是最核心的地方,分二类讨论(1)如果是1个通道的图像(灰度图像)CImage中内置了调色板,我们要对他进行赋值:RGBQUAD* ColorT able;int MaxColors=256;//这里可以通过CI.GetMaxColorTableEntries()得到大小(如果你是CI.Load读入图像的话)ColorTable = new RGBQUAD[MaxColors];CI.GetColorTable(0,MaxColors,ColorT able);//这里是取得指针for (int i=0; i<MaxColors; i++){ColorTable.rgbBlue = (BYTE)i;//BYTE和uchar一回事,但MFC中都用它ColorTable.rgbGreen = (BYTE)i;ColorTable.rgbRed = (BYTE)i;}CI.SetColorTable(0,MaxColors,ColorTable);delete []ColorTable;然后就是数据拷贝了(这里的矩阵表示方法,根据需要(cvMat or Mat)修改):if(chinnels==1){//灰度图像uchar *pS;uchar *pImg=(uchar *)CI.GetBits();int step=CI.GetPitch();for(int i=0;i<h;i++){pS=img.ptr<uchar>(i);for(int j=0;j<w;j++){*(pImg+i*step+j)=pS[j];}}}(2)如果是3个通道(彩色图像)没有调色板,直接赋值if(chinnels==3){//彩色图像uchar *pS;uchar *pImg=(uchar *)CI.GetBits();//得到CImage数据区地址int step=CI.GetPitch();//这个是一行像素站的存储空间w*3,并且结果是4的倍数(这个不用关注,到底是不是4的倍数有待考证)for(int i=0;i<h;i++){pS=img.ptr<uchar>(i);for(int j=0;j<w;j++){for(int k=0;k<3;k++)*(pImg+i*step+j*3+k)=pS[j*3+k];//注意到这里的step不用乘以3}}}4.至此已经构建好CImage,下来就是显示它。
MFC中使用OpenCV捕捉摄像头视频并在Image控件中播放
在参加腾讯校园之星大赛中做了一些手势识别的插件,其中需要使用OpenCV相关的东西,今天将它整理一下,希望对其他人能有所帮助。
首先,OpenCV 2.1似乎不能获取设想设备的数目,名称以及其它相关属性,在实际应用中很不方便,为了解决这个问题,OpenCV论坛上YuShiQi老师给出了一个风转好的CameraDS类,通过Directshow来调用摄像头(详情请见/index.php/使用DirectShow采集图像),不过,这个类只在VC++6.0编译下通过,对于VS2005、2008和2010,需要做相应的设置,如下:1、在CameraDS.h包含头文件之上预先定义加入如下代码#define POINTER_64 __ptr642、将project ->Property-> c++ ->general->Additional Include Directories 的DirectShow/Include挪到tools->options->project and solutions->vc++ Directories->include files的文件末尾就可以了,当然也可以换成绝对目录。
问题解决后,就可以在vs2005,vs2008上编译该工程了其次,捕捉到了视频,还需要将它显示在Image控件上,这里就没有OpenCV自身所使用的UI控件那么方便了,需要自己定义Timer函数来重复调用,过程如下://打开该摄像头之前,因先检查之前是否在进行图像捕捉,若有,关闭ReleaseCapture();//打开摄像头if(!camera.OpenCamera(sgCurSelCameraIndex,false,FRAME_WIDTH,FRAME_HEI GHT))//这里使用CameraDS中的方法打开摄像头{MessageBox(_T("打开视频设备"+sgCameraName+"失败,请检查设备状态"),_T("SmartGesture插件信息"), MB_OK | MB_ICONEXCLAMATION); }SetTimer(status,30,NULL);//关键是这里,需要自己定义Timer函数去反复读取图像并将它显示出来,处理的代码会在OnTimer函数中出现SetTimer函数第一个参数是Timer的标识ID,也就是下面出现的nIDEvent。
MFC下利用OpenCV进行人脸检测的研究与实现
中很多繁琐的计算 , 如全部靠程序员手动编写, 工 作量 非 常 大 . 本 文 设 计 的 系 统 采 用 了 C+ +中 的 O p e n C V计算机 视觉 函数库 中的一 些 函数. 并 以 V i s u a l C++ 6 . 0作为 开发 环境 .
难题是 : 采取合适恰 当的方法从众多的 H a a r 特征 中筛选出最优 的 H a a r 特征 , 并利用该特征制作成 人脸检测中所使用的分类器.
A d a b os t 算法是通过 b o o s t i n g算 法 改 进 而 来 的 ¨, b o o s t i n g算 法 是 一 种 通 用 的 学 习算 法 , 这
一
训练很多人脸数据 , 本文 采用从 网上下载 的 Y l a e 大 学 的人 脸数 据库 , 即将它 们 当做训 练 的正样 本使
其思 想 源 于 1 9 8 4年 V l a i a n t 提出 的“ 可 能 近 似 正
确” 一 P C A ( P r o b a b l y A p p r o x i m a t e l y C o r r e c t ) 学习模
① 收稿 日期 : 2 0 1 3—1 0—1 8 .
高的准 确性和稳 定性 , 基 本 达到预 期 的效 果.
关键 词 : A d a B o o s t ; 人 脸检 测 ; O p e n C V; MF C 中图分类 号 : T P 3 9 1 . 4 文献标 识码 : A
O 引 言
人脸检测的 目的是 在给定 的一副图像上将人
用. 该人脸数据库是 由 Y l a e大 学 的计 算 视 觉 与控
算法可 以提升任意 给定 的学 习算 法 的性 能 引,
opencv在MFC中的使用
opencv在MFC中的使⽤OpenCV 在MFC中的⼀些基本使⽤⽅法在《OpenCV教程-基础篇》的中,所创建的MFC图像显⽰是直接放在对话框⾯板的左上⾓的,感觉不⼤美观;《MFC 中快速应⽤OpenCV》则是介绍⽤SDI(单⽂档界⾯)来显⽰图像,《A step-by-step guide to the use of Microsoft Visual C++ and the Intel OpenCV library》使⽤VS2005来进⾏图像和视频的读取和处理,但是其图像和视频的显⽰界⾯不是在对话框⾥⾯的,⽽是新建⼀个窗⼝来做。
所以下⾯我们就来看看怎么在对话框⾥使⽤Picture控件来显⽰和处理图像。
⼀、创建MFC⾸先创建⼀个MFC对话框应⽤程序(Dialog-based Application)如下:在VS2005和2008⾥,我们可以⽤⼀个Solution 来组合⼏个Project (每个Project 基本上只包含⼀个Program),当我们要构建⼀个多Program的应⽤时(例如⼀个客户端程序加⼀个服务器应⽤程序),利⽤Solution 可以将这些Projects 组合起来、并且共享⽂件和函数库。
通常需要为Solution创建⼀个主路径,其中包含了所有Projects的路径。
不过在这篇⽂章⾥,我们只构建⼀个简单的Project,所以在创建MFC的New Project对话框⾥,不⽤勾选“Create directory for solution”这个选项。
点击OK -- Next进⼊下⼀步,在这⾥我们创建⼀个Dialog-based Application,⼤部分选项按默认设置就⾏,不过最下⾯的“Use Unicode libraries”最好去掉。
如果勾选了这个选项,程序代码就会使⽤16bit的Unicode字符集来编码,但是很多函数虽然使⽤char* (ASCII stings) 类型字符,⽽将字符串从Unicode 转换到ASCII 是⾮常⿇烦的。
MFC结合OPENCV图像处理例子
利用MFC结合OPENCV进行图像处理
对于学习图像处理的朋友们,OPENCV库函数可以帮助大家方便快捷地进行一些通用的图像处理工作,使得人们能够把精力放在自己的算法编程上面。
而MFC则可以帮助我们大大减少一些编程方面的工作。
所以,在MFC框架上利用OPENCV解决图像处理方面的问题是一个很好的选择。
下面通过一个简单的例子来说明如何在MFC里采用OPENCV库函数进行图像处理。
1.新建一个MFC AppWizard(exe)工程,取名test
这里,建立的是基本对话框。
建立完成之后,取消预编译头文件
2.在VC++6.0上添加OPENCV库函数
具体的在VC++6.0上怎么使用OPENCV,网上已经有大量的参考例子。
这里就简单的介绍一下要添加的函数库。
一般只是使用到OPENCV里面的cv.lib,cxcore.lib,highgui.lib库,所以本工程只是将这三个库添加到工程里面
3.往对话框里添加3个按钮,并修改按钮名字
4.分别给三个按钮添加消息处理函数,双击按钮确定即可添加。
然后,可以在按钮消息函数中添加自己的代码,实现具体功能。
按钮一是“显示原图”按钮,功能是打开一副指定的图像。
为了能使用OPENCV库函数,还要添加相应头文件
编译连接无误之后,点击“显示原图”按钮,运行结果如下
同样,在另外两个按钮消息函数中编辑自己的程序
运行后,分别点击三个按钮,整个程序的运行如下。
openCV——在MFC中使用openCV
#include "cv.h"
#include "highgui.h" #pragma comment( lib, "cv200.lib" ) #pragma comment( lib, "ccxcore200.lib" ) #pragma comment( lib, "highgui200.lib" ) #pragma comment( lib, "cvaux200.lib" )
{ viewimgdata(); CDialog::OnPaint();
}
//自定义函数
void viewimgdata()
{ CPaintDC dc(this); CDC* pdc = &dc; int res = StretchDIBits( pdc->GetSafeHdc(),//句柄 0,//目的 0, int(256), int(256),
(char)(w/dx); }
} } else if (theimage->nChannels == 3) //对 RGB 图像 {
IplImage* temp = cvCreateImage(imgsize,IPL_DEPTH_8U,1);
int h,w; float dx = temp->width/256.0f; for (w= 0; w<temp->width;w++) {
edge,//单通道存储边缘的输出图像 30,//第一阀值 100,//第二阀值 3 //Sobel 算子内核大小 );//注意:cvCanny 只接受单通道图像作为输入(有人写了自适应阀值 函数,可以参考) cvSetImageCOI(img,0);//这可能是个 bug,添加此句修改通道设置 cvCvtColor(edge,img,CV_GRAY2RGB); //保存结果 cvCopyImage(img,m_ipl);//各种条件一致,复制才不会出错 cvReleaseImage(&gray); cvReleaseImage(&edge);
opencv+MFC图像处理界面设计与实现
opencv+MFC图像处理界⾯设计与实现数字图像处理作业⽤opencv + MFC图像处理界⾯设计与实现,点击按钮(Button)在Picture Control上显⽰处理前后的对⽐图像vs2015+opencv2.4.13.6 实现运⾏// ImageprocessingDlg.cpp : 实现⽂件//#include "stdafx.h"#include "Imageprocessing.h"#include "ImageprocessingDlg.h"#include "afxdialogex.h"#include<opencv2/opencv.hpp>#include <iostream>#include <fstream>using namespace cv;using namespace std;Mat src,gray, equalized;void drawEndPoints(const Mat& maskImg, Mat &dstImg);Mat thinning(const Mat &binaryImg);Mat findCorners(const Mat &inImg);void drawCircles(const Mat& maskImg, Mat &dstImg);double iterativeThreshold(const Mat &grayImg);double otsuThreshold(const Mat &grayImg);double pTileThreshold(const Mat &grayImg, double objRatio);/// 分块⾃适应阈值分割void blockAdaptiveThreshold(const Mat &srcImg, Mat& dstImg, Size blockSize = Size(64, 64));void writetxt(int num);#ifdef _DEBUG#define new DEBUG_NEW#endif// ⽤于应⽤程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{CAboutDlg();// 对话框数据#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };#endifprotected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV ⽀持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CImageprocessingDlg 对话框CImageprocessingDlg::CImageprocessingDlg(CWnd* pParent /*=NULL*/): CDialogEx(IDD_IMAGEPROCESSING_DIALOG, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CImageprocessingDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_COMBO1_GRAYMORPHOLOGY, cbBox1);DDX_Control(pDX, IDC_COMBO1_Hough, cbBox2);}BEGIN_MESSAGE_MAP(CImageprocessingDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1_OPENIMG, &CImageprocessingDlg::OnBnClickedButton1Openimg)ON_BN_CLICKED(IDC_BUTTON2_CLOSEIMG, &CImageprocessingDlg::OnBnClickedButton2Closeimg)ON_BN_CLICKED(IDC_BUTTON1_2GRAY, &CImageprocessingDlg::OnBnClickedButton12gray)ON_BN_CLICKED(IDC_BUTTON2_2EQUA, &CImageprocessingDlg::OnBnClickedButton22equa)ON_BN_CLICKED(IDC_BUTTON3_GRAYHIST, &CImageprocessingDlg::OnBnClickedButton3Grayhist)ON_BN_CLICKED(IDC_BUTTON4_EQUAHIST, &CImageprocessingDlg::OnBnClickedButton4Equahist)ON_BN_CLICKED(IDC_BUTTON5_AVERFILTER, &CImageprocessingDlg::OnBnClickedButton5Averfilter)ON_BN_CLICKED(IDC_BUTTON6_MEDIANBLUR, &CImageprocessingDlg::OnBnClickedButton6Medianblur) ON_BN_CLICKED(IDC_BUTTON7_GAUSSBLUR, &CImageprocessingDlg::OnBnClickedButton7Gaussblur) ON_BN_CLICKED(IDC_BUTTON8_SOBEL, &CImageprocessingDlg::OnBnClickedButton8Sobel)ON_BN_CLICKED(IDC_BUTTON9_Laplacian, &CImageprocessingDlg::OnBnClickedButton9Laplacian)ON_BN_CLICKED(IDC_BUTTON10_CANNY, &CImageprocessingDlg::OnBnClickedButton10Canny)ON_BN_CLICKED(IDC_BUTTON1_RESIZE, &CImageprocessingDlg::OnBnClickedButton1Resize)ON_BN_CLICKED(IDC_BUTTON2_MOVE, &CImageprocessingDlg::OnBnClickedButton2Move)ON_BN_CLICKED(IDC_BUTTON3_FLIP, &CImageprocessingDlg::OnBnClickedButton3Flip)ON_BN_CLICKED(IDC_BUTTON4_ROTATE, &CImageprocessingDlg::OnBnClickedButton4Rotate)ON_BN_CLICKED(IDC_BUTTON6_DCT, &CImageprocessingDlg::OnBnClickedButton6Dct)ON_BN_CLICKED(IDC_BUTTON7_ERODE, &CImageprocessingDlg::OnBnClickedButton7Erode)ON_BN_CLICKED(IDC_BUTTON8_DLIATE, &CImageprocessingDlg::OnBnClickedButton8Dliate)ON_BN_CLICKED(IDC_BUTTON9_OPEN, &CImageprocessingDlg::OnBnClickedButton9Open)ON_BN_CLICKED(IDC_BUTTON10_CLOSE, &CImageprocessingDlg::OnBnClickedButton10Close)ON_BN_CLICKED(IDC_BUTTON11_FINDENDPOINT, &CImageprocessingDlg::OnBnClickedButton11Findendpoint)ON_CBN_SELCHANGE(IDC_COMBO1_GRAYMORPHOLOGY, &CImageprocessingDlg::OnCbnSelchangeCombo1Graymorphology) ON_BN_CLICKED(IDC_BUTTON4_THIN, &CImageprocessingDlg::OnBnClickedButton4Thin)ON_BN_CLICKED(IDC_BUTTON5_FINDCORNERS, &CImageprocessingDlg::OnBnClickedButton5Findcorners)ON_BN_CLICKED(IDC_BUTTON1_ITERATIVE, &CImageprocessingDlg::OnBnClickedButton1Iterative)ON_BN_CLICKED(IDC_BUTTON2_OTSU, &CImageprocessingDlg::OnBnClickedButton2Otsu)ON_BN_CLICKED(IDC_BUTTON3_PTILEThreshold, &CImageprocessingDlg::OnBnClickedButton3Ptilethreshold)ON_BN_CLICKED(IDC_BUTTON4_blockAdaptiveThreshold, &CImageprocessingDlg::OnBnClickedButton4blockadaptivethreshold)ON_CBN_SELCHANGE(IDC_COMBO1_Hough, &CImageprocessingDlg::OnCbnSelchangeCombo1Hough)ON_BN_CLICKED(IDC_BUTTON8_RegionLabel, &CImageprocessingDlg::OnBnClickedButton8Regionlabel)ON_BN_CLICKED(IDC_BUTTON1_AutoMarkerWatershed, &CImageprocessingDlg::OnBnClickedButton1Automarkerwatershed)ON_WM_CLOSE()END_MESSAGE_MAP()// CImageprocessingDlg 消息处理程序BOOL CImageprocessingDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。
在单文档中使用opencv打开影像
继承opencv的CImage类在MFC的单文档中编辑并显示图像在opencv中显示一个图像简单,但是想在MFC的单文档框架中可不是件容易的,好在opencv 提供了CImage类可以简化这一工作,但是还是碰到了些问题,如如何装IplImage*图像放入CImage类的成员变量中.CImage类封装了图像打开\保存\获取\等方法,并将图像保存在一个protected的图像成员变量里.虽然也提供了CopeOf来装入图像,但是由于类型转换的问题,总是出错.解决方法:以CImage为基类自定义一个类:1.从论坛上看到一哥们使用的方法是在自定义的类的构造函数中修改CImage的protected的图像成员变量,如下:myimg::myimg(IplImage* img) : CvvImage(){m_img=cvCloneImage(img);}调试时发现无法在MFC的xxxxDoc.h中定义新类myimg的对像,错误是构造函数不正确,也可能是自己MFC水平太差^_^(请大家提意见).2.自己的解决办法是,以CImage为基类自定义一个类如下://class声明文件#include "stdafx.h"#include "mcv_common.h" //其中是opencv的一些头文件class myimg :public CvvImage{public:myimg();mSetImg(IplImage* pImg);};//class实现文件#include "stdafx.h"#include "mcv_common.h" //其中是opencv的一些头文件#include "mCImage.h"myimg::myimg(){}myimg::mSetImg(IplImage* pImg){m_img=cvCloneImage(pImg); //这句很关键,调试也曾换成CImage类中的CopeOf方法,但是总有类型转换错误}//测试代码//打开文件BOOL CMcv_image_sdiDoc::OnOpenDocument(LPCTSTR lpszPathName){if (!CDocument::OnOpenDocument(lpszPathName))return FALSE;m_imgBackup=cvLoadImage(lpszPathName,0);mcv_image.mSetImg(m_imgBackup);return TRUE;}//图像处理:这里以灰度拉伸为例void CMcv_image_sdiView::OnPointStre(){CMcv_image_sdiDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);IplImage* pImgTemp=pDoc ->mcv_image.GetImage();pImgTemp=GrayStretch(pImgTemp, pImgTemp->width,pImgTemp->height, bX1, bY1, bX2, bY2);//此处是自定义函数,可以换成其他处理pDoc ->mcv_image.mSetImg(pImgTemp); //主要是部分:将处理后和图像写入CImage中的m_img//非常关键的部分UpdateData(FALSE); // 更新CRect m_MouseRect;GetClientRect (&m_MouseRect);InvalidateRect(m_MouseRect, TRUE);// 重绘}//显示部分void CMcv_image_sdiView::OnDraw(CDC* pDC){CMcv_image_sdiDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);myimg & c_myimg = pDoc ->mcv_image; //mcv_image->m_imageCRect m_rect;m_rect.SetRect(0,0,c_myimg.Width(),c_myimg.Height());c_myimg.DrawToHDC(pDC->GetSafeHdc() ,m_rect);}PS:Mcv_image_sdi为工程名,是一个单文档工程虽然不大一个问题,但是还是费了半天劲,和大家分享,希望多提意见,共同学习。
VS2010+Opencv+MFC读取图像和视频显示在Picture控件
VS2010+Opencv+MFC读取图像和视频显⽰在Picture控件VS2010+Opencv+MFC读取图像和视频显⽰在Picture控件,供⼤家参考,具体内容如下1.新建MFC对话框应⽤程序。
其余选项默认,单击完成,创建出对话框应⽤程序。
删掉原来⾃带的⼀些控件,添加picture控件和两个按钮。
2.由于以后的代码会⽤到CvvImage类,⽽opencv2.3以后就去掉了对它的⽀持,这⾥先介绍添加CvvImage⽀持的⽅法,直接能⽤的可以略过这⼀步。
如下图添加相应的⽂件:这⾥附上两个⽂件的源码⽅便使⽤。
#pragma once#ifndef CVVIMAGE_CLASS_DEF#define CVVIMAGE_CLASS_DEF#include "opencv.hpp"class CvvImage{public:CvvImage();virtual ~CvvImage();virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 );virtual bool Load( const char* filename, int desired_color = 1 );virtual bool LoadRect( const char* filename,int desired_color, CvRect r );#if defined WIN32 || defined _WIN32virtual bool LoadRect( const char* filename,int desired_color, RECT r ){return LoadRect( filename, desired_color,cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top ));}#endifvirtual bool Save( const char* filename );virtual void CopyOf( CvvImage& image, int desired_color = -1 );virtual void CopyOf( IplImage* img, int desired_color = -1 );IplImage* GetImage() { return m_img; };virtual void Destroy(void);int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; }; int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;}; int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };virtual void Fill( int color );virtual void Show( const char* window );#if defined WIN32 || defined _WIN32virtual void Show( HDC dc, int x, int y, int width, int height,int from_x = 0, int from_y = 0 );virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect );#endifprotected:IplImage* m_img;#endif#include "StdAfx.h"#include "CvvImage.h"//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CV_INLINE RECT NormalizeRect( RECT r );CV_INLINE RECT NormalizeRect( RECT r ){int t;if( r.left > r.right ){t = r.left;r.left = r.right;r.right = t;}if( r.top > r.bottom ){t = r.top;r.top = r.bottom;r.bottom = t;}return r;}CV_INLINE CvRect RectToCvRect( RECT sr );CV_INLINE CvRect RectToCvRect( RECT sr ){sr = NormalizeRect( sr );return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top );}CV_INLINE RECT CvRectToRect( CvRect sr );CV_INLINE RECT CvRectToRect( CvRect sr ){RECT dr;dr.left = sr.x;dr.top = sr.y;dr.right = sr.x + sr.width;dr.bottom = sr.y + sr.height;return dr;}CV_INLINE IplROI RectToROI( RECT r );CV_INLINE IplROI RectToROI( RECT r ){IplROI roi;r = NormalizeRect( r );roi.xOffset = r.left;roi.yOffset = r.top;roi.width = r.right - r.left;roi.height = r.bottom - r.top;roi.coi = 0;return roi;}void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin ){assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);memset( bmih, 0, sizeof(*bmih));bmih->biSize = sizeof(BITMAPINFOHEADER);bmih->biWidth = width;bmih->biHeight = origin ? abs(height) : -abs(height);bmih->biPlanes = 1;bmih->biBitCount = (unsigned short)bpp;bmih->biCompression = BI_RGB;if( bpp == 8 ){RGBQUAD* palette = bmi->bmiColors;int i;for( i = 0; i < 256; i++ ){palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;palette[i].rgbReserved = 0;{m_img = 0;}void CvvImage::Destroy(){cvReleaseImage( &m_img );}CvvImage::~CvvImage(){Destroy();}bool CvvImage::Create( int w, int h, int bpp, int origin ){const unsigned max_img_size = 10000;if( (bpp != 8 && bpp != 24 && bpp != 32) ||(unsigned)w >= max_img_size || (unsigned)h >= max_img_size ||(origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL)){assert(0); // most probably, it is a programming errorreturn false;}if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h ) {if( m_img && m_img->nSize == sizeof(IplImage))Destroy();m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 ); }if( m_img )m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;return m_img != 0;}void CvvImage::CopyOf( CvvImage& image, int desired_color ){IplImage* img = image.GetImage();if( img ){CopyOf( img, desired_color );}}#define HG_IS_IMAGE(img) \((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \ ((IplImage*)img)->imageData != 0)void CvvImage::CopyOf( IplImage* img, int desired_color ){if( HG_IS_IMAGE(img) ){int color = desired_color;CvSize size = cvGetSize( img );if( color < 0 )color = img->nChannels > 1;if( Create( size.width, size.height,(!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8,img->origin )){cvConvertImage( img, m_img, 0 );}}}bool CvvImage::Load( const char* filename, int desired_color ){IplImage* img = cvLoadImage( filename, desired_color );if( !img )return false;CopyOf( img, desired_color );cvReleaseImage( &img );return true;}bool CvvImage::LoadRect( const char* filename,int desired_color, CvRect r ){if( r.width < 0 || r.height < 0 ) return false;IplImage* img = cvLoadImage( filename, desired_color );if( !img )return false;if( r.width == 0 || r.height == 0 ){r.width = img->width;r.height = img->height;r.x = r.y = 0;}if( r.x > img->width || r.y > img->height ||r.x + r.width < 0 || r.y + r.height < 0 ){cvReleaseImage( &img );return false;}if( r.x < 0 ){r.width += r.x;r.x = 0;}if( r.y < 0 ){r.height += r.y;r.y = 0;}if( r.x + r.width > img->width )r.width = img->width - r.x;if( r.y + r.height > img->height )r.height = img->height - r.y;cvSetImageROI( img, r );CopyOf( img, desired_color );cvReleaseImage( &img );return true;}bool CvvImage::Save( const char* filename ){if( !m_img )return false;cvSaveImage( filename, m_img );return true;}void CvvImage::Show( const char* window ){if( m_img )cvShowImage( window, m_img );}void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y ){if( m_img && m_img->depth == IPL_DEPTH_8U ){uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];BITMAPINFO* bmi = (BITMAPINFO*)buffer;int bmp_w = m_img->width, bmp_h = m_img->height;FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 );from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 );int sw = MAX( MIN( bmp_w - from_x, w ), 0 );int sh = MAX( MIN( bmp_h - from_y, h ), 0 );SetDIBitsToDevice(dc, x, y, sw, sh, from_x, from_y, from_y, sh,m_img->imageData + from_y*m_img->widthStep,bmi, DIB_RGB_COLORS );}}void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ){if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData ) {uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];BITMAPINFO* bmi = (BITMAPINFO*)buffer;int bmp_w = m_img->width, bmp_h = m_img->height;CvRect roi = cvGetImageROI( m_img );CvRect dst = RectToCvRect( *pDstRect );if( roi.width == dst.width && roi.height == dst.height ){Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y );return;}if( roi.width > dst.width ){SetStretchBltMode(hDCDst, // handle to device contextHALFTONE );}else{SetStretchBltMode(hDCDst, // handle to device contextCOLORONCOLOR );}FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );::StretchDIBits(hDCDst,dst.x, dst.y, dst.width, dst.height,roi.x, roi.y, roi.width, roi.height,m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );}}void CvvImage::Fill( int color ){cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) );}在需要引⽤该类的地⽅添加如下引⽤:3.在Picture控件中显⽰图⽚如图所⽰修改控件ID,并删除按钮已存在的响应代码。
在MFC中使用OpenCV
在MFC中使用OpenCV演示程序CVMFC本程序是在MFC 中使用OpenCV 的演示程序,由3部分组成。
一、Windows 下用MFC 编制的程序框架采用设备无关位图DIB实现Windows多文档模式下图像的显示,实现显示的关键函数StretchDIBits的原型如下:int StretchDIBits(HDC hdc, // 显示设备句柄int XDest, // 目标矩形区域左上角X坐标int YDest, // 目标矩形区域左上角Y坐标int nDestWidth, // 目标矩形区域宽度int nDestHeight, // 目标矩形区域高度int XSrc, // 源矩形区域左上角X坐标int YSrc, // 源矩形区域左上角Y坐标int nSrcWidth, // 源矩形区域宽度int nSrcHeight, // 源矩形区域高度CONST VOID *lpBits, // 位图的像素存放首地址CONST BITMAPINFO *lpBitsInfo, // 位图信息存放地址UINT iUsage, // 位图中的颜色类型,RGB模式用DIB_RGB_COLORSDWORD dwRop // 像素操作码,简单复制用SRCCOPY);由于OpenCV中的位图结构中的像素数据与DIB中的像素具有相同的存储结构,见表1中的像素部分。
所以,只要为它构造一个DIB的位图信息就可以调用API函数StretchDIBits实现它的显示了。
表1DIB位图参数与IplImage结构参数参数DIB (MFC) IplImage (OpenCV)宽度biWidth width高度biHeight height像素位数biBitCount (1,4,8,16,24,32) = depth*nChannels depth (8,16,32,64)通道数--- nChannels (1,2,3,4)(单通道位图) 调色板单元数2biBitCount(2, 16, 256)二值图像显示为灰阶图像256色彩色图像显示为真彩色图像位图坐标原点底-左origin (0 顶-左,1 底-左) 像素分量存放方式交叉存取(按像素为单位存放) 0 交叉存取,1 位平面方式对齐方式(行像素数据凑整) 4字节对齐4字节对齐或8字节对齐每行字节数(biWidth*biBitCount+31)/32*4 widthStep像素字节数((biWidth*biBitCount+31)/32*4)* biHeight imageSize像素存放地址BYTE* pBits char* imageData感兴趣区域---roi表中正体字母部分表示相同的参数,粗体字母表示参数部分相同时的交集,斜体加下划线表示结构特有的参数。
mfc中使用opencv获取摄像头视频并显示
一、使用DirectShow获取摄像头视频DirectShow在V isual Studio 2005开发环境下的使用说明:1.将CameraDS.h CameraDS.cpp复制到你的项目中;2.将DirectShow复制到你的opencv根目录下,菜单工具->选项->项目和解决方案->vc++目录,把..(你的opencv安装目录)/DirectShow/Include添加到“包含文件”中;3.菜单工具->选项->项目和解决方案->vc++目录,把..(你的opencv安装目录)/DirectShow/Lib添加到“库文件”下面。
获取摄像视频:利用CameraDS的OpenCamera函数打开摄像头,利用QueryFrame获取每一帧。
二、使用CvvImage类显示摄像头视频opencv的较高版本中没有CvvImage类,因此需要手动添加这个类的头文件CvvImage.h 和代码文件CvvImage.cpp。
mfc界面添加一个picture控件,ID为IDC_VIEW1。
在对话框头文件中定义如下变量:CRect rect1;CStatic* pStc1;CDC* pDC1;HDC hDC1;在对话框源文件OnInitDialog中初始化变量:pStc1=(CStatic *)GetDlgItem(IDC_VIEW1);pStc1->GetClientRect(&rect1);pDC1=pStc1->GetDC();hDC1=pDC1->GetSafeHdc();显示视频:CvvImage m_CvvImage;m_CvvImage.CopyOf(frame,frame->nChannels); //frame是视频帧m_CvvImage.DrawToHDC(dlg->hDC1, &dlg->rect1);。
分别用MFC、Opencv库、FreeImage库显示同一张BMP图像
分别用MFC、Opencv库、FreeImage库显示同一张BMP图像用VS2008平台设计一个简单的MFC程序,分别用MFC、Opencv库、FreeImage 库三种不同的方法来显示同一张BMP图像。
1 MFC显示BMP图像(1)MFC插入单张图片1、创建MFC打开VS2008软件,创建一个MFC对话框应用程序(Dialog-based Application),在名称栏输入创建项目的名称,点击“确定”。
如下图所示:在出现的“MFC应用程序向导”对话框内,选择“基于对话框”,并取消“使用Unicode库(N)”其他选项不做修改,单击“下一步”,如下图所示:一直点击“下一步”到“生成的类”对话框,选择基类为“CDialog”单击完成即可创建一个MFC对话框。
如下图所示:2、添加控件并导入图片生成如下图所示的初始的GUI界面,在工具箱中单击“Picture Control”,将鼠标移动到GUI界面内,这样就在此界面添加了一个Picture控件。
接着,在“资源视图”下,右击选择“添加资源”,在“添加资源”对话框的“资源类型”下选择“Bitmap”,再单击“导入(M)”,打开BMP图片。
如下图所示:3、设置控件最后在Picture控件的“属性”窗口中将“Type”选择为“Bitmap”类型,将“Image”和“ID”都选择为导入BMP图片的ID,比如IDB_BITMAP1。
如下图所示:4、运行程序最后保存并运行一下程序,成功后将会得到一个含有导入的BMP图像的窗口,完成显示BMP图像的功能,如下图所示:(2)MFC插入多张图片1、添加控件并导入多张图片当需要插入多张图片时,导入图片的方法同上,然后为每一张图片设置它们的“ID”,例如:IDB_BITMAP1、IDB_BITMAP2、IDB_BITMAP3、IDB_BITMAP4。
在GUI界面中添加一个选择按钮,选择工具箱中的“Combo box”,如下图所示:通过属性窗口修改它的“ID”为“IDC_CHOICE”,“Type”选择“Drop List”,“Owner Draw”选择“No”,在“数据”项中输入每幅图片的名字,每个名字间用分号隔开。
OpenCV和MFC结合编程例子新
下面是一个简单的应用OpenCV和MFC结合编程的例子。
(1)成立一个基于Dialog的MFC工程OpenCV_Dlg1,在头文件中加入“#include <>”,
过Edit控件IDC_EDIT_TH,用户能够输入图像分割阈值,程序会将其自动更新到,int,
(7)添加Edit控件,ID号为IDC_EDIT_TH2,应用向导工具MFC ClassWizard给该ID
至此,当点击“读图”按钮打开一幅图片,该图片将在Picture控件中显示;在Edit控件IDC_EDIT_TH中输入阈值,并点击“阈值分割”按钮,则对读入的图像做二值化处置,处置结果在一个新弹出窗口中显示。
以上所编写程序是个实验性程序,从中能够反映出用OpenCV编程的一般性步骤。
但该程序仍然存在Bug:即显示在Picture控件中的图像不会重绘,也就是说若是用另外一个窗口遮挡Picture控件中的图像,当该窗口移去时被遮挡部份的图像便显示一片空白。
此问题有待对程序进一步查错。
OpenCV锐利体验系列课程_MFC中快速应用OpenCV
OpenCV锐利体验系列课程_连连看程序设计(4)
MFC中快速应用 中快速应用OpenCV 中快速应用
5.在View类中添加显示图像代码 在 类中添加显示图像代码
主要是在Ondraw里面。 CImage & img = pDoc->m_image; CRect r; GetClientRect(&r); img.DrawToHDC(pDC->GetSafeHdc(), r);
OpenCV锐利体验系列课程_连连看程序设计(4)
MFC中快速应用 中快速应用OpenCV 中快速应用
二.在MFC中如何应用菜单和 中如何应用菜单和Canny算子的实例 在 中如何应用菜单和 算子的实例
修改代码:m_image.Load(lpszPathName,0); 第三个参数0:强制转化读取图像为8位深度灰度图
MFC中快速应用 中快速应用OpenCV 中快速应用
选中As a statically linked library单选按钮
OpenCV锐利体验系列课程_连连看程序设计(4)
MFC中快速应用 中快速应用OpenCV 中快速应用
2.加入 加入OpenCV库支持 加入 库支持
加入openCV必须的头文件和库文件 添加库文件: cxcore.lib cv.lib highgui.lib
锐利体验系列课程
MFC中快速应用 中快速应用OpenCV 中快速应用
OpenCV锐利体验系列课程_连连看程序设计
MFC中快速应用 中快速应用OpenCV 中快速应用
一.介绍基本的 介绍基本的openCV和MFC的操作 介绍基本的 和 的操作 1.创建 创建SDI工程 工程 创建
按照VC的向导,产生一个默认的MFC的工程,注意,选 择SDI单文档支持的,同时最好选择“use MFC As a static library”(防止MFC中使用OpenCV的内存泄露问题)
一种基于OpenCV和MFC的图像输出方法
一种基于OpenCV和MFC的图像输出方法
唐良;何伟;秦波;刘建国
【期刊名称】《怀化学院学报》
【年(卷),期】2018(037)005
【摘要】OpenCV在图像处理中的一个优点是执行效率高,而MFC可以通过控件技术实现图像的输出.本文借助MFC和OpenCV解决图像处理过程中的分辨率过高,有可能导致显示器不能完全显示的问题.在问题解决过程中,通过响应滑动控件的WM_HSCROLL消息找到了适合高效遍历算法的颜色缩减系数,为研究动态图像的即时处理提供理论基础.
【总页数】5页(P61-65)
【作者】唐良;何伟;秦波;刘建国
【作者单位】怀化学院实践教学中心, 湖南怀化 418008;怀化学院数学与计算科学学院, 湖南怀化 418008;怀化学院实践教学中心, 湖南怀化 418008;怀化学院数学与计算科学学院, 湖南怀化 418008
【正文语种】中文
【中图分类】TP3
【相关文献】
1.一种基于OpenCV的彩色图像滤波算法设计 [J], 韦星;马智愚
2.一种基于TuriCreate和OpenCV的实时图像识别系统设计 [J], 罗伊杭;罗诗光;潘与维;杨欢;韦金娇
3.一种硬件加速OpenCV的图像处理方法研究 [J], 张俊涛;王园伟;庞多
4.一种基于OpenCV的指静脉图像匹配方法 [J], 蓝波;吴昊;赵双喜
5.一种基于OpenCV的二值图像线状要素坐标识别方法 [J], 尹舒祚;张乃丹;孙志民;梁博
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
OpenCV 在MFC中的一些基本使用方法在《OpenCV教程-基础篇》的中,所创建的MFC图像显示是直接放在对话框面板的左上角的,感觉不大美观;《MFC 中快速应用OpenCV》则是介绍用SDI(单文档界面)来显示图像,《A step-by-step guide to the use of Microsoft Visual C++ and the Intel OpenCV library》使用VS2005来进行图像和视频的读取和处理,但是其图像和视频的显示界面不是在对话框里面的,而是新建一个窗口来做。
所以下面我们就来看看怎么在对话框里使用Picture控件来显示和处理图像。
一、创建MFC首先创建一个MFC对话框应用程序(Dialog-based Application)如下:在VS2005和2008里,我们可以用一个Solution 来组合几个Project (每个Project 基本上只包含一个Program),当我们要构建一个多Program的应用时(例如一个客户端程序加一个服务器应用程序),利用Solution 可以将这些Projects 组合起来、并且共享文件和函数库。
通常需要为Solution创建一个主路径,其中包含了所有Projects的路径。
不过在这篇文章里,我们只构建一个简单的Project,所以在创建MFC的New Project对话框里,不用勾选“Create directory for solution”这个选项。
点击OK -- Next进入下一步,在这里我们创建一个Dialog-based Application,大部分选项按默认设置就行,不过最下面的“Use Unicode libraries”最好去掉。
如果勾选了这个选项,程序代码就会使用16bit的Unicode字符集来编码,但是很多函数虽然使用char* (ASCII stings) 类型字符,而将字符串从Unicode 转换到ASCII 是非常麻烦的。
使用Unicode 在编译时可能会遇到下列错误:cannot convert parameter 1 from 'CString' to 'const char *'cannot convert from 'const char [11]' to 'LPCWSTR'这意味着在Unicode和Multi-byte字符串的转换中出现了问题。
在上一篇学习笔记中,就提到“成员函数LoadBMP其输入参数类型应为const char*”,那应该只是一个治标的方法,这里的去掉“Use Unicode libraries”选项,才是治本之道。
往后的几步设置,可以根据自己的需要来操作,我的设置如下:二、编写代码在Resource View面板->mymfc(工程名称)->mymfc.rc->Dialog双击IDD_MYMFC_DIALOG,可以看到一个初始的GUI界面,往里面添加两个Button 和一个Picture 控件,如下:选中单个控件、右击选择属性(Properties),可以看到控件的ID号,这个号可以自行编辑,例如Picture 控件的ID 号我设置为IDC_ShowImg,这个ID 号在后面的图像显示函数中要用到。
首先在项目属性中加载lib文件:菜单Project -> Properties -> Configuration Properties -> Linker –> Input -> additional dependencies 中加入cxcore200.lib cv200.lib highgui200.lib。
然后在mymfc.h 的#include "resource.h" 下加入如下代码:#include "cv.h"#include "highgui.h"#define IMAGE_WIDTH 256#define IMAGE_HEIGHT 256#define IMAGE_CHANNELS 3在Class View 面板右击CmymfcDlg,选择Add –> Add Variable,添加一个IplImage* 类型的变量TheImage;再点击CmymfcDlg,在下面窗口的列表中双击OnInitDialog,在“// TODO: Add extra initialization here”下面添加TheImage 的初始化代码:CvSize ImgSize;ImgSize.height = IMAGE_HEIGHT;ImgSize.width = IMAGE_WIDTH;TheImage = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );然后双击OnPaint,在if(IsIconic())…的else 里添加以下代码,用来重绘窗口:CDialog::OnPaint(); // 重绘对话框CDialog::UpdateWindow(); // 更新windows窗口,如果无这步调用,图片显示还会出现问题ShowImage( TheImage, IDC_ShowImg ); // 重绘图片函数接着在CmymfcApp 下面的成员列表中双击InitInstance,在两个“// TODO: Place code here to handle when the dialog is…”下面添加:cvReleaseImage( &dlg.TheImage );即按下“OK”或“Cancel”时,释放TheImage占用的内存。
接下来就是写读取和处理图片的功能函数了。
回到mymfc 的GUI 编辑界面中,右击按钮ReadImg,选择Add Event Handler,建立按钮点击的消息响应程序:句柄名设置为OnBnClickedReadimg,主要的响应操作包括弹出对话框选择图片文件、读入图片文件、对图片统一缩放至256*256的大小、显示图像,代码如下:// TODO: Add your control notification handler code hereCFileDialog dlg(TRUE, _T("*.bmp"), NULL,OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,_T("image files (*.bmp; *.jpg) |*.bmp; *.jpg | All Files (*.*) |*.*||"), NULL); // 选项图片的约定dlg.m_ofn.lpstrTitle = _T("Open Image"); // 打开文件对话框的标题名if( dlg.DoModal() != IDOK ) // 判断是否获得图片return;CString mPath = dlg.GetPathName(); // 获取图片路径IplImage* ipl = cvLoadImage( mPath, 1 ); // 读取图片、缓存到一个局部变量ipl 中if( !ipl ) // 判断是否成功载入图片return;if( TheImage ) // 对上一幅显示的图片数据清零cvZero( TheImage );ResizeImage( ipl ); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于256,再复制到TheImage 中ShowImage( TheImage, IDC_ShowImg ); // 调用显示图片函数cvReleaseImage( &ipl ); // 释放ipl 占用的内存其中包含了两个新的成员函数ResizeImage 和ShowImage,前者的作用是对读入的不同大小的图像进行缩放,再通过设置ROI 的方式将图像存入256*256 的TheImage 中;后者是将图像TheImage 显示到图片显示控件IDC_ShouImg 窗口的正中部位。
为了实现这两个功能,首先在Class View 面板右击CmymfcDlg,选择Add –> Add Function,创建两个函数:void ShowImage( IplImage* img, UINT ID ) 和void ResizeImage(IplImage* img)。
以下是这两个函数的实现代码:void CmymfcDlg::ResizeImage(IplImage* img){// 读取图片的宽和高int w = img->width;int h = img->height;// 找出宽和高中的较大值者int max = (w > h)? w: h;// 计算将图片缩放到TheImage区域所需的比例因子float scale = (float) ( (float) max / 256.0f );// 缩放后图片的宽和高int nw = (int)( w/scale );int nh = (int)( h/scale );// 为了将缩放后的图片存入TheImage 的正中部位,需计算图片在TheImage 左上角的期望坐标值int tlx = (nw > nh)? 0: (int)(256-nw)/2;int tly = (nw > nh)? (int)(256-nh)/2: 0;// 设置TheImage 的ROI 区域,用来存入图片imgcvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );// 对图片img 进行缩放,并存入到TheImage 中cvResize( img, TheImage );// 重置TheImage 的ROI 准备读入下一幅图片cvResetImageROI( TheImage );}void CmymfcDlg::ShowImage( IplImage* img, UINT ID ) // ID 是Picture Control控件的ID号{CDC* pDC = GetDlgItem( ID ) ->GetDC(); // 获得显示控件的DCHDC hDC = pDC ->GetSafeHdc(); // 获取HDC(设备句柄) 来进行绘图操作CRect rect;GetDlgItem(ID) ->GetClientRect( &rect );int rw = rect.right - rect.left; // 求出图片控件的宽和高int rh = rect.bottom - rect.top;int iw = img->width; // 读取图片的宽和高int ih = img->height;int tx = (int)(rw - iw)/2; // 使图片的显示位置正好在控件的正中int ty = (int)(rh - ih)/2;SetRect( rect, tx, ty, tx+iw, ty+ih );CvvImage cimg;cimg.CopyOf( img ); // 复制图片cimg.DrawToHDC( hDC, &rect ); // 将图片绘制到显示控件的指定区域内ReleaseDC( pDC );}函数ResizeImage 是参考了学习笔记(5)中单窗口显示多幅图像的函数cvShowMultiImages 修改而成的,函数ShowImage 则是参考了帖子《OpenCV如何把图像显示到MFC的picture控件上》的代码,另外下面几个帖子也可以参考:1、《MFC picture control 畫框的問題》2、《MFC picture control控件实现(隐藏)文字显示》3、《MFC在Picture Control中显示图片(jpg)遇到的问题》4、《vc怎样在picture control中显示jpg,jif,bmp格式图象》5、《使用Picture Control显示BMP图片》最后是要对读入的图像做简单的Canny边缘处理,为此,建立一个按钮EdgeDetect,相应的响应代码如下:void CmymfcDlg::OnBnClickedEdgedetect(){// TODO: Add your control notification handler code hereIplImage *gray = 0, *edge = 0;gray = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );edge = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );cvCvtColor( TheImage, gray, CV_BGR2GRAY );cvCanny( gray, edge, 30, 100, 3 );cvCvtColor( edge, TheImage, CV_GRAY2BGR );ShowImage( TheImage, IDC_ShowImg ); // 调用显示图片函数cvReleaseImage( &gray );cvReleaseImage( &edge );}这里主要是参考了《OpenCV教程-基础篇》P33的代码,不过并没有像书中那样创建新的MyIplClass 类来进行图像的读取和处理操作。