Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

linux - Qimage to cv::Mat convertion strange behaviour

I am trying to create an application where I am trying to integrate opencv and qt.

I managed successfully to convert a cv::Mat to QImage by using the code below:

void MainWindow::loadFile(const QString &fileName)
{
    cv::Mat tmpImage = cv::imread(fileName.toAscii().data());
    cv::Mat image;

    if(!tmpImage.data || tmpImage.empty())
    {
        QMessageBox::warning(this, tr("Error Occured"), tr("Problem loading file"), QMessageBox::Ok);
        return;
    }

/* Mat to Qimage */
    cv::cvtColor(tmpImage, image, CV_BGR2RGB);
    img = QImage((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);

    imgLabel->setPixmap(QPixmap::fromImage(img));
    imgLabel->resize(imgLabel->pixmap()->size());

    saveAsAct->setEnabled(true);
}

However, when I am trying to convert the QImage to cv::Mat by using the following code:

bool MainWindow::saveAs()
{
    if(fileName.isEmpty())
    {
        QMessageBox::warning(this, tr("Error Occured"), tr("Problem loading file"), QMessageBox::Close);
        return EXIT_FAILURE;
    }else{
        outputFileName = QFileDialog::getSaveFileName(this, tr("Save As"), fileName.toAscii().data(), tr("Image Files (*.png *.jpg *.jpeg *.bmp)
 *.png
 *.jpg
 *.jpeg
 *.bmp"));

    /* Qimage to Mat */
    cv::Mat mat = cv::Mat(img.height(), img.width(), CV_8UC4, (uchar*)img.bits(), img.bytesPerLine());
    cv::Mat mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC3 );
    int from_to[] = {0,0,  1,1,  2,2};
    cv::mixChannels(&mat, 1, &mat2, 1, from_to, 3);

    cv::imwrite(outputFileName.toAscii().data(), mat);
}

saveAct->setEnabled(true);
return EXIT_SUCCESS;
}

I have no success and the result is totally disordered image. In the net that I searched I saw that the people are using this way without mentioning any specific problems. Does someone have any idea, about what could be cause the problem? Thanks in advance.

Theoodore

P.S. I am using opencv 2.4 and Qt 4.8, under a Arch Linux system with gnome-3.4

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Just find out the "correct" solution of copying(not reference) the QImage to cv::Mat

The answer of Martin Beckett is almost correct

for (int i=0;i<image.height();i++) {
    memcpy(mat.ptr(i),image.scanline(i),image.bytesperline());
}

I don't see the full codes, but I guess you may want to use it like this way

cv::Mat mat(image.height(), image.width(), CV_8UC3);
for (int i=0;i<image.height();i++) {
        memcpy(mat.ptr(i),image.scanline(i),image.bytesperline());
    }

But this code exist a problem, the memory allocated by cv::Mat may not have the same "bytesperline" as the QImage

The solution I found is take the reference of the QImage first, then clone it

return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine()).clone();    

The solution of Martin Beckett suggested could generate correct result in most of the times, I didn't notice there are a bug until I hit it.

Whatever, I hope this is a "correct" solution. If you find any bug(s), please let everyone know so we could have a change to improve the codes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...