मैं opencv (C++) में इमेज हैंडलिंग के लिए ATL::CImage से cv::Mat में कनवर्ट करना चाहता हूं। क्या आप कृपया इस वस्तु को बदलने में मदद कर सकते हैं?

मुझे विंडोज़ स्क्रीन शॉट (एमएफसी का उपयोग करके) से CImage मिला है। फिर, मैं ओपनसीवी मैट ऑब्जेक्ट में छवि को संभालना चाहता हूं।

मुझे नहीं पता था कि कैसे परिवर्तित किया जाए।

  • सी ++ प्रोजेक्ट (वीसी 2017)
  • एमएफसी
  • ओपनसीवी 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 में नहीं बदल सकते।

4
Kevin Kim 15 मई 2019, 03:26

1 उत्तर

सबसे बढ़िया उत्तर

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 से उधार लेना होगा जो कि मुश्किल हो सकता है।

अगर आप सिर्फ एक स्क्रीन शॉट ले रहे हैं, तो आप इसे सादे विंडोज एपीआई के साथ कर सकते हैं, फिर सीधे 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);

CWnd::ReleaseDC(dc) के साथ विरोध से बचने के लिए ReleaseDC(0, hdc) को ::ReleaseDC(0, hdc) में बदला गया

3
Barmak Shemirani 17 मई 2019, 03:40