项目需要,要将cmos相机的数据读出来,并显示出图片来。同事已经通过FPGA+USB的方式,把相机并行数据转成串行,我需要做的就是上位机,找到frame valid和line valid有位,读取一个frame的数据后,显示出来。
设计思路: 三个thread,第一个从usb读数据,第二个处理usb数据包,找frame valid 和 line valid, 第三个负责显示;显示部分通过定义IplImage指针,分配空间,然后通过给imdata赋值,来实现显示。
因为相机是黑白相机,处理难度不大。之前的每个pixel都是8个bits,所以opencv显示起来很容易。但是后来,上级要求每个pixel要有10个bits来表示,本以为很容易实现,后来搞了2天才搞定,决定总结一下经验,供需要的朋友参考一下。
1. opencv 图像深度
图像深度是指存储每个像素所用的位数,也用于量度图像的色彩分辨率.图像深度确定彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数.它决定了彩色图像中可出现的最多颜色数,或灰度图像中的最大灰度等级.比如一幅单色图像,若每个象素有8位,则最大灰度数目为2的8次方,即256.一幅彩色图像RGB3个分量的象素位数分别为4,4,2,则最大颜色数目为2的4+4+2次方,即1024,就是说像素的深度为10位,每个像素可以是1024种颜色中的一种.
opencv 深度显示范围:(也就是说当定义了如下不同深度的时候,像素的灰度值要处于显示范围之中才可以显示出来。否则要进行转换)
测试double型:0.0--1.0之间 IPL_DEPTH_64F 测试float型:0.0--1.0之间 IPL_DEPTH_32F 测试long型:0--65535之间 IPL_DEPTH_32S 测试short int型:-32768--32767之间 IPL_DEPTH_16S 测试unsigned short int型:0--65535之间 IPL_DEPTH_16U 测试char型:-128--127之间 IPL_DEPTH_8S 测试unsigned char型:0--255之间 IPL_DEPTH_8U
2. 图像深度转换
当定义了如下的深度为16的IplImage
IplImage* dst = cvCreateImage(cvGetSize(img),IPL_DEPTH_16U,img->nChannels);
对其进行赋值,先把imdata强制转换成unsigned short型
1 <span style="font-size:18px;">unsigned short* data = (unsigned short *)(pImg->imageData)
2 for ( i=0;i<HEIGH;i++)
3 for( j=0;j<WIDTH;j++)
4 {
5 data[j+i*(WIDTH)] = array[j+i*(WIDTH)];
6 }</span>
处理完后要对其进行显示。直接使用cvShowImage显示是有问题的。要进行深度转换
1 cvMinMaxLoc(dst , &m, &M, NULL, NULL, NULL); // 找出dst中,所有数据的最大值和最小值
2 cvScale(dst , dst , 65535/(M-m), 65535*(-(m+1))/(M-m)); //把dst中的数据映射到0-65535的范围中
3 cvShowImage( "source image", pImg ); //完成了上述深度转换,接下来才能用cvshowImage来显示
3. 图像保存
最后就是要保存图片了,但是对于深度位16的图片,用cvSaveImage是不能够保存的,因为cvSaveImage只能保存深度为8的图片。这里,用imwrite来保存,无压缩,png格式。
1 <span style="font-size:18px;"> vector<int> compression_params;
2 compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
3 compression_params.push_back(0); // 无压缩png.
4 sprintf(fileName, "Picture %d.png", ++countCamera); //生成文件名
5 cv::Mat pImgMat(pImg,0); //把IplImage转换为Mat
6 imwrite(fileName,pImgMat,compression_params); //保存图片</span>