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;
}

Я сделал временный мат, потому что я хочу иметь копию данных в 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 \

И у меня плохой результат !!!
Мой плохой результат

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

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

alex@lenovo /media/Files/Programming/Cpp/tests/QImagecvMat $ ./QcvMat
cv step  942
QImage  bytesPerLine  944
cv step  942
QImage  bytesPerLine  944

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

14

Решение

Код выглядит хорошо с одним исключением.
Управление памятью. 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 :).

НЕ ПО ТЕМЕ:
Лучший способ включить openCV в проекты qt в Linux — добавить в pro-файл что-то вроде:

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

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

32

Другие решения

Большое спасибо! Это действительно работает!
Но. Почему испорчена память?
Первый. У меня какая-то загрузка памяти 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 --/

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

2

По вопросам рекламы [email protected]