opencv 如何将ATL::CImage转换为cv::Mat?

06odsfpq  于 2023-02-23  发布在  其他
关注(0)|答案(3)|浏览(341)

我想把ATL::CImage转换成cv::Mat,以便在opencv(C++)中进行图像处理。您能帮助转换这个对象吗?
我从windows屏幕截图中得到了CImage(使用MFC)。然后,我想在OpenCV Mat对象中处理图像。
我不知道如何改变信仰。

  • C++项目(VC 2017)
  • 多功能控制器
  • OpenCV 3.4.6版本
CImage image;
int cx;
int cy;
CWnd* pWndDesktop = CWnd::GetDesktopWindow();
CWindowDC srcDC(pWndDesktop);

Rect rcDesktopWindow;
::GetWindowRect(pWndDesktop->m_hWnd, %rcDesktopWindow);

cx = (rcDesktopWindow.right - rcDesktopWindow.left);
cy = (rcDesktopWindow.bottom - rcDesktopWindow.top);

image.create(cx, cy, srcDC.GetDeviceCaps(BITPIXEL));

CDC* pDC = CDC::FromHandle(image.GetDC());
pDC->BitBlt(0, 0, cx, cy, &srcDC, 0, 0, SRCCOPY);

image.ReleaseDC();

cv::Mat mat;

// I want set image to mat!
mat = image???

无法将ATL::Image转换为cv::Mat

v64noz0r

v64noz0r1#

如果高度为正值,则CImage创建自下而上位图。必须传递负高度才能为mat创建自上而下位图
使用CImage::GetBits检索位,如下所示:

HDC hdc = GetDC(0);
RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
int cx = rc.right;
int cy = rc.bottom;

CImage image;
image.Create(cx, -cy, 32);

BitBlt(image.GetDC(), 0, 0, cx, cy, hdc, 0, 0, SRCCOPY);
image.ReleaseDC();
ReleaseDC(0, hdc);

cv::Mat mat;
mat.create(cy, cx, CV_8UC4);
memcpy(mat.data, image.GetBits(), cy * cx * 4);

//or borrow pixel data from CImage 
cv::Mat mat(cy, cx, CV_8UC4, image.GetBits());

或强制执行深层复制,如下所示:

cv::Mat mat;
mat = cv::Mat(cy, cx, CV_8UC4, image.GetBits()).clone();

请注意,CImage为像素数据进行了自己的分配,而Mat需要进行自己的分配,或者不得不从CImage中借用,这可能很棘手。
如果你只是截图,你可以使用普通的Windows API,然后直接写入cv::Mat。这样就有了一个单一的分配(快一点),并且mat不依赖于其他对象。例如:

void foo()
{
    HDC hdc = ::GetDC(0);

    RECT rc;
    ::GetClientRect(::GetDesktopWindow(), &rc);
    int cx = rc.right;
    int cy = rc.bottom;
    cv::Mat mat;
    mat.create(cy, cx, CV_8UC4);

    HBITMAP hbitmap = CreateCompatibleBitmap(hdc, cx, cy);
    HDC memdc = CreateCompatibleDC(hdc);
    HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, hbitmap);
    BitBlt(memdc, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY);

    BITMAPINFOHEADER bi = { sizeof(bi), cx, -cy, 1, 32, BI_RGB };
    GetDIBits(hdc, hbitmap, 0, cy, mat.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);

    //GDI cleanup:
    SelectObject(memdc, oldbmp);
    DeleteDC(memdc);
    DeleteObject(hbitmap);
    ::ReleaseDC(0, hdc);
}

编辑:
mat.data = (unsigned char*)image.GetBits();更改为
memcpy(mat.data, image.GetBits(), cy * cx * 4);
ReleaseDC(0, hdc)更改为::ReleaseDC(0, hdc),以避免与CWnd::ReleaseDC(dc)冲突

ogq8wdun

ogq8wdun2#

#include <opencv2\opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <atlimage.h>

using namespace cv;

Mat CImage2Mat(CImage cimg)
{
    BITMAP bmp;
    ::GetObject(cimg.Detach(), sizeof(BITMAP), &bmp);

    int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
    int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;

    IplImage* img = cvCreateImageHeader(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);

    img->imageData = (char*)malloc(bmp.bmHeight * bmp.bmWidth * nChannels * sizeof(char));
    memcpy(img->imageData, (char*)(bmp.bmBits), bmp.bmHeight * bmp.bmWidth * nChannels);
    cvFlip(img, img, 0);
    return cvarrToMat(static_cast<IplImage*>(img));
}

用法:

CImage cimg;
cimg.Load(L"resim.png");

Mat img = CImage2Mat(cimg);
ycl3bljg

ycl3bljg3#

通常,这种情况发生在MFC窗口应用程序开发中的图像处理。我正在开发一个基于MFC的应用程序,它使用EDSDK(佳能SDK)从佳能数码单反相机捕获图像。我使用了这个解决方案(节省时间),我面临的问题是图像分辨率下降!
解决方案在这里!100%工作。https://github.com/wlrl/convertType

相关问题