cv::Mat 到 QImage 并返回 [英] cv::Mat to QImage and back

查看:32
本文介绍了cv::Mat 到 QImage 并返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

//对不起我的英语.

请告诉我,我做错了什么?我已经阅读了很多关于这方面的内容.并写了一些代码,但结果很糟糕.

Tell me please, what I am doing wrong? I have read a lot about this. And write some code, but I have a terrible result.

据我所知在 Opencv 中 CV_8UC3QImage::Format_RGB888 相同,除了相应的 BRG 和 RGB.

As I understand in Opencv CV_8UC3 is the same as QImage::Format_RGB888 , except BRG and RGB accordingly.

以这种格式读取 cv::Mat 我可以这样做:

to read cv::Mat in this format I can do:

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

所以,要将 cv::Mat 转换为 QImage 我可以这样做:

So, to convert cv::Mat to QImage I can do:

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 中复制数据.

I made temp mat becouse I want to have copy of data in QImage.

那么.要将其转换回我必须做的:

Then. To convert it back I Have to do:

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); 改变 R 和 B 的位置,这将改变这种颜色的位置,因为我没有找到 CV_BGR2RGB.

I have inserted cvtColor(res, res,CV_BGR2RGB); to make cv Mat with BGR colors. I do not exactly know what in inside this function cvtColor(res, res,CV_BGR2RGB);, But I decided that if cvtColor(res, res,CV_BGR2RGB); change places R and B, that will chage places of this colors back, because I did not found CV_BGR2RGB.

所以,我写了一个简短的示例程序

So, I wrote short sample 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();
}

和 .pro 文件

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

我得到了一个糟糕的结果!!!

And I have got a BAD result!!!

有吗?各位,我需要帮助!

Is there some? People,I need help!

我添加了一些调试信息来获取 cv::Mat.step 和 QImage.bytesPerLine() 并且它是不同的.

I added some debug info to get cv::Mat.step and QImage.bytesPerLine() and it is different.

alex@lenovo /media/Files/Programming/Cpp/tests/QImagecvMat $ ./QcvMat 
cv step  942 
QImage  bytesPerLine  944 
cv step  942 
QImage  bytesPerLine  944 

这是什么意思,可能有什么问题?

What does it means and may be problem in it?

推荐答案

代码看起来不错,但有一个例外.
内存管理.cv::Mat 在这个材料中不像 QImage 那样工作.请记住,QImage 使用写时复制机制并为每个副本共享内存.cv::Mat 也共享内存,但它不会在写入时进行复制(我也是 open cv 的新手(2 周),所以我无法确切解释它是如何工作的,但我'因为那个,我偶然发现了一些迷恋)!
另一件事是,当您从内存中创建 QImage 时,图像正在使用此内存并且不拥有它的所有权.
最终结果是,在 Linux 和 Qt5 上,您的代码由于内存管理问题而崩溃.在屏幕截图中,您可以在第二个窗口的顶部看到发生了一些奇怪的事情,并且您会看到一些内存垃圾.

Code looks fine with one exception.
Memory management. cv::Mat doesn't work like QImage in this mater. Remember that QImage is using copy on write mechanism and shares memory for each copy. cv::Mat also shares memory but it doesn't do copy on write (I'm also new with open cv (2 weeks) so I can't explain yet exactly how it works but I've stumbled on some crushes because of that)!
Another thing is that when you are creating QImage from memory image is using this memory and doesn't take ownership of it.
Final outcome is that on Linux and Qt5 your code is crashes because of problems with memory management. On your screen shot you can see at the top of second window that something strange is going on and you see some memory trash.

所以我更正了你的转换函数,它完美地工作:

So I've corrected your conversion functions it works perfectly:

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 中内存管理的内容:)

So we both have to do a reading about memory management in open-CV :).

离题:
在 Linux 上的 qt 项目中包含 openCV 的最佳方法是添加到 pro 文件中,例如:

OFFTOPIC:
Best way to include openCV in qt projects on Linux is to add to pro file something like:

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

将代码移动到另一台机器时,您将不会遇到路径问题.

You will be free of path problems when moving code to another machine.

这篇关于cv::Mat 到 QImage 并返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆