问题
I am looking for an efficient way for converting an image stored in opencv Mat variable to a CImage object (CBitmap would be good as well). By efficient I mean both fast, and 'short-spelled'. my extended search resulted with finding code which is manually writing bitmap headers and data to the object, which i'd like to avoid, as i do not quite understand what is going on there. to make things worse it looks a little bit deprecated and produces runtime errors... (i believe i obtained it here: http://howto-code-it.blogspot.com/2011/05/how-to-convert-iplimage-to-hbitmap.html)
as for now i'm just coppying pixels one by one which is not too wise (though i needed to make it work) and it is time to improve performance;)
if anyone could come up with conversion in the other way it would also be appreciated.
回答1:
To copy data, you don't need to do it pixel by pixel. One way is (and its header):
CImage* m_pImg;
cv::Size m_sizeShow;
cv::Mat m_matCVImg;
BITMAPINFO bitInfo;
...
StretchDIBits(m_pImg->GetDC(), 0, 0,
m_sizeShow.width, m_sizeShow.height, 0, 0,
m_sizeShow.width, m_sizeShow.height,
matImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);
Check out http://kvy.com.ua/transformation-of-opencv-image-to-mfc-image-in-msvc-project/ for step-by-step instructions.
回答2:
Some checks are needed because StretchDIBits requires that m_matCVImg must be DWORD aligned and must be continuous
bool ok1 = m_matCVImg.isContinuous();
bool ok2 = (m_matCVImg.cols % 4) == 0;
- ok1: if your m_matCVImg is a ROI or is sparse matrix you can't use StretchDIBits directly
- ok2: your m_matCVImg is DWORD aligned only if it has modulo 4 cols or is 32bit depth
in case your check fails you need to create a temp cv::Mat with right cols
if (!(ok1 && ok2)) {
// create a new cv::Mat using
// m_matCVImg.CopyTo(...) or cv::copyMakeBorder(m_matCVImg,...)
}
finally if your m_matCVImg is grey scale you have to prepare a flat palette in bitInfo.bmiColors;
来源:https://stackoverflow.com/questions/25510743/conversion-between-opencv-mat-and-cimage