vc++ MFC opencv 显示摄像头图像的2种方法
1.通过 vvimage 类显示到MFC控件中
参考
opencv -- cvvimage 的使用 opencv2.1后版本
Cvvimage.h 文件
1 #pragma once 2 #ifndef CVVIMAGE_CLASS_DEF 3 #define CVVIMAGE_CLASS_DEF 4 #include "opencv.hpp" 5 #include <windows.h> 6 /* CvvImage class definition */ 7 class CvvImage 8 { 9 public: 10 CvvImage(); 11 virtual ~CvvImage(); 12 /* Create image (BGR or grayscale) */ 13 virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 ); 14 /* Load image from specified file */ 15 virtual bool Load( const char* filename, int desired_color = 1 ); 16 /* Load rectangle from the file */ 17 virtual bool LoadRect( const char* filename, 18 int desired_color, CvRect r ); 19 #if defined WIN32 || defined _WIN32 20 virtual bool LoadRect( const char* filename, 21 int desired_color, RECT r ) 22 { 23 return LoadRect( filename, desired_color, 24 cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top )); 25 } 26 #endif 27 /* Save entire image to specified file. */ 28 virtual bool Save( const char* filename ); 29 /* Get copy of input image ROI */ 30 virtual void CopyOf( CvvImage& image, int desired_color = -1 ); 31 virtual void CopyOf( IplImage* img, int desired_color = -1 ); 32 IplImage* GetImage() { return m_img; }; 33 virtual void Destroy(void); 34 /* width and height of ROI */ 35 int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; }; 36 int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;}; 37 int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; }; 38 virtual void Fill( int color ); 39 /* draw to highgui window */ 40 virtual void Show( const char* window ); 41 42 #if defined WIN32 || defined _WIN32 43 /* draw part of image to the specified DC */ 44 virtual void Show( HDC dc, int x, int y, int width, int height, 45 int from_x = 0, int from_y = 0 ); 46 /* draw the current image ROI to the specified rectangle of the destination DC */ 47 virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect ); 48 #endif 49 protected: 50 IplImage* m_img; 51 }; 52 typedef CvvImage CImage; 53 #endif
Cvvimage.cpp文件
1 #include "StdAfx.h" 2 #include "CvvImage.h" 3 // 4 // Construction/Destruction 5 // 6 CV_INLINE RECT NormalizeRect( RECT r ); 7 CV_INLINE RECT NormalizeRect( RECT r ) 8 { 9 int t; 10 if( r.left > r.right ) 11 { 12 t = r.left; 13 r.left = r.right; 14 r.right = t; 15 } 16 if( r.top > r.bottom ) 17 { 18 t = r.top; 19 r.top = r.bottom; 20 r.bottom = t; 21 } 22 23 return r; 24 } 25 CV_INLINE CvRect RectToCvRect( RECT sr ); 26 CV_INLINE CvRect RectToCvRect( RECT sr ) 27 { 28 sr = NormalizeRect( sr ); 29 return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top ); 30 } 31 CV_INLINE RECT CvRectToRect( CvRect sr ); 32 CV_INLINE RECT CvRectToRect( CvRect sr ) 33 { 34 RECT dr; 35 dr.left = sr.x; 36 dr.top = sr.y; 37 dr.right = sr.x + sr.width; 38 dr.bottom = sr.y + sr.height; 39 40 return dr; 41 } 42 CV_INLINE IplROI RectToROI( RECT r ); 43 CV_INLINE IplROI RectToROI( RECT r ) 44 { 45 IplROI roi; 46 r = NormalizeRect( r ); 47 roi.xOffset = r.left; 48 roi.yOffset = r.top; 49 roi.width = r.right - r.left; 50 roi.height = r.bottom - r.top; 51 roi.coi = 0; 52 53 return roi; 54 } 55 void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin ) 56 { 57 assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); 58 59 BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 60 61 memset( bmih, 0, sizeof(*bmih)); 62 bmih->biSize = sizeof(BITMAPINFOHEADER); 63 bmih->biWidth = width; 64 bmih->biHeight = origin ? abs(height) : -abs(height); 65 bmih->biPlanes = 1; 66 bmih->biBitCount = (unsigned short)bpp; 67 bmih->biCompression = BI_RGB; 68 if( bpp == 8 ) 69 { 70 RGBQUAD* palette = bmi->bmiColors; 71 int i; 72 for( i = 0; i < 256; i++ ) 73 { 74 palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 75 palette[i].rgbReserved = 0; 76 } 77 } 78 } 79 CvvImage::CvvImage() 80 { 81 m_img = 0; 82 } 83 void CvvImage::Destroy() 84 { 85 cvReleaseImage( &m_img ); 86 } 87 CvvImage::~CvvImage() 88 { 89 Destroy(); 90 } 91 bool CvvImage::Create( int w, int h, int bpp, int origin ) 92 { 93 const unsigned max_img_size = 10000; 94 95 if( (bpp != 8 && bpp != 24 && bpp != 32) || 96 (unsigned)w >= max_img_size || (unsigned)h >= max_img_size || 97 (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL)) 98 { 99 assert(0); // most probably, it is a programming error 100 return false; 101 } 102 if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h ) 103 { 104 if( m_img && m_img->nSize == sizeof(IplImage)) 105 Destroy(); 106 /* prepare IPL header */ 107 m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 ); 108 } 109 if( m_img ) 110 m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL; 111 return m_img != 0; 112 } 113 void CvvImage::CopyOf( CvvImage& image, int desired_color ) 114 { 115 IplImage* img = image.GetImage(); 116 if( img ) 117 { 118 CopyOf( img, desired_color ); 119 } 120 } 121 #define HG_IS_IMAGE(img) \ 122 ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \ 123 ((IplImage*)img)->imageData != 0) 124 void CvvImage::CopyOf( IplImage* img, int desired_color ) 125 { 126 if( HG_IS_IMAGE(img) ) 127 { 128 int color = desired_color; 129 CvSize size = cvGetSize( img ); 130 if( color < 0 ) 131 color = img->nChannels > 1; 132 if( Create( size.width, size.height, 133 (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8, 134 img->origin )) 135 { 136 cvConvertImage( img, m_img, 0 ); 137 } 138 } 139 } 140 bool CvvImage::Load( const char* filename, int desired_color ) 141 { 142 IplImage* img = cvLoadImage( filename, desired_color ); 143 if( !img ) 144 return false; 145 146 CopyOf( img, desired_color ); 147 cvReleaseImage( &img ); 148 149 return true; 150 } 151 bool CvvImage::LoadRect( const char* filename, 152 int desired_color, CvRect r ) 153 { 154 if( r.width < 0 || r.height < 0 ) return false; 155 156 IplImage* img = cvLoadImage( filename, desired_color ); 157 if( !img ) 158 return false; 159 if( r.width == 0 || r.height == 0 ) 160 { 161 r.width = img->width; 162 r.height = img->height; 163 r.x = r.y = 0; 164 } 165 if( r.x > img->width || r.y > img->height || 166 r.x + r.width < 0 || r.y + r.height < 0 ) 167 { 168 cvReleaseImage( &img ); 169 return false; 170 } 171 /* truncate r to source image */ 172 if( r.x < 0 ) 173 { 174 r.width += r.x; 175 r.x = 0; 176 } 177 if( r.y < 0 ) 178 { 179 r.height += r.y; 180 r.y = 0; 181 } 182 if( r.x + r.width > img->width ) 183 r.width = img->width - r.x; 184 185 if( r.y + r.height > img->height ) 186 r.height = img->height - r.y; 187 cvSetImageROI( img, r ); 188 CopyOf( img, desired_color ); 189 cvReleaseImage( &img ); 190 return true; 191 } 192 bool CvvImage::Save( const char* filename ) 193 { 194 if( !m_img ) 195 return false; 196 cvSaveImage( filename, m_img ); 197 return true; 198 } 199 void CvvImage::Show( const char* window ) 200 { 201 if( m_img ) 202 cvShowImage( window, m_img ); 203 } 204 void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y ) 205 { 206 if( m_img && m_img->depth == IPL_DEPTH_8U ) 207 { 208 uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; 209 BITMAPINFO* bmi = (BITMAPINFO*)buffer; 210 int bmp_w = m_img->width, bmp_h = m_img->height; 211 FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); 212 from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 ); 213 from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 ); 214 int sw = MAX( MIN( bmp_w - from_x, w ), 0 ); 215 int sh = MAX( MIN( bmp_h - from_y, h ), 0 ); 216 SetDIBitsToDevice( 217 dc, x, y, sw, sh, from_x, from_y, from_y, sh, 218 m_img->imageData + from_y*m_img->widthStep, 219 bmi, DIB_RGB_COLORS ); 220 } 221 } 222 void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) 223 { 224 if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData ) 225 { 226 uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; 227 BITMAPINFO* bmi = (BITMAPINFO*)buffer; 228 int bmp_w = m_img->width, bmp_h = m_img->height; 229 CvRect roi = cvGetImageROI( m_img ); 230 CvRect dst = RectToCvRect( *pDstRect ); 231 if( roi.width == dst.width && roi.height == dst.height ) 232 { 233 Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y ); 234 return; 235 } 236 if( roi.width > dst.width ) 237 { 238 SetStretchBltMode( 239 hDCDst, // handle to device context 240 HALFTONE ); 241 } 242 else 243 { 244 SetStretchBltMode( 245 hDCDst, // handle to device context 246 COLORONCOLOR ); 247 } 248 FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); 249 ::StretchDIBits( 250 hDCDst, 251 dst.x, dst.y, dst.width, dst.height, 252 roi.x, roi.y, roi.width, roi.height, 253 m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY ); 254 } 255 } 256 void CvvImage::Fill( int color ) 257 { 258 cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) ); 259 }
调用方法是直接把这2个文件加入到工程
1 CvvImage m_CvvImage; 2 CDC *pDC;//关闭时释放 3 CRect CameraPicRect; 4 HDC hDC; 5 CvCapture* Capture; 6 IplImage* frame; 7 8 Capture = cvCreateCameraCapture(0);//要使用的摄像头索引 9 if (Capture == 0) 10 { 11 MessageBox(_T("无法连接摄像头!!!")); 12 return; 13 } 14 pDC = GetDlgItem(IDC_PIC_STATIC)->GetDC();//获取显示控件的句柄 15 GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&CameraPicRect);//得到控件尺寸 16 hDC = pDC->GetSafeHdc();//获取显示控件的句柄 17 18 frame = cvQueryFrame(Capture); //从摄像头或者文件中抓取并返回一帧 19 m_CvvImage.CopyOf(frame, 1); //复制该帧图像 20 m_CvvImage.DrawToHDC(hDC, &CameraPicRect); //显示到设备的矩形框内 21 22 //保存图像文件 23 IplImage* TakePictureFrame; 24 TakePictureFrame = frame; 25 char ImagePathName[256] = "123.jpg"; 26 IplImage *m_snap = cvCreateImage(cvGetSize(TakePictureFrame), TakePictureFrame->depth, TakePictureFrame->nChannels); 27 cvCopy(TakePictureFrame, m_snap, NULL); 28 cvSaveImage(ImagePathName, m_snap); //把图像写入指定文件夹的文件中去 29 cvReleaseImage(&m_snap);
2.新版本的opencv Cvvimage 类没有,改成了Mat
把 imshow 显示 Mat 的对话框窗口添加到MFC
参考
1 cv::Mat frame; 2 cv::Mat showFrame; 3 4 cv::namedWindow("view", cv::WINDOW_AUTOSIZE); 5 HWND hWnd = (HWND)cvGetWindowHandle("view"); 6 HWND hParent = ::GetParent(hWnd); 7 ::SetParent(hWnd, GetDlgItem(IDC_STA_TakePhoto)->m_hWnd); 8 ::ShowWindow(hParent, SW_HIDE); 9 CRect picRect; 10 GetDlgItem(IDC_STA_TakePhoto)->GetClientRect(picRect); 11 cv::VideoCapture capture(0); 12 if (!capture.isOpened()) 13 { 14 MessageBox(_T("打开摄像头失败")); 15 } 16 capture >> frame; 17 resize(frame, showFrame, cv::Size(picRect.Width(), picRect.Height())); 18 imshow("view", showFrame); 19 cv::waitKey(30);//没有这个显示不了 20 21 //保存图片 22 strPathName = strPath + strName;//这里用完整路径 23 char chPathName[MAX_PATH]; 24 WideCharToMultiByte(CP_ACP, 0, LPCTSTR(strPathName), -1, chPathName, MAX_PATH, NULL, NULL); 25 BOOL ret; 26 ret = imwrite(chPathName, frame); 27 if (!ret) 28 { 29 MessageBox(_T("照片保存失败")); 30 }