2013-06-15 20 views
14

// Benim ingilizce için özür dilerim.cv :: Mat to QImage ve geri

Söyle bana, ne yapıyorum yanlış? Bu konuda çok şey okudum. Ve biraz kod yaz, ama çok kötü bir sonucum var. Ben OpenCV anlamak gibi

CV_8UC3 buna göre BRG ve RGB hariç Qimage :: Format_RGB888 aynıdır. Bu biçimde cv :: Mat okumak için

Yapabileceğim:

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

Yani, Qimage için cv :: Mat dönüştürmek için yapabileceğim:

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

Ben nedeniyle bu derste geçici mat yapılmış QImage'da veri kopyasına sahip olmak istiyorum.

Ardından. Yapacak mı geri dönüştürmek için:

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

ben cvtColor (res, res, CV_BGR2RGB) ekledikten; BGR renkleri ile cv Mat yapmak. Bu fonksiyonun içinde tam olarak ne olduğunu bilmiyorum cvtColor (res, res, CV_BGR2RGB); cvtColor (res, res, CV_BGR2RGB) ise ;, R ve B değişkenlerini değiştir, bu renklerin yerlerini geri döndürecek, çünkü bulamıyorum, CV_BGR2RGB.

Yani, kısa örnek program

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

ve .pro dosya

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

yazdım Ve ben bir KÖTÜ sonucu var !!! My bad result

Bazı var mı? İnsanlar, yardıma ihtiyacım var!

cv :: Mat.step ve QImage.bytesPerLine() öğelerini almak için bazı hata ayıklama bilgilerini ekledim ve farklı.

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

Bu ne anlama geliyor ve sorun olabilir?

cevap

31

Kod bir istisna dışında iyi görünüyor.
Bellek yönetimi. cv::Mat, bu materyalden QImage gibi çalışmıyor. QImage'un yazma mekanizmasında kopya kullandığını ve her kopya için belleği paylaştığını unutmayın. cv::Mat ayrıca hafızayı paylaşır ancak yazım üzerinde kopyalama yapmaz (ayrıca açık cv (2 hafta) ile yeni olduğum için tam olarak nasıl çalıştığını tam olarak açıklayamıyorum ama bu yüzden bazı ezmelerde tökezledim) !
Başka bir şey, bellek görüntüsünden QImage oluştururken bu belleği kullanıyor ve sahipliğini almıyor.
Nihai sonuç, Linux ve Qt5 üzerinde, bellek yönetimi ile ilgili sorunlar nedeniyle kodunuzun çökmesidir.Ekran resminizde ikinci pencerenin üstünde tuhaf bir şeyin olup bittiğini görebiliyorsunuz ve hafızanızı görebiliyorsunuz.

Bu yüzden mükemmel çalışıyor dönüşüm fonksiyonları düzeltilmiş ettik:
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; 
} 

Yani ikimiz de açık CV bellek yönetimi hakkında okuma yapmak zorunda :).

Offtopic: Başka bir makineye kod taşırken yol sorunlarının ücretsiz olacak

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

: Linux üzerinde qt projelerde opencv dahil etmek
iyi yolu gibi pro dosya şey eklemektir.

+2

Sadece 'dest.detach() 'yapamaz ve' dest' iadesi yapamaz mısın? Ayrıca, 'detach() '[belgeler] (http://qt-project.org/doc/qt-5/qimage.html) içinde değildir. Niye ya? Her iki durumda da, [bu çözüm] (http://asmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap/), Qt' rgbSwapped() 'i çalıştıran ve belgelenen kullanır. – takfuruya

+0

Bu bağlantıyı yazdığımda güzel link, bu sayfa henüz mevcut değildi :). Kesinlikle daha iyi bir çözümdür (daha evrensel). CV_8UC1' durumunda (bellek ayrılmamış) bir hata görüyorum. 'CvMatToQPixmap' ile zincirde kullanıldığından ve bu içeriği kopyaladığı için ortaya çıkmadı. Bunun hakkında 'ayırma' belgelenmemiş olduğunu fark etmedim. Böylece bunu düzeltirim. –

+0

Şu an sana sadece sarılabiliyorum! Benim için bir sihir gibi çalıştı, güzel açıklanmış adam! – PRIME

2

Çok Teşekkürler! Gerçekten işe yarıyor! Ama. Neden bellek bozulmuş? İlk önce . Mat

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

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

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

sonra bu veriler Qimage varış = Qimage ((UCHAR gelen Qimage olun: Bazı bellek yükü incv :: Mat

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

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

diğer cv bu cvMat bir kopyasını koymak zorunda *) temp.data, temp.cols, temp.rows, temp.step, QImage :: Format_RGB888);

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

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

Ve daha sonra temp kapsama alanı dışına çıkıyor ve siliniyor mu? QImage sahipliğini almaz, böylece temp1 belleğinde ve dest boş olarak işaretlenir ve orada derleyici başka veriler koyabilir mi? Haklı mıyım

+1

bozuk (mem sızıntı) değil ama bozuk (sarkan işaretçiler). IMO sorunu, Mat2QImage'da yerel "temp" matrisi idi. QImage, bu matrisin belleğine atıfta bulundu ve bu, yerel değişkendir, dolayısıyla bellek "Mat2QImage" dönüş formunda serbest bırakıldı. –