cv :: Mat para QImage y vuelta

//Lo siento por mi ingles.

Dime, por favor, ¿qué estoy haciendo mal? He leído mucho sobre esto. Y escriba un código, pero tengo un resultado terrible.

Como entiendo en Opencv CV_8UC3 es lo mismo que QImage :: Format_RGB888 , excepto BRG y RGB en consecuencia.

para leer cv :: Mat en este formato que puedo hacer:

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

Entonces, para convertir cv :: Mat a QImage puedo:

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

Hice temp mate porque quiero tener copia de datos en QImage.

Entonces. Para convertirlo de nuevo tengo que hacer:

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

He insertado cvtColor (res, res, CV_BGR2RGB) ; para hacer cv Mat con colores BGR. No sé exactamente qué hay dentro de esta función cvtColor (res, res, CV_BGR2RGB) ;, pero decidí que si cvtColor (res, res, CV_BGR2RGB); cambia los lugares R y B, que cambiarán los lugares de estos colores, porque no encontré CV_BGR2RGB .

Entonces, escribí un progtwig de muestra corto

 #include  #include  #include  #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(); } 

y archivo .pro

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

Y tengo un mal resultado !!! Mi mal resultado

¿Hay alguna? ¡Gente, necesito ayuda!

Agregué información de depuración para obtener cv :: Mat.step y QImage.bytesPerLine () y es diferente.

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

¿Qué significa y puede ser un problema en eso?

El código se ve bien con una excepción.
Gestión de la memoria. cv::Mat no funciona como QImage en este material. Recuerde que QImage usa copia en el mecanismo de escritura y comparte memoria para cada copia. cv::Mat también comparte memoria, pero no copia en escritura (también soy nuevo con open cv (2 semanas), así que no puedo explicar exactamente cómo funciona, pero he tropezado con algunos aplastamientos debido a ese)!
Otra cosa es que cuando está creando QImage desde la memoria, la imagen está usando esta memoria y no se QImage de ella.
El resultado final es que en Linux y Qt5 su código falla debido a problemas con la administración de la memoria. En su captura de pantalla puede ver en la parte superior de la segunda ventana que algo extraño está sucediendo y ve basura en la memoria.

Así que he corregido tus funciones de conversión, funciona perfectamente:

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

Así que ambos tenemos que hacer una lectura sobre la gestión de memoria en open-CV :).

FUERA DE CONTEXTO:
La mejor forma de incluir openCV en proyectos qt en Linux es agregar al archivo pro algo como:

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

No tendrá problemas de ruta al mover el código a otra máquina.

¡Muchas gracias! ¡Realmente funciona! Pero. ¿Por qué la memoria se ha echado a perder? Primero. Tengo un poco de carga de memoria :: Mat

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

luego puse una copia de este cvMat a otro cv: Mat

 cv::Mat temp(src.cols,src.rows,src.type()); cvtColor(src, temp,CV_BGR2RGB); mat1 - [=========================================] temp - [=========================================] 

luego haga QImage a partir de estos datos QImage dest = QImage ((uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage :: Format_RGB888);

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

¿Y luego la temperatura sale del scope y se elimina? QImage no se apropia de él, por lo que la memoria en temp1 y el destino se marcan como libres, y allí el comstackdor puede poner otros datos. ¿Tengo razón?