Cv:: Mat to QImage и обратно - программирование
Подтвердить что ты не робот

Cv:: Mat to QImage и обратно

//Извините за мой английский.

Скажите, пожалуйста, что я делаю неправильно? Я много читал об этом. И напишите какой-то код, но у меня есть ужасный результат.

Как я понимаю в Opencv CV_8UC3 совпадает с QImage:: Format_RGB888, за исключением BRG и RGB соответственно.

читать cv:: Mat в этом формате я могу сделать:

cv::Mat mat1 = cv::imread("bugero.jpg",3); 

Итак, чтобы преобразовать cv:: Mat в QImage, я могу сделать:

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp(src.cols,src.rows,src.type());
     cvtColor(src, temp,CV_BGR2RGB);
     QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     return dest;
}

Я сделал temp mat becouse Я хочу иметь копию данных в QImage.

Тогда. Чтобы преобразовать его обратно, мне нужно:

cv::Mat QImage2Mat(QImage const& src)
{
     QImage temp = src.copy();
     cv::Mat res(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine());
     cvtColor(res, res,CV_BGR2RGB); 
     return res;
}

Я вставил cvtColor (res, res, CV_BGR2RGB); сделать cv Mat с цветами BGR. Я не знаю, что внутри этой функции cvtColor (res, res, CV_BGR2RGB);, но я решил что если cvtColor (res, res, CV_BGR2RGB); изменит места R и B, которые будут исправлять места этих цветов назад, потому что я не нашел CV_BGR2RGB.

Итак, я написал небольшую примерную программу

#include <QApplication>
#include <QtGui>
#include <cv.h>
#include "opencv2/highgui/highgui.hpp"

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp(src.cols,src.rows,src.type()); // make the same cv::Mat
     cvtColor(src, temp,CV_BGR2RGB); // cvtColor Makes a copt, that what i need
     QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     return dest;
}

cv::Mat QImage2Mat(QImage const& src)
{
     QImage temp = src.copy(); 
     cv::Mat res(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine());
     cvtColor(res, res,CV_BGR2RGB); // make convert colort to BGR ! 
     return res; 
}


int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     QWidget W1;
     QWidget W2;
     QLabel imlab1(&W1);
     QLabel imlab2(&W2);
     W1.setWindowTitle("Convert cv::Mat to QImage First time"); 
     W2.setWindowTitle("Convert cv::Mat to QImage Second time");    




     cv::Mat mat1 = cv::imread("bugero.jpg",3);

     QImage qim1  = Mat2QImage(mat1);

     cv::Mat mat2 = QImage2Mat(qim1);

     QImage qim2 = Mat2QImage(mat2); 

     cv::Mat mat3 = QImage2Mat(qim2);



     cv::imshow("First Mat",mat1);
     imlab1.setPixmap(QPixmap::fromImage(qim1)); 
     W1.setFixedSize(qim1.size()); 
     cv::imshow("Convert QImage to cv::Mat firstly",mat2);
     imlab2.setPixmap(QPixmap::fromImage(qim2));
     W2.setFixedSize(qim2.size()); 
     cv::imshow("Convert QImage to cv::Mat secondly",mat2);
     W1.show();
     W2.show();

     return a.exec();
}

и .pro файл

INCLUDEPATH += /usr/local/include/opencv /usr/local/include/opencv2
LIBS += -lopencv_core -lopencv_imgproc\
                                       -lopencv_highgui
QT       += gui
QT       += core
SOURCES += \
    QcvMat.cpp \

И у меня есть ЛУЧШИЙ результат!!! My bad result

Есть ли какие-то? Люди, мне нужна помощь!

Я добавил некоторую отладочную информацию, чтобы получить cv:: Mat.step и QImage.bytesPerLine(), и она отличается.

[email protected] /media/Files/Programming/Cpp/tests/QImagecvMat $ ./QcvMat 
cv step  942 
QImage  bytesPerLine  944 
cv step  942 
QImage  bytesPerLine  944 

Что это значит и может быть проблемой в нем?

4b9b3361

Ответ 1

Код выглядит отлично с одним исключением.
Управление памятью. cv::Mat не работает как QImage в этом мастере. Помните, что QImage использует копию для механизма записи и разделяет память для каждой копии. cv::Mat также разделяет память, но не копирует ее при записи (я также новичок в open cv (2 недели), поэтому не могу объяснить, как именно это работает, но я наткнулся на некоторые раздатки из-за этого )!
Другое дело, что при создании QImage из образа памяти используется эта память и не принимает на себя ответственность. Конечным результатом является то, что в Linux и Qt5 ваш код выходит из строя из-за проблем с управлением памятью. На снимке экрана вы можете видеть в верхней части второго окна, что происходит что-то странное, и вы видите мусор памяти.

Итак, я исправил ваши функции преобразования, которые он отлично работает:

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp; // make the same cv::Mat
     cvtColor(src, temp,CV_BGR2RGB); // cvtColor Makes a copt, that what i need
     QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     dest.bits(); // enforce deep copy, see documentation 
     // of QImage::QImage ( const uchar * data, int width, int height, Format format )
     return dest;
}

cv::Mat QImage2Mat(QImage const& src)
{
     cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
     cv::Mat result; // deep copy just in case (my lack of knowledge with open cv)
     cvtColor(tmp, result,CV_BGR2RGB);
     return result;
}

Итак, мы оба должны сделать чтение об управлении памятью в open-CV:).

OFFTOPIC:
Лучший способ включить openCV в qt-проекты в Linux - добавить в pro файл что-то вроде:

# add open CV
unix {
    CONFIG += link_pkgconfig
    PKGCONFIG += opencv
}

При перемещении кода на другую машину вы будете свободны от проблем с контуром.

Ответ 2

Спасибо большое! Это действительно работает! Но. Почему память, которая испортилась? Первый. У меня есть некоторая загрузка памяти incv:: Mat

cv::Mat mat1 = cv::imread("bugero.jpg",3);

mat1 - [=====================================]

то я поместил копию этого cvMat в другой cv: Mat

cv::Mat temp(src.cols,src.rows,src.type());
cvtColor(src, temp,CV_BGR2RGB);

mat1  -  [=========================================]

temp  -  [=========================================]

затем сделайте QImage из этих данных   QImage dest = QImage ((uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage:: Format_RGB888);

mat1  -   [============================================]

temp  - > [============================================]
         /
dest --/

И затем temp выходит из области видимости и удаляет ее самостоятельно? QImage не принимает на себя ответственность за это, поэтому память в temp1 и dest помечена как свободная, и компилятор может поместить другие данные? Я прав?