項目需要,要將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>