• OpenCV和Qt的图像格式互转


    做图像处理的时候经常使需要用到opencv的,这应该是免费的图像处理库中用得最广泛而且最好用的库了吧。然后有时候想用界面来展示点东西的时候,我们就需要编写个界面,编写界面的方法千千万,弱水三千我只取一瓢饮,所以我用Qt来写界面,这个时候,就会想,如果我用OpenCV处理后的图像不会还要用OpenCV的GUI来显示吧,虽然完全可以这么做,但是既然都有个界面了,为啥我们还要用两个窗口来显示呢,于是就有了让OpenCV处理后的图像在Qt写的的界面上显示。

    最简单粗暴无脑的方法就是把OpenCV处理后的图像保存到本地,然后用Qt加载进来,简单粗暴(23333...T_T!!!)。所以后来我找到一些别人的方法,然后我自己再修改一下,就成了我现在一直在用的方法,感觉上还可以,所以就直接上代码吧...等等,还是说一下Mat和QImage都有哪些格式吧。

    首先是cv::Mat,cv::Mat是OpenCV的图像数据类型,是一个类,具体的内容可以参考OpenCV的关于cv::Mat的API,这里要注意几个地方:

    1、指向图像数据的指针:

    uchar* cv::Mat::data

    2、图像的行跟列:

    int cv::Mat::rows
    int cv::Mat::cols

    3、数据类型,这个比较重要,在转为QImage的时候需要用到它来辨别数据格式。

    int cv::Mat::type() const

    OpenCV的图像数据格式如下:

    typedef uint32_t     	uint 
    typedef signed char 	schar
    typedef unsigned char 	uchar
    typedef unsigned short 	ushort
    typedef int64_t 	int64
    typedef uint64_t 	uint64
    #define 	CV_BIG_INT(n)   n##LL
    #define 	CV_BIG_UINT(n)   n##ULL
    #define 	CV_CN_MAX   512
    #define 	CV_CN_SHIFT   3
    #define 	CV_DEPTH_MAX   (1 << CV_CN_SHIFT)
    #define 	CV_8U   0
    #define 	CV_8S   1
    #define 	CV_16U   2
    #define 	CV_16S   3
    #define 	CV_32S   4
    #define 	CV_32F   5
    #define 	CV_64F   6
    #define 	CV_USRTYPE1   7
    #define 	CV_MAT_DEPTH_MASK   (CV_DEPTH_MAX - 1)
    #define 	CV_MAT_DEPTH(flags)   ((flags) & CV_MAT_DEPTH_MASK)
    #define 	CV_MAKETYPE(depth, cn)   (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
    #define 	CV_MAKE_TYPE   CV_MAKETYPE
    #define 	CV_8UC1   CV_MAKETYPE(CV_8U,1)
    #define 	CV_8UC2   CV_MAKETYPE(CV_8U,2)
    #define 	CV_8UC3   CV_MAKETYPE(CV_8U,3)
    #define 	CV_8UC4   CV_MAKETYPE(CV_8U,4)
    #define 	CV_8UC(n)   CV_MAKETYPE(CV_8U,(n))
    #define 	CV_8SC1   CV_MAKETYPE(CV_8S,1)
    #define 	CV_8SC2   CV_MAKETYPE(CV_8S,2)
    #define 	CV_8SC3   CV_MAKETYPE(CV_8S,3)
    #define 	CV_8SC4   CV_MAKETYPE(CV_8S,4)
    #define 	CV_8SC(n)   CV_MAKETYPE(CV_8S,(n))
    #define 	CV_16UC1   CV_MAKETYPE(CV_16U,1)
    #define 	CV_16UC2   CV_MAKETYPE(CV_16U,2)
    #define 	CV_16UC3   CV_MAKETYPE(CV_16U,3)
    #define 	CV_16UC4   CV_MAKETYPE(CV_16U,4)
    #define 	CV_16UC(n)   CV_MAKETYPE(CV_16U,(n))
    #define 	CV_16SC1   CV_MAKETYPE(CV_16S,1)
    #define 	CV_16SC2   CV_MAKETYPE(CV_16S,2)
    #define 	CV_16SC3   CV_MAKETYPE(CV_16S,3)
    #define 	CV_16SC4   CV_MAKETYPE(CV_16S,4)
    #define 	CV_16SC(n)   CV_MAKETYPE(CV_16S,(n))
    #define 	CV_32SC1   CV_MAKETYPE(CV_32S,1)
    #define 	CV_32SC2   CV_MAKETYPE(CV_32S,2)
    #define 	CV_32SC3   CV_MAKETYPE(CV_32S,3)
    #define 	CV_32SC4   CV_MAKETYPE(CV_32S,4)
    #define 	CV_32SC(n)   CV_MAKETYPE(CV_32S,(n))
    #define 	CV_32FC1   CV_MAKETYPE(CV_32F,1)
    #define 	CV_32FC2   CV_MAKETYPE(CV_32F,2)
    #define 	CV_32FC3   CV_MAKETYPE(CV_32F,3)
    #define 	CV_32FC4   CV_MAKETYPE(CV_32F,4)
    #define 	CV_32FC(n)   CV_MAKETYPE(CV_32F,(n))
    #define 	CV_64FC1   CV_MAKETYPE(CV_64F,1)
    #define 	CV_64FC2   CV_MAKETYPE(CV_64F,2)
    #define 	CV_64FC3   CV_MAKETYPE(CV_64F,3)
    #define 	CV_64FC4   CV_MAKETYPE(CV_64F,4)
    #define 	CV_64FC(n)   CV_MAKETYPE(CV_64F,(n))

    这里最最常见和默认的应该是:

    #define     CV_8U   0    
    #define     CV_8UC1   CV_MAKETYPE(CV_8U,1)
    #define     CV_8UC3   CV_MAKETYPE(CV_8U,3)

    然后因为有时候要用到浮点型数据,所以,可能我会用到:

    #define    CV_32F    5 
    #define    CV_64F    6
    #define    CV_32FC1    CV_MAKETYPE(CV_32F,1)
    #define    CV_32FC3    CV_MAKETYPE(CV_32F,3)
    #define    CV_64FC1    CV_MAKETYPE(CV_64F,1)
    #define    CV_64FC3    CV_MAKETYPE(CV_64F,3)

    然后是QImage是Qt提供的图像类型之一,其数据类型有:

    但是,对应上面cv::Mat的类型如下:

    //单通道灰度图
    CV_8UC1 == QImage::Format_Grayscale8
    CV_8U == QImage::Format_Grayscale8
    //三通道图
    CV_8UC3 == QImage::Format_RGB888

    基本上,有这几个类型的转换就够了的,好了,类型说完了,该上代码了:

    QImage mat2qimage(const cv::Mat &mat)
    {
    	if (mat.type() == CV_8UC1 || mat.type() == CV_8U)
    	{
    	    // Copy input Mat
    	    const uchar *pSrc = (const uchar*)mat.data;
    	    // Create QImage with same dimensions as input Mat
    	    QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8);
    	    return image;
    	}
    	// 8-bits unsigned, NO. OF CHANNELS = 3  
    	else if (mat.type() == CV_8UC3)
    	{
    	    // Copy input Mat
    	    const uchar *pSrc = (const uchar*)mat.data;
    	    // Create QImage with same dimensions as input Mat
    	    QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
    	    // Because of the BGR order in opencv, 
    	    // here the rgbSwapped() function is needed.
    	    return image.rgbSwapped();
    	}
    }

    如果要显示的是float或者fouble型的呢...那就转一下吧,应该,上面这两种会更常见一点吧。其实还有QImage转cv::Mat的方法的,但是我觉得...好像不是很有必要,毕竟我更倾向于用Open'CV做图像处理,然后用Qt带来显示。

    草在结它的种子 

    风在摇它的叶子 

    我们站着,不说话

    就十分美好

      -- 顾城

      

    上善若水,为而不争。
  • 相关阅读:
    python的struct模块
    Linux程序设计学习笔记(独乐乐版)
    理解AndroidX
    Android中的样式和主题
    Android中Fragment的使用
    Android 中Dialog的使用
    直接在apk中添加资源的研究
    Android签名生成和互转
    简单扒一下Volley源码,扩展Volley生命周期
    获取android所有联系人信息
  • 原文地址:https://www.cnblogs.com/Bearoom/p/11721776.html
Copyright © 2020-2023  润新知