2013-06-15 9 views
14

// 영어로 죄송합니다.cv :: Mat to QImage 및 뒤로

제게 말해주십시오, 내가 뭘 잘못하고있는 걸까요? 나는 이것을 많이 읽었습니다. 그리고 몇 가지 코드를 작성하지만, 나는 끔찍한 결과가 있습니다. 내가 OpenCV의에서 알고있는 것처럼

CV_8UC3 이에 따라 BRG 및 RGB를 제외하고, QImage :: Format_RGB888과 동일합니다. 이 형식으로 이력서 :: 매트를 읽을 수

내가 할 수있는 :

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

을 따라서, 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 (입술, 입술, CV_BGR2RGB)를 삽입 한; BGR 색상으로 cv Mat을 만드는 것. 이 함수의 내부에서 정확히 무엇이 들어 있는지 알지 못한다. 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 

무엇이 의미가 있으며 문제가있을 수 있나요?

답변

31

코드는 한 가지 예외가 있습니다.
메모리 관리. cv::MatQImage처럼 작동하지 않습니다. QImage은 copy on write 메커니즘을 사용하고 각 복사본에 대해 메모리를 공유합니다. cv::Mat도 메모리를 공유하지만 복사시 쓰기를하지 않습니다. (오픈 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; 
} 

그래서 우리 모두는 오픈 CV의 메모리 관리에 대한 책을 읽은를해야 할 :).

논외 다른 컴퓨터에 코드를 이동할 때 당신은 경로 문제가 없어야합니다

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

: 리눅스에서 QT 프로젝트에 OpenCV의를 포함하는
가장 좋은 방법은 같은 프로 파일 무언가에 추가하는 것입니다.

+2

'dest.detach()'를 실행하고'dest'를 리턴 할 수 없습니까? 또한,'detach()'는 [documentation] (http://qt-project.org/doc/qt-5/qimage.html)에 없습니다. 왜? 어느 쪽이든, [이 솔루션] (http://asmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap/)은 Qt의'rgbSwapped()'를 사용하여 작동하고 문서화되어 있습니다. – takfuruya

+0

좋은 링크, 내가이 답변을 쓰고있을 때 아직이 페이지가 존재하지 않았다. :) 확실히 더 나은 해결책입니다 (더 보편적입니다). 나는'CV_8UC1' (메모리가 분리되지 않은) 케이스에 대해 하나의 에러를 봅니다. 그것은'cvMatToQPixmap'과 함께 사슬에서 사용 되었기 때문에 노출되지 않았습니다. 그리고 이것은 내용을 복사합니다. 이 '분리 (detach)'에 관해서는 그것이 문서화되어 있지 않다는 것을 눈치 채지 못했습니다. 그래서 나는 이것을 고칠 것이다. –

+0

나는 너를 지금 안아 줄 수있어! 나를 위해 마술 같이 일했다, 멋지게 사람을 설명했다! – PRIME

2

고마워요! 그것은 진짜로 작동합니다! 하지만. 왜 메모리가 망가 졌는가? 먼저. 매트

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

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

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

다음이 데이터 QImage 이명 령 = QImage ((UCHAR에서 QImage합니다 좀 메모리 부하 incv :: 매트

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

mat1 - [=====================================] 
다음

내가 다른 이력서이 cvMat의 사본을 넣어 가지고 *) temp.data, temp.cols, temp.rows, temp.step, QImage :: Format_RGB888);

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

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

그리고 temp는 범위를 벗어나 스스로 삭제합니다. QImage는 소유권을 가지고 있지 않으므로 temp1과 dest의 메모리는 free로 표시되고 컴파일러는 다른 데이터를 넣을 수 있습니까? 내가 옳은가?

+1

(mem leak)하지만 손상되었습니다 (포인터가 매달려 있음). IMO 문제는'Mat2QImage'의 로컬'temp' 행렬입니다. QImage는 그 행렬의 메모리를 가리키며 로컬 변수이므로 메모리가 반환 형식'Mat2QImage'에서 해제되었습니다. –