1. 程式人生 > >利用opencv將raw轉換為rgb

利用opencv將raw轉換為rgb

        最近工作中碰到將.raw格式檔案轉換為彩圖格式檔案。待轉換的.raw格式檔案不帶有影象的寬高等資訊,只有影象畫素值資訊,利用opencv介面無法直接讀取。網上查的方法都無法滿足我的需求,經過各種嘗試終於成功了。因此,將該格式下的raw檔案的轉換方法總結下,給自己留個筆記,也希望對opencv的初學者有所幫助。

        raw資料是大多數相機(單板sensor)的原始影象資料,與像.bmp,.jpg等格式的彩圖相比,他的影象畫素只有單個通道,即r,gr,gb和b中的任意一個(gr和gb可以理解為都是g通道)。因此,將raw資料轉換為正常的彩圖,就要補充影象畫素點缺失的另外兩個通道的值,對應的處理演算法稱為去馬賽克(demosaic)或者插值(Bayer Color Filter Array, CFA)。Bayer是raw格式較常用的一種,如圖1,網上有較詳細的資料,這裡不做深入說明。


圖1

        慶幸的是,opencv中的介面cvCvtColor幫我們做了從raw到rgb的轉換。接下來的問題是,只要利用別的方法正確讀取raw資料即可。目前我碰到的raw資料檔案,檔案未儲存影象格式相關資訊(比如寬和高),畫素值內容以二進位制檔案形式儲存,每個畫素值儲存空間為2個位元組。因此,首先將影象畫素值內容從二進位制檔案讀取,然後拷貝到對應的符合opencv介面cvCvtColor轉換的資料結構,最後利用該介面就可以得到結果。以1080p解析度(寬:1920;高:1080)名字為"d6500_1920x1080"的raw為例,其bayer格式是Gb-B-R-GR,轉換程式碼如下:

int raw2rgb(void)
{
	char *rawFileName = "./6500_1920x1080.raw";
	FILE *fp = NULL;
	int ret = 0, width = 1920, height = 1080;

	/*為讀取14bit raw資料分配空間*/
	unsigned short *pRawData = (unsigned short *)calloc(width*height, sizeof(unsigned short));

	if (NULL == pRawData)
	{
		printf("Fail to calloc buf\r\n");
		return -1;
	}
    
	if (NULL == (fp=fopen(rawFileName, "rb")))
	{
		printf("Fail to read %s.\r\n", rawFileName);
		return -2;
	}

        ret = fread(pRawData,sizeof(unsigned short)*width*height,1, fp);
	if (ret != 1)
	{
		printf("Fail to read raw data\r\n");
		return -3;
	}
	
	IplImage *pBayerData = cvCreateImage(cvSize(width,height), 16, 1);
	IplImage *pRgbDataInt16 = cvCreateImage(cvSize(width,height),16,3);
	IplImage *pRgbDataInt8 = cvCreateImage(cvSize(width,height),8,3);
	memcpy(pBayerData->imageData, (char *)pRawData, width*height*sizeof(unsigned short));
	cvCvtColor(pBayerData, pRgbDataInt16, CV_BayerRG2BGR);

	/*將14bit資料轉換為8bit*/
	cvConvertScale(pRgbDataInt16, pRgbDataInt8, 0.015625, 0);

	cvNamedWindow("rgb", 1);
	cvShowImage("rgb", pRgbDataInt8);
	cvWaitKey(0);

	free(pRawData);
	fclose(fp);
	cvDestroyWindow("rgb");
	cvReleaseImage(&pBayerData);
	cvReleaseImage(&pRgbDataInt8);
	cvReleaseImage(&pRgbDataInt16);


	return 0;
}
但是有一點我不明白的地方是,我的raw格式Gb-B-R-GR,但是用cvCvtColor轉換引數是CV_BayerRG2BGR才能轉換對。