Mat 显示到MFC中Pictrue Control的问题
時代在進步,近期忙于工作,好久沒能坐在辦公室寫點關于技術的東西了,想想感覺畢業后工作的幾年丟掉了自己的老本行,沒有在程序的海洋里徜徉,而是為了應付客戶和領導開始不斷背離初心。終于現在又有時間寫點東西了,很開心,我又回來了。
好了,閑言碎語不要講,講講今天要說的東西。
以前顯示到Picture Control用的是Iplimage*,但是隨著opencv的不斷更新,我發現opencv作者們開始主推Mat,我們下邊的也只能順應時代。
?
直接上代碼
void CMultipleCameraDlg::ShowMatImgToWnd(UINT ID, const Mat& disimg)//Mat圖像加載到picture control函數 {CWnd *pictureWnd = GetDlgItem(ID);if (disimg.empty()) return ;static BITMAPINFO *bitMapinfo = NULL;static bool First = TRUE;if (First){BYTE *bitBuffer = new BYTE[40 + 4 * 256];//開辟一個內存區域if (bitBuffer == NULL){return;}First = FALSE;memset(bitBuffer, 0, 40 + 4 * 256);bitMapinfo = (BITMAPINFO *)bitBuffer;bitMapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bitMapinfo->bmiHeader.biPlanes = 1;bitMapinfo->bmiHeader.biCompression = BI_RGB; //位圖壓縮類型,必須是 0(不壓縮), 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一for (int i = 0; i<256; i++){ //顏色的取值范圍 (0-255)bitMapinfo->bmiColors[i].rgbBlue = bitMapinfo->bmiColors[i].rgbGreen = bitMapinfo->bmiColors[i].rgbRed = (BYTE)i;}}bitMapinfo->bmiHeader.biHeight = -disimg.rows;bitMapinfo->bmiHeader.biWidth = disimg.cols;bitMapinfo->bmiHeader.biBitCount = disimg.channels() * 8;CRect drect;pictureWnd->GetClientRect(drect); //pWnd指向CWnd類的一個指針 CClientDC dc(pictureWnd);HDC hDC = dc.GetSafeHdc(); //HDC是Windows的一種數據類型,是設備描述句柄;SetStretchBltMode(hDC, COLORONCOLOR);StretchDIBits(hDC,0,0,drect.right, //顯示窗口寬度drect.bottom, //顯示窗口高度0,0,disimg.cols, //圖像寬度disimg.rows, //圖像高度disimg.data,bitMapinfo,DIB_RGB_COLORS,SRCCOPY); }這一段代碼主要用的就是下邊這個
StretchDIBits(hDC,
????????0,
????????0,
????????img.cols,//drect.right, //顯示窗口寬度
????????img.rows,//drect.bottom, //顯示窗口高度
????????0,
????????0,
????????img.cols, //圖像寬度
????????img.rows, //圖像高度
????????img.data,
????????bitMapinfo,
????????DIB_RGB_COLORS,
????????SRCCOPY
????????);
在使用過程中我發現有得圖像顯示的沒問題,但是設置Mat srcROI( src,cvRect(m_ROIX, m_ROIY,roiwidth,roiheight));感興趣區域后,就不對了,數據有錯亂,后來終于找到問題出現原因:是因為字節對齊不一致。
假定位圖頭和調色板完全正確。顯示錯誤的原因:位圖每行數據都4字節對齊,OpenCV的cv::Mat沒有這個對齊。所以數據會錯位。
?
?
接下來在網上找到了強大的網友給出的另一個方案,這個就沒問題了
void LoginDlg::ShowMatImgToWnd(UINT nID, const Mat& srcImg) //Mat顯示 {cv::Mat imgTmp; CRect rect; GetDlgItem(nID)->GetClientRect(&rect); cv::resize(srcImg, imgTmp, cv::Size(rect.Width(), rect.Height())); // 統一轉換為 CV_8UC4 switch (imgTmp.channels()) { case 1: cv::cvtColor(imgTmp, imgTmp, CV_GRAY2BGRA); // GRAY --> BGRA(CV_8UC4) break; case 3: cv::cvtColor(imgTmp, imgTmp, CV_BGR2BGRA); // BGR --> BGRA(CV_8UC4) break; default: break; } // 計算一個像素多少個字節// 其實這里可以換成常量 int pixelBytes = imgTmp.channels()*(imgTmp.depth() + 1); // 使用 BITMAPINFO 結構體創建一個數據頭 BITMAPINFO bitInfo; bitInfo.bmiHeader.biBitCount = 8 * pixelBytes; // 可以換成常量24 bitInfo.bmiHeader.biWidth = imgTmp.cols; bitInfo.bmiHeader.biHeight = -imgTmp.rows; bitInfo.bmiHeader.biPlanes = 1; bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitInfo.bmiHeader.biCompression = BI_RGB; bitInfo.bmiHeader.biClrImportant = 0; bitInfo.bmiHeader.biClrUsed = 0; bitInfo.bmiHeader.biSizeImage = 0; bitInfo.bmiHeader.biXPelsPerMeter = 0; bitInfo.bmiHeader.biYPelsPerMeter = 0; // 顯示 Mat // Mat data + BITMAPINFO --> MFC DigItem CDC *pDC = GetDlgItem(nID)->GetDC(); ::StretchDIBits( pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, rect.Width(), rect.Height(), imgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY ); ReleaseDC(pDC); }?
總結
以上是生活随笔為你收集整理的Mat 显示到MFC中Pictrue Control的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Halcon 记录1
- 下一篇: C++单链表学习随想