opencv - cv::imread 图像未显示在 MFC 的图片框上
问题描述
我正在构建基于对话框的 MFC 应用程序。当我单击按钮时,我可以从文件资源管理器中选择图像,并且该图像也被加载到cv::imread()
. 并且还显示在优化校准中。
我可以使用以下代码在优化校准中加载和显示图像。
void CMFCApplication3Dlg::OnBnClickedButton1()
{
cv::Mat src = cv::imread("D:/source/repos/Testing_Photos/Large/cavalls.png");
Display(src);
}
但不是用下面的代码。
void CMFCApplication3Dlg::OnBnClickedButton1()
{
TCHAR szFilter[] = _T("PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|Bitmap (*.bmp)|*.bmp||");
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, AfxGetMainWnd());
if (dlg.DoModal() == IDC_BUTTON1)
{
CString cstrImgPath = dlg.GetPathName();
CT2CA pszConvertedAnsiString(cstrImgPath);
std::string strStd(pszConvertedAnsiString);
cv::Mat src = cv::imread(strStd);
Display(src);
}
}
以下是“显示”功能。
void CMFCApplication3Dlg::Display(cv::Mat& mat) {
CStatic * PictureB = (CStatic *)GetDlgItem(IDC_STATIC);
CWnd* cwn = (CWnd *)GetDlgItem(IDC_STATIC);
CDC* wcdc = cwn->GetDC();
HDC whdc = wcdc->GetSafeHdc();
RECT rec;
cwn->GetClientRect(&rec);
cv::Size matSize;
matSize = cv::Size(rec.right, rec.bottom);
BITMAPINFO bitmapinfo;
bitmapinfo.bmiHeader.biBitCount = 24;
bitmapinfo.bmiHeader.biWidth = mat.cols;
bitmapinfo.bmiHeader.biHeight = -mat.rows;
bitmapinfo.bmiHeader.biPlanes = 1;
bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapinfo.bmiHeader.biCompression = BI_RGB;
bitmapinfo.bmiHeader.biClrImportant = 0;
bitmapinfo.bmiHeader.biClrUsed = 0;
bitmapinfo.bmiHeader.biSizeImage = 0;
bitmapinfo.bmiHeader.biXPelsPerMeter = 0;
bitmapinfo.bmiHeader.biYPelsPerMeter = 0;
StretchDIBits(
whdc,
0, 0,
matSize.width, matSize.height,
0, 0,
mat.cols, mat.rows,
mat.data,
&bitmapinfo,
DIB_RGB_COLORS,
SRCCOPY
);
}
我对 MFC 很陌生,我真的不知道我错在哪里。请帮我!谢谢你。
解决方案
这不是正确的绘画方法。每次有绘画请求时,图片都会被删除。
这就是CFileDialog
在您绘制图像后立即强制重新绘制的情况。您必须回复OnPaint
or OnDrawItem
,或CStatic::SetBitmap
按照评论中的说明使用。
你可以在CImage
课堂上做到这一点,不需要 OpenCV:
CImage img;
if(S_OK == img.Load(L"unicode.jpg"))
{
CStatic *control = (CStatic*)GetDlgItem(IDC_STATIC);
control->ModifyStyle(0, SS_BITMAP);
auto oldbmp = control->SetBitmap(img.Detach());
if(oldbmp)
DeleteObject(oldbmp);
}
或者您可以使用 OpenCV 创建HBITMAP
句柄。
请注意,OpenCV 不处理 Unicode 文件名。CW2A
将 Unicode 转换为 ANSI 字符编码。如果一个或多个代码点无法在当前活动的代码页中表示,则会失败。为了解决这个问题,我们可以使用CFile
or打开文件std::ifstream
,将其读取为二进制文件,然后使用打开cv::imdecode
。例子:
//open the file from unicode path:
const wchar_t *filename = L"unicode.jpg";
std::ifstream fin(filename, std::ios::binary);
if(!fin.good())
return;
//read from memory
std::vector<char> vec(std::istreambuf_iterator<char>(fin), {});
cv::Mat src = cv::imdecode(vec, cv::IMREAD_COLOR);
if(!src.data)
return;
//create hbitmap
BITMAPINFOHEADER bi = { sizeof(bi), src.cols, -src.rows, 1, 24 };
CClientDC dc(this);
auto hbmp = CreateDIBitmap(dc, &bi, CBM_INIT, src.data, (BITMAPINFO*)&bi, 0);
//send hbitmap to control
auto control = (CStatic*)GetDlgItem(IDC_STATIC);
auto oldbmp = control->SetBitmap(hbmp);
if (oldbmp)
DeleteObject(oldbmp);
推荐阅读
- javascript - 遍历背景图像
- flutter - 我正在写颤振代码,我得到一个与 const (invalid constant value) 相关的错误,代码如下所示
- html - Adobe Animate (HTML5 Canvas) 检查两个影片剪辑的时间线位置,如果两个影片剪辑都在第 2 帧上,则显示另一个影片剪辑
- javascript - 更新一个复杂的状态对象:React
- r - 覆盖数据帧的子集而不进一步拆分
- terraform - 无论如何要模拟 terraform 数据源
- javascript - 将颜色选择器颜色分配给变量并使用 JavaScript 将变量用于 fontcolor
- sqlite - SQLite Versioning. Is it possible to use EXCEPT to show differences between rows where only one column changes?
- .net - 如何使用 Swashbuckle 在生成的 Swagger 文件中生成全局参数?
- python - Python我如何找到一个特定的字符串并将其添加到列表中