opencv的Mat圖像顯示在MFC控件中
方法:
只需要給Mat圖像建立一個位圖信息頭即可;
例:
頭文件中(.h)成員:
cv::Mat m_image
BITMAPINFO *m_imgInfo;
源文件中(.cpp):
BOOL CPointMatchDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加額外的初始化代碼
m_image = cv::imread("E:\\dog.jpeg", cv::IMREAD_UNCHANGED); //(1)
//根據圖像通道數建立圖像信息(這里假定圖像像素為24與32位或者8位(有顏色表的類似))
if(m_image.channels() == 3 || m_image.channels() == 4)
{
m_imgInfo = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFOHEADER)];
}
else //8位,有顏色表
{
m_imgInfo = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)];
//顏色表賦值
for (int i(0); i < 256; ++i)
{
m_imgInfo ->bmiColors[i].rgbBlue = i;
m_imgInfo ->bmiColors[i].rgbGreen = i;
m_imgInfo ->bmiColors[i].rgbRed = i;
m_imgInfo ->bmiColors[i].rgbReserved = 0;
}
}
//頭文件信息(注意由實際顯示情況可得出圖像原點顯示在空間左下角)
m_imgInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_imgInfo->bmiHeader.biBitCount = 8 * m_image .channels();
m_imgInfo->bmiHeader.biHeight = -m_image .rows;
m_imgInfo->bmiHeader.biWidth = m_image .cols;
m_imgInfo->bmiHeader.biPlanes = 1;
m_imgInfo->bmiHeader.biCompression = BI_RGB;
m_imgInfo->bmiHeader.biSizeImage = m_image .channels() * m_image .cols * m_image .rows;
m_imgInfo->bmiHeader.biXPelsPerMeter = 0;
m_imgInfo->bmiHeader.biYPelsPerMeter = 0;
m_imgInfo->bmiHeader.biClrUsed = 0;
m_imgInfo->bmiHeader.biClrImportant = 0;
return TRUE;
}
void CPointMatchDlg::OnPaint()
{
CDC *pDC;
pDC = GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetDC();
CRecr imgCtrlRect;
GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetClientRect(&imgCtrlRect);
pDC->SetStretchBltMode(COLORONCOLOR);
::StretchDIBits(pDC->GetSafeHdc(),
0, 0,
imgCtrlRect.Width(), m_imgCtrlRect.Height(),
0, 0,
m_image.cols, m_image.rows,
m_image.data,
m_imgInfo,
DIB_RGB_COLORS,
SRCCOPY);
ReleaseDC(pDC);
}
注:onPaint中的繪圖程序一定不要放到OnInitDialog中,否則會發現StretchDIBits返回值不為零(說明函數執行正常),但是圖像無法顯示——OnInitDialog中是對話框初始化程序,對話框還沒有初始化完成。OnInitDialog(初始化完成)后系統會自動調用onPaint繪制窗口(則OnInitDialog中顯示圖片沒有意義,會被擦除)。
注意:
這里繪制圖片時,一定要保證Mat圖片符合window圖片要求(即每行字節數為4的倍數),如果不滿足則要進行適當的轉化,否則畫出的圖像會出現問題(圖像不是標准圖像,反而是斜的)。
如果圖片行字節數不是4的倍數,可在語句(1)修改為如下語句:
cv::Mat tempImg = cv::imread("E:\\dog.jpeg", cv::IMREAD_UNCHANGED);
m_image = cv::Mat::zeros(tempImg.rows, (tempImg.cols + 3) / 4 * 4, m_image.type()); //轉化行字節數為4的倍數(這里直接轉化行像素為4的倍數)
tempImage.copyTo(m_image(cv::Rect(0, 0, tempImg.cols, tempImg.rows)));