linux – Qimage to cv :: mat convertion奇怪的行为

我正在尝试创建一个应用程序,我试图集成opencv和qt.

我成功地使用以下代码将cv :: Mat转换为QImage

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

但是,当我尝试使用以下代码将QImage转换为cv :: Mat时:

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)\n *.png\n *.jpg\n *.jpeg\n *.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;
}

我没有成功,结果是完全无序的图像.在我搜索的网中,我看到人们正在使用这种方式而没有提到任何具体问题.有人有任何想法,关于可能导致问题的原因是什么?提前致谢.

Theoodore

附:我在使用gnome-3.4的Arch Linux系统下使用opencv 2.4和Qt 4.8

最佳答案 只需找出将QImage复制(不参考)到cv :: Mat的“正确”解决方案

Martin Beckett的答案几乎是正确的

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

我没有看到完整的代码,但我想你可能想要这样使用它

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

但是这段代码存在问题,
由cv :: Mat分配的内存可能与QImage没有相同的“bytesperline”

我找到的解决方案是首先引用QImage,然后克隆它

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

Martin Beckett建议的解决方案可以在大多数情况下产生正确的结果
有时,我没注意到有一个bug,直到我点击它.

无论如何,我希望这是一个“正确”的解决方案.如果您发现任何错误,请告知
每个人都知道,所以我们可以改变以改进代码.

点赞