OpenCV与Windows MFC的图片显示

10 篇文章 0 订阅
9 篇文章 0 订阅

问题:

        经常需要为某个算法做一个demo的时候,会经常使用Windows的MFC程序框架进行简单快速的开发,

        也因此经常需要涉及到MFC上Picture Control上实时显示视频源的图片。

 

代码:

 

//
// MFC上Picture Control控件显示图像
// src 待显示的图像 (OpenCV库Mat对象结构)
// hwnd MFC显示图像的窗口句柄
//
void ShowImage (Mat& src, HWND hwnd) {
    //
    HDC hdc = ::GetDC (hwnd);
    //
    RECT rect;
    ::GetWindowRect (hwnd, &rect);
    //
    int dst_width = rect.right - rect.left;
    int dst_height = rect.bottom - rect.top;
    Mat image = Mat::zeros (dst_height, dst_width, src.type());
    //
    resize (src, image, Size (dst_width, dst_height));
    int depth = image.depth();
    int channel = image.channels();
    int type = image.type();
    CV_8U;
    IPL_DEPTH_8U;
    int bpp = 8 * image.channels();// 24;//8;//32;//
    uchar buffer[sizeof (BITMAPINFOHEADER) + 1024];
    BITMAPINFO* bmi = (BITMAPINFO*) buffer;
    BITMAPINFOHEADER* bmih = & (bmi->bmiHeader);
    memset (bmih, 0, sizeof (*bmih));
    bmih->biSize = sizeof (BITMAPINFOHEADER);
    bmih->biWidth = image.cols;
    bmih->biHeight = -image.rows;
    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;
        }
    }
    
    //
    CvRect dst (rect.left, rect.top,
                rect.right - rect.left,
                rect.bottom - rect.top);
    ::StretchDIBits (
        hdc,
        0, 0, dst.width, dst.height,
        0, 0, image.cols, image.rows,
        image.data, bmi, DIB_RGB_COLORS, SRCCOPY);
    //
    ::ReleaseDC (hwnd, hdc);
}
// Mylaf 

测试及效果:

    // 获取显示控件的窗口句柄
    HWND hwnd = GetDlgItem (IDC_PIC_LEFT)->GetSafeHwnd();
    // 获取显示的图像
    Mat img = imread ("D:\\Mylaf\\Project\\VS2013\\XMRK\\testOpenCV320\\ambush_5_left.jpg");
    // 调用显示函数
    ShowImage (img, hwnd);

 

扩展代码:

头文件:

  // header file 
  // mylaf 
  struct StDisplayWnd {
    HWND hwnd;
    HDC  hdc;
    RECT rect;
    BITMAPINFO* bmi;
    cv::Mat image;
  };

  void initDisplayParam(StDisplayWnd* wnd, HWND hwnd);
  //
  void Display(StDisplayWnd* wnd, cv::Mat& img);

  void releaseDisplay(StDisplayWnd* wnd);

实现文件:

// implement file 
// mylaf 

void initDisplayParam(StDisplayWnd* wnd, HWND hwnd) { // 
	unsigned int buff_size = sizeof(BITMAPINFOHEADER) + 1024;
	unsigned char* buff = new unsigned char[buff_size]; // 
	wnd->hwnd = hwnd;//GetDlgItem(id)->GetSafeHwnd(); 
	wnd->hdc = ::GetDC(wnd->hwnd);
	::GetWindowRect(wnd->hwnd, &wnd->rect); // 
	int dst_width = wnd->rect.right - wnd->rect.left;
	int dst_height = wnd->rect.bottom - wnd->rect.top;
	int dst_bpp = 24;// 8 * image.channels(); // 
	wnd->bmi = (BITMAPINFO*)buff;
	BITMAPINFOHEADER* bmih = &(wnd->bmi->bmiHeader);
	memset(bmih, 0, sizeof(*bmih));
	bmih->biSize = sizeof(BITMAPINFOHEADER);
	bmih->biWidth = dst_width;// image.cols;
	bmih->biHeight = -dst_height;// -image.rows; 
	bmih->biPlanes = 1;
	bmih->biBitCount = (unsigned short)dst_bpp;
	bmih->biCompression = BI_RGB; // 
	if (dst_bpp == 8)
	{
		RGBQUAD* palette = wnd->bmi->bmiColors;
		for (int i = 0; i < 256; i++)
		{
			palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
			palette[i].rgbReserved = 0;
		}
	}

	wnd->image = cv::Mat::zeros(dst_height, dst_width, CV_8UC3);
}

void Display(StDisplayWnd* wnd, cv::Mat& img) { // 图像缩放 
	resize(img, wnd->image, cv::Size(wnd->image.cols, wnd->image.rows)); // 
	::StretchDIBits(wnd->hdc,
		0, 0, wnd->bmi->bmiHeader.biWidth, -wnd->bmi->bmiHeader.biHeight,
		0, 0, wnd->image.cols, wnd->image.rows,
		wnd->image.data, wnd->bmi, DIB_RGB_COLORS, SRCCOPY);
}

void releaseDisplay(StDisplayWnd* wnd)
{
	::ReleaseDC(wnd->hwnd, wnd->hdc); unsigned char* buff = (unsigned char*)wnd->bmi;
	delete[] buff;
}

收藏的代码:

/*
 * 图像播放器
 * Mylaf 
 */

#ifndef _ME_IMAGEPLAYER_HEADER_
#define _ME_IMAGEPLAYER_HEADER_

#include "me_opencv_inc.h"
#include "Windows.h"

class CImagePlayer
{
public:
	static const int BUFF_SIZE_BITMAPINFO = sizeof(BITMAPINFOHEADER) + 1024;

public:
	CImagePlayer():hWnd(NULL),bmi(NULL){}
	virtual ~CImagePlayer() { Release(); }

	int Init(HWND hWnd)
	{
		this->hWnd = hWnd;
		this->dcWnd = ::GetDC(hWnd);
		::GetWindowRect(hWnd, &(this->rectWnd));

		int dst_width = ((rectWnd.right - rectWnd.left + 3) >> 2) << 2;
		int dst_height = rectWnd.bottom - rectWnd.top;
		int dst_bpp = 24;// 8 * image.channels();

		this->show = cv::Mat::zeros(dst_height, dst_width, CV_8UC3);

		unsigned char* buff = new unsigned char[BUFF_SIZE_BITMAPINFO];
		memset(buff, 0, BUFF_SIZE_BITMAPINFO);

		this->bmi = (BITMAPINFO*)buff;
		BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);
		memset(bmih, 0, sizeof(*bmih));
		bmih->biSize = sizeof(BITMAPINFOHEADER);
		bmih->biWidth = dst_width;// image.cols;
		bmih->biHeight = -dst_height;// -image.rows;
		bmih->biPlanes = 1;
		bmih->biBitCount = (unsigned short)dst_bpp;
		bmih->biCompression = BI_RGB;

		if (dst_bpp == 8) {
			RGBQUAD* palette = this->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;
			}
		}
		return 0;
	}

	int ReSize(const cv::Mat& image)
	{
		RECT rc;
		::GetWindowRect(hWnd, &rc);
		int width = ((rc.right - rc.left) >> 2) << 2;
		int height = rc.bottom - rc.top;

		if (width != this->show.cols || height != this->show.rows)
		{
			BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);

			bmih->biWidth = width;// image.cols;
			bmih->biHeight = -height;// -image.rows;

			// 需要
			this->show = cv::Mat::zeros(height, width, CV_8UC3);
		}
		return 0;
	}

	int ReColor(const cv::Mat& image)
	{
		BITMAPINFOHEADER* bmih = &(this->bmi->bmiHeader);
		if (bmih->biBitCount != 8 * image.channels())
		{
			bmih->biBitCount = 8 * image.channels();
			if (bmih->biBitCount == 8) {
				RGBQUAD* palette = this->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;
				}
			}
		}
		return 0;
	}

	int Play(const cv::Mat& image)
	{
		if (this->hWnd == NULL || this->bmi == NULL) return -1;

		ReSize(image);
		ReColor(image);

		// 图像缩放
		resize(image, this->show, cv::Size(this->show.cols, this->show.rows));

		// 贴图
		::StretchDIBits(
			this->dcWnd,
			0, 0, this->bmi->bmiHeader.biWidth, -this->bmi->bmiHeader.biHeight,
			0, 0, this->show.cols, this->show.rows,
			this->show.data, this->bmi, DIB_RGB_COLORS, SRCCOPY);

		return 0;
	}

	void Release(void) {
		::ReleaseDC(this->hWnd, this->dcWnd);
		unsigned char* buff = (unsigned char*)this->bmi;
		delete[] buff;

		this->bmi = NULL;
	}

protected:
	HWND hWnd; // 
	HDC  dcWnd;
	RECT rectWnd;
	cv::Mat show;
	BITMAPINFO* bmi;
};

#endif //_ME_IMAGEPLAYER_HEADER_
 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值