緊接著上一篇博文,因為direct2d的方式不夠穩(wěn)定,所以博主急需要找到其他的方法,實現(xiàn)把opencv的Mat顯示到指定的窗體中。
本博文主要記錄基于CImage類的實現(xiàn)。
1、要使用微軟提供的CImage類需要包含頭文件:
#include <atlimage.h> 2、要使用的三個函數(shù)(1)改變Mat圖像的大小,以適應窗體
BOOL GetFixMat(const cv::Mat& src_img, cv::Mat& dst_img, unsigned int dc_heigh, unsigned int dc_width){ if (!src_img.data) { return FALSE; } unsigned int img_rows(src_img.rows); unsigned int img_cols(src_img.cols); unsigned int fix_heigh(chaoMin(img_rows, dc_heigh)); unsigned int fix_width(chaoMin(img_cols, dc_width)); float ratio_w = static_cast<float>(fix_width) / static_cast<float>(img_cols); float ratio_h = static_cast<float>(fix_heigh) / static_cast<float>(img_rows); float ratio = chaoMin(ratio_w, ratio_h); int show_width = static_cast<unsigned int>(ratio * img_cols); int show_height = static_cast<unsigned int>(ratio * img_rows); cv::resize(src_img, dst_img, cv::Size(show_width, show_height), (0.0), (0.0), cv::INTER_LINEAR); return TRUE;}(2)將Mat轉(zhuǎn)換成CImage
BOOL ConvertMat2CImage(const cv::Mat& src_img, CImage& dst_img){ if (!src_img.data) { return FALSE; } int width = src_img.cols; //獲取輸入圖像的寬度 int height = src_img.rows; //獲取輸入圖像的高度 int channels = src_img.channels(); //獲取輸入圖像的 int src_type = src_img.type(); dst_img.Destroy(); switch (src_type) { case CV_8UC1: { dst_img.Create(width, -1 * height, 8 * channels); unsigned char* dst_data = static_cast<unsigned char*>(dst_img.GetBits()); int step_size = dst_img.GetPitch(); //獲取位圖行與行之間相差的字節(jié)數(shù) unsigned char* src_data = nullptr; for (int i = 0; i < height; i++) { src_data = const_cast<unsigned char*>(src_img.ptr<unsigned char>(i)); //獲取行指針 for (int j = 0; j < width; j++) { if (step_size > 0) { *(dst_data + step_size*i + j) = *src_data++; } //像素的排列方式是自左上開始的 else { *(dst_data + step_size*i - j) = *src_data++; } } } break; } case CV_8UC3: { dst_img.Create(width, height, 8 * channels); unsigned char* dst_data = static_cast<unsigned char*>(dst_img.GetBits()); int step_size = dst_img.GetPitch(); //獲取位圖行與行之間相差的字節(jié)數(shù) unsigned char* src_data = nullptr; for (int i = 0; i < height; i++) { src_data = const_cast<unsigned char*>(src_img.ptr<unsigned char>(i)); //獲取行指針 for (int j = 0; j < width; j++) { for (int k = 0; k < 3; k++) { *(dst_data + step_size*i + j * 3 + k) = src_data[3 * j + k]; } } } break; } default: MessageBox(NULL, _T("輸入的圖像類型出錯"), _T("提示"), MB_ICONINFORMATION | MB_OK); break; } return TRUE;}(3)將CImage顯示到窗體BOOL Show2DC(const cv::Mat& img, HDC dst_hdc, unsigned int dc_heigh, unsigned int dc_width){ if (!img.data) { return FALSE; } CImage dst_img; cv::Mat temp; //定義中間變量 GetFixMat(img, temp, dc_heigh, dc_width); //圖像的幾何大小變換 ConvertMat2CImage(temp, dst_img); //圖像轉(zhuǎn)換 int offsetx = (dc_width - temp.cols) / 2; //調(diào)整偏移量 int offsety = (dc_heigh - temp.rows) / 2; BOOL temp1 = dst_img.Draw(dst_hdc, offsetx, offsety, dst_img.GetWidth(), dst_img.GetHeight()); //圖像顯示 return TRUE;}3、調(diào)用示例void getHanle(HWND formhandle, int HDCwidth, int HDCheight)//記錄傳過來的窗體句柄,和窗體大小{ windowHDC = GetDC(formhandle);//傳過來HWND,得到窗體HDC, windowHeight = HDCheight; windowwidth = HDCwidth;}void showImage(){ int idx = 1; while (true) { if (idx > 3) idx = 1; char filename[100]; sPRintf_s(filename, "%d.bmp", idx); Mat image = imread(filename); if (image.empty()) continue; Show2DC(image, windowHDC, windowHeight, windowwidth); idx++; Sleep(100); }}4、完畢。并且CImage類的方式,在Win7最簡單的系統(tǒng)上都可以使用。over
祝大家編程快樂!
新聞熱點
疑難解答