Как отобразить OpenCV Mat на MFC View - PullRequest
6 голосов
/ 14 декабря 2011

Я думал, что отображение OpenCV2 Mat на MFC View просто, но это не так. Это только релевантные материалы, которые я нашел в Google .Извините за мое незнание, но я не могу найти никаких других материалов, показывающих, как использовать SetDIBitsToDevice с одномерным массивом, возвращаемым членом data.Более конкретно, мне нужно знать, как указать BITMAPINFO для функции.Вернуться к старому OpenCV в стиле C для работы с MFC?

ОБНОВЛЕНИЕ:

Я нашел пример SetDIBitsToDevice , который на самом деледля старого C-стиля OpenCV.Но было легко преобразовать его для OpenCV2.Есть вещи, которые я должен упомянуть, чтобы заставить его работать:

  1. Метод Bpp не работает должным образом, поскольку глубина Mat возвращает 0. Я просто изменился следующим образом:

    static int Bpp(cv::Mat img) { return 8 * img.channels(); } 
    
  2. Мат не имеет члена происхождения.Но просто поставить 0 хорошо для аргумента источника метода FillBitmapInfo.

Кроме этого, следующий код прекрасно работает.Надеюсь, это поможет и другим разработчикам.

void COpenCVTestView::OnDraw(CDC* pDC)
{
COpenCVTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
    return;
if(pDoc->m_cvImage.empty()) return;
// TODO: add draw code for native data here
int height=pDoc->m_cvImage.rows;
int width=pDoc->m_cvImage.cols;
uchar buffer[sizeof( BITMAPINFOHEADER ) + 1024]; 
BITMAPINFO* bmi = (BITMAPINFO* )buffer; 
FillBitmapInfo(bmi,width,height,Bpp(pDoc->m_cvImage),0);
SetDIBitsToDevice(pDC->GetSafeHdc(), 0, 0, width,
    height, 0, 0, 0, height, pDoc->m_cvImage.data, bmi,
    DIB_RGB_COLORS);
}
void COpenCVTestView::FillBitmapInfo(BITMAPINFO* bmi, int width, int height, int bpp, int origin) 
{ 
assert(bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); 

BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 

memset(bmih, 0, sizeof(*bmih)); 
bmih->biSize = sizeof(BITMAPINFOHEADER); 
bmih->biWidth = width; 
bmih->biHeight = origin ? abs(height) : -abs(height); 
bmih->biPlanes = 1; 
bmih->biBitCount = (unsigned short)bpp; 
bmih->biCompression = BI_RGB; 

if (bpp == 8) 
{ 
    RGBQUAD* palette = bmi->bmiColors; 

            for (int i = 0; i < 256; i++) 
    { 
        palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 
        palette[i].rgbReserved = 0; 
    } 
} 
}

Ответы [ 3 ]

2 голосов
/ 14 декабря 2011

Вот другой возможный способ отображения данных OpenCV в MFC, который я использую и прекрасно работает:

IplImage* image// <-- this contains the image you want to display
CvvImage tempdefault;
RECT myrect;   // <-- specifiy where on the screen you want it to be displayed
myrect.top    =  0;
myrect.bottom = _pictureh;
myrect.left   = _picturex;
myrect.right =  _picturew+_picturex;
tempdefault.Create(_pictureh,_picturew,32);
tempdefault.CopyOf(image);
tempdefault.DrawToHDC(pDC->GetSafeHdc(),&myrect);
1 голос
/ 26 июля 2015

CvvImage недоступен в новых версиях OpenCV. Используя следующий код, вы можете конвертировать Mat в CImage и затем отображать CImage везде, где хотите:

int Mat2CImage(Mat *mat, CImage &img){
  if(!mat || mat->empty())
    return -1;
  int nBPP = mat->channels()*8;
  img.Create(mat->cols, mat->rows, nBPP);
  if(nBPP == 8)
  {
    static RGBQUAD pRGB[256];
    for (int i = 0; i < 256; i++)
        pRGB[i].rgbBlue = pRGB[i].rgbGreen = pRGB[i].rgbRed = i;
    img.SetColorTable(0, 256, pRGB);
  }
  uchar* psrc = mat->data;
  uchar* pdst = (uchar*) img.GetBits();
  int imgPitch = img.GetPitch();
  for(int y = 0; y < mat->rows; y++)
  {
    memcpy(pdst, psrc, mat->cols*mat->channels());//mat->step is incorrect for those images created by roi (sub-images!)
    psrc += mat->step;
    pdst += imgPitch;
  }

  return 0;
}
1 голос
/ 14 декабря 2011

Из MSDN:

lpvBits [in] Указатель на данные цвета, хранящиеся в виде массива байтов.Для получения дополнительной информации см. Следующий раздел «Примечания».

Это указатель, который необходимо инициализировать данными, возвращаемыми из Mat :: data.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...