18

//私の英語でごめんなさい。

私が間違っていることを教えてください。私はこれについて多くのことを読みました。いくつかのコードを書きますが、ひどい結果が得られます。

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) ;を挿入しました。BGRカラーでcv Matを作る。この関数cvtColor(res, res,CV_BGR2RGB) ;の内部が正確にはわかりませんが、 cvtColor(res, res,CV_BGR2RGB); CV_BGR2RGBが見つからなかったため、場所 R と B を変更します。これにより、この色の場所が元に戻ります。

だから、私は短いサンプルプログラムを書きました

#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 

それは何を意味し、問題になる可能性がありますか?

4

2 に答える 2

38

コードは 1 つの例外を除いて問題ないように見えます。
メモリ管理。cv::Matこの問題のようには機能しませんQImageQImageコピー オン ライト メカニズムを使用しており、コピーごとにメモリを共有して いることに注意してください。cv::Matもメモリを共有しますが、コピーオンライトは行いません(私もopen cv(2週間)が初めてなので、それがどのように機能するかをまだ正確に説明することはできませんが、そのためにいくつかのクラッシュに遭遇しました)!
もう1つのことは、QImageメモリイメージから作成している場合、このメモリを使用しており、所有権を取得していないことです。
最終的な結果として、Linux および Qt5 では、メモリ管理の問題によりコードがクラッシュします。スクリーン ショットでは、2 番目のウィンドウの上部に奇妙なことが起こっていることがわかります。また、メモリのゴミがいくつか表示されます。

だから私はそれが完全に動作するあなたの変換関数を修正しました:

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 でのメモリ管理について読む必要があります :)。

オフトピック:
Linux の qt プロジェクトに openCV を含める最善の方法は、pro ファイルに次のようなものを追加することです。

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

コードを別のマシンに移動するときのパスの問題がなくなります。

于 2013-06-16T21:41:39.783 に答える
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 --/

そして、一時は範囲外になり、それ自体を削除しますか? QImageはその所有権を取得しないため、temp1とdestのメモリは空きとしてマークされ、コンパイラは他のデータを配置できますか? 私は正しいですか?

于 2013-06-17T08:43:54.353 に答える