• QImage 与 cv::Mat 之间的相互转换


    最近做图像处理方面的项目比较多,很多算法自己从头写的话太浪费时间,而且自己写的也不一定完善,早就听说OpenCV在图像处理算法方面功能很强大,一直没时间学习,这次正好项目用到了,临时抱佛脚学习些OpenCV入门知识。因为我的程序界面都是用Qt写的,因此也花了点时间研究了如何将OpenCV 和Qt 融合在一起,协同工作。

    Qt 中处理图像主要用的是QImage类,OpenCV中主要用的是cv::Mat类。下面的两个函数可以用来实现这两个类相互转换。

    [cpp] view plain copy
     
    1. QImage cvMat2QImage(const cv::Mat& mat)  
    2. {  
    3.     // 8-bits unsigned, NO. OF CHANNELS = 1  
    4.     if(mat.type() == CV_8UC1)  
    5.     {  
    6.         QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);  
    7.         // Set the color table (used to translate colour indexes to qRgb values)  
    8.         image.setColorCount(256);  
    9.         for(int i = 0; i < 256; i++)  
    10.         {  
    11.             image.setColor(i, qRgb(i, i, i));  
    12.         }  
    13.         // Copy input Mat  
    14.         uchar *pSrc = mat.data;  
    15.         for(int row = 0; row < mat.rows; row ++)  
    16.         {  
    17.             uchar *pDest = image.scanLine(row);  
    18.             memcpy(pDest, pSrc, mat.cols);  
    19.             pSrc += mat.step;  
    20.         }  
    21.         return image;  
    22.     }  
    23.     // 8-bits unsigned, NO. OF CHANNELS = 3  
    24.     else if(mat.type() == CV_8UC3)  
    25.     {  
    26.         // Copy input Mat  
    27.         const uchar *pSrc = (const uchar*)mat.data;  
    28.         // Create QImage with same dimensions as input Mat  
    29.         QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);  
    30.         return image.rgbSwapped();  
    31.     }  
    32.     else if(mat.type() == CV_8UC4)  
    33.     {  
    34.         qDebug() << "CV_8UC4";  
    35.         // Copy input Mat  
    36.         const uchar *pSrc = (const uchar*)mat.data;  
    37.         // Create QImage with same dimensions as input Mat  
    38.         QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);  
    39.         return image.copy();  
    40.     }  
    41.     else  
    42.     {  
    43.         qDebug() << "ERROR: Mat could not be converted to QImage.";  
    44.         return QImage();  
    45.     }  
    46. }  
    47. cv::Mat QImage2cvMat(QImage image)  
    48. {  
    49.     cv::Mat mat;  
    50.     qDebug() << image.format();  
    51.     switch(image.format())  
    52.     {  
    53.     case QImage::Format_ARGB32:  
    54.     case QImage::Format_RGB32:  
    55.     case QImage::Format_ARGB32_Premultiplied:  
    56.         mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());  
    57.         break;  
    58.     case QImage::Format_RGB888:  
    59.         mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());  
    60.         cv::cvtColor(mat, mat, CV_BGR2RGB);  
    61.         break;  
    62.     case QImage::Format_Indexed8:  
    63.         mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());  
    64.         break;  
    65.     }  
    66.     return mat;  
    67. }  

    程序比较简单,就不多说明了。唯一需要注意的是cvMat 和QImage 对于RGBA 这四个分量的排列顺序是不相同的。转换的时候需要调换一下。但是Qt 的文档中说的很明确,QImage内部数据存储的方式不能保证以后永远不变。所以这个代码也不能保证一直是可用的。

    下面是五个测试用例。基本上把各种常见情况都覆盖了。

    [cpp] view plain copy
     
    1. void test1()  
    2. {  
    3.     cv::Mat mat = cv::imread("Q:\Koala.jpg", cv::IMREAD_UNCHANGED);  
    4.     cv::cvtColor(mat, mat, CV_BGR2BGRA);  
    5.     QImage image = cvMat2QImage(mat);  
    6.     qDebug() << (mat.type() == CV_8UC4);  
    7.     cvNamedWindow("cvMat2QImage RGB32", CV_WINDOW_AUTOSIZE);  
    8.     imshow("cvMat2QImage RGB32", mat);  
    9.     QLabel label;  
    10.     label.setPixmap(QPixmap::fromImage(image));  
    11.     label.show();  
    12.     cv::waitKey(10000);  
    13. }  
    14. void test2()  
    15. {  
    16.     cv::Mat mat = cv::imread("Q:\Koala.jpg", cv::IMREAD_UNCHANGED);  
    17.     cv::cvtColor(mat, mat, CV_BGR2GRAY);  
    18.     QImage image = cvMat2QImage(mat);  
    19.     cvNamedWindow("cvMat2QImage gray", CV_WINDOW_AUTOSIZE);  
    20.     imshow("cvMat2QImage gray", mat);  
    21.     QLabel label;  
    22.     label.setPixmap(QPixmap::fromImage(image));  
    23.     label.show();  
    24.     cv::waitKey(10000);  
    25. }  
    26. void test3()  
    27. {  
    28.     QImage image("Q:\Koala.jpg");  
    29.     image = image.convertToFormat(QImage::Format_RGB32);  
    30.     cv::Mat mat = QImage2cvMat(image);  
    31.     //cv::cvtColor(mat, mat, CV_BGR2RGB);  
    32.     imshow("QImage2cvMat RGB32", mat);  
    33.     cv::waitKey(10000);  
    34. }  
    35.   
    36. void test4()  
    37. {  
    38.     QImage image("Q:\Koala.jpg");  
    39.     image = image.convertToFormat(QImage::Format_RGB888);  
    40.     cv::Mat mat = QImage2cvMat(image);  
    41.     imshow("QImage2cvMat RGB24", mat);  
    42.     cv::waitKey(10000);  
    43. }  
    44. void test5()  
    45. {  
    46.     QImage image("Q:\Koala.jpg");  
    47.     image = image.convertToFormat(QImage::Format_Indexed8);  
    48.     cv::Mat mat = QImage2cvMat(image);  
    49.     imshow("QImage2cvMat Indexed8", mat);  
    50.     cv::waitKey(10000);  
    51. }  
    52. int main(int argc, char *argv[])  
    53. {  
    54.     QApplication a(argc, argv);  
    55.     //test1();  
    56.     //test2();  
    57.     //test3();  
    58.     //test4();  
    59.     //test5();  
    60.     test1();  
    61.     return a.exec();  
    62. }  

    http://blog.csdn.net/liyuanbhu/article/details/46662115

  • 相关阅读:
    javascript中的预编译问题
    五环
    两列布局
    定位以及z-index
    [vijos1234]口袋的天空<最小生成树>
    [讲解]prim算法<最小生成树>
    [noip模拟]B<构造>
    [JZOJ5343]健美猫<模拟>
    [noip模拟]心<并查集>
    [noip模拟]种花<快速幂+结论>
  • 原文地址:https://www.cnblogs.com/findumars/p/6546097.html
Copyright © 2020-2023  润新知