opencv与labview的结合(升级版:彩色图像的传输)
OK,上一篇讲完了opencv与Labview实现了黑白图像的传输,结尾有提到彩色图像的传输问题,我也自己试了一下,直接改变unsigned int8 char *data指针为unsigned int32 char *data,最后Labview并没有成功接收到彩色图像,经过网上的查找,有提到说这两者要是实现彩色图像传输,要借助图像的分离与融合,简单说就是把RGB图像的R、G、B三个通道拆分开来,然后逐个通道进行传输,有了上一篇的基础,已经知道了如何传输8bit的图片,实质就是单通道的功能,那么在实现彩色图像传输上也就有了更大的方便性。
原理比较简单,实现起来应该也不难,结果本人在尝试过程中却遇到了许多小问题,在这个过程中我会把要特别注意的细节问题用不同颜色注释:
首先是实现从opencv传输和一幅图像到Labview
关于DLL的创建也不再复述,不知道的可以查看往期的文章,这里主要讲DLL里面的实现代码
定义图像输出的函数名为outImage,函数主体如下:
_declspec(dllexport) extern void outImage(int rows, int cols, unsigned __int8 *imageR, unsigned __int8 *imageG, unsigned __int8 *imageB) { Mat ImgSrc = imread("E:\\study\\VS2015\\practice\\shumaguang\\shumaguang\\30.jpg");//read the image; vectorsbgr(ImgSrc.channels()); split(ImgSrc, sbgr); Mat temp1(rows, cols, CV_8U, &imageR[0]); Mat temp2(rows, cols, CV_8U, &imageG[0]); Mat temp3(rows, cols, CV_8U, &imageB[0]); //cvtColor(ImgSrc, temp1, CV_BGR2GRAY); sbgr[2].copyTo(temp1); sbgr[1].copyTo(temp2); sbgr[0].copyTo(temp3); }
可以看到,函数参数里面定义了三个unsigned __int8 *的指针,这三个指针分别会关联到RGB三个通道图像,函数实现的是读取一张本地文件图片,将这张图片三个通道拆分后存到一个vector中,然后将三个通道分别复制到指针所指向的图像上。
这里要注意两点:
1、图像复制要采用深拷贝,而不能使用浅拷贝,也就是不能直接使用temp1=sbgr[0],而要用sbgr[0].copyTo(temp3);最开始我就因为这个原因卡了许久。关于深拷贝、浅拷贝的差别可自行百度
2、opencv里面Mat图像的RGB三个通道顺序是BGR,所以在进行拷贝时要注意顺序,sbgr[0]对应的是B通道,要对应到参数里的imagB指针,最后在labview里接收到的RGB按本来的顺序即可,否则合并后的图像与原图不符。
反过来是实现从Labview传输图片到opencv中
在DLL中定义接收函数名为getimage,函数主体如下:
_declspec(dllexport) extern void getImage(int rows, int cols, unsigned __int8 *imageR, unsigned __int8 *imageG, unsigned __int8 *imageB) { Mat Image; Mat srcImageR(rows, cols, CV_8U, &imageR[0]); Mat srcImageG(rows, cols, CV_8U, &imageG[0]); Mat srcImageB(rows, cols, CV_8U, &imageB[0]); Mat merger_array_src[] = { srcImageB,srcImageG,srcImageR }; merge(merger_array_src,3,Image); }
也是三个指针参数,分别接收三个通道的图像数据,最后将得到的三通道进行融合
接着就是Labview的代码主体了:
首先给大家看后面板要注意的事项,后面板逻辑如下:
图片中上半部分是实现从Labview传输到opencv中,可以看到将摄像头采集到的RGB图像通过IMAQ ExtractSingleColorPlane函数拆分得到R、G、B三个通道图像,特别注意IMAQ ExtractSingleColorPlane这个函数一定要给Image Dst接线端一个图片缓存区,否则一定会出问题,后续则是将图像转化为数组,连接到DLL getimage函数的参数接口上。
下图是调用getimage函数的参数设置
后面板下半部分就是实现从opencv传输一幅图片到Labview上进行显示
可以看到首先调用的还是getimagesize函数,该函数在上一篇有介绍到,接着就是初始化三通道的数据为0,注意三个通道一定要初始化大小和数值,最后调用IMAQ ReplaceColorPlane 函数实现三通道的合并,最后说一点要注意的,所有IMAQ Creat创建的图像要注意图片的类型,这里涉及到32位和8位图的互相转换,确保所有图片格式正确保证程序的准确性。
最后就是前面板的程序运行结果图片了
可以看到上半部分就是摄像头的捕捉画面,拆分为R、G、B三个通道进行显示了
下半部分就是接收到的来自opencv发送来的三个通道的图片,以及最后组合融合的彩色图片。效果完美!