1. 程式人生 > >視訊清晰度、色偏以及亮度異常檢測[轉]

視訊清晰度、色偏以及亮度異常檢測[轉]

 昨天老闆臨時交代一個活,要求通過演算法檢測監控裝置是否存在失焦、偏色、亮度異常等問題。問題本身不難,在網上查看了一些資料,自己也做了一些思考,方法如下:

        1.失焦檢測。

        失焦的主要表現就是畫面模糊,衡量畫面模糊的主要方法就是梯度的統計特徵,通常梯度值越高,畫面的邊緣資訊越豐富,影象越清晰。需要注意的是梯度資訊與每一個視訊本身的特點有關係,如果畫面中本身的紋理就很少,即使不失焦,梯度統計資訊也會很少,對監控裝置失焦檢測需要人工參與的標定過程,由人告訴計算機某個裝置正常情況下的紋理資訊是怎樣的。

 

/********************************************************************************
*函式描述:DefRto 計算並返回一幅影象的清晰度   
*函式引數:frame  彩色幀圖
*函式返回值:double	清晰度表示值,針對該視訊,當清晰度小於10為模糊,大於14為清楚				  
*********************************************************************************/
double DefRto(Mat frame)
{
	Mat gray;
	cvtColor(frame,gray,CV_BGR2GRAY);
	IplImage *img = &(IplImage(gray));
	double temp = 0;
	double DR = 0;
	int i,j;//迴圈變數
	int height=img->height;
	int width=img->width;
	int step=img->widthStep/sizeof(uchar);
	uchar *data=(uchar*)img->imageData;
	double num = width*height;
 
	for(i=0;i<height;i++)
	{
		for(j=0;j<width;j++)
		{
			temp += sqrt((pow((double)(data[(i+1)*step+j]-data[i*step+j]),2) + pow((double)(data[i*step+j+1]-data[i*step+j]),2)));
			temp += abs(data[(i+1)*step+j]-data[i*step+j])+abs(data[i*step+j+1]-data[i*step+j]);
		}
	}
	DR = temp/num;
	return DR;
}

2.色偏檢測。

        網上常用的一種方法是將RGB影象轉變到CIE L*a*b*空間,其中L*表示影象亮度,a*表示影象紅/綠分量,b*表示影象黃/藍分量。通常存在色偏的影象,在a*和b*分量上的均值會偏離原點很遠,方差也會偏小;通過計算影象在a*和b*分量上的均值和方差,就可評估影象是否存在色偏。計算CIE L*a*b*空間是一個比較繁瑣的過程,好在OpenCV提供了現成的函式,因此整個過程也不復雜。

 

/********************************************************************************************
*函式描述:	calcCast 	計算並返回一幅影象的色偏度以及,色偏方向   
*函式引數:	InputImg 	需要計算的圖片,BGR存放格式,彩色(3通道),灰度圖無效
*			cast    	計算出的偏差值,小於1表示比較正常,大於1表示存在色偏
*			da       	紅/綠色偏估計值,da大於0,表示偏紅;da小於0表示偏綠
*			db       	黃/藍色偏估計值,db大於0,表示偏黃;db小於0表示偏藍
*函式返回值:	返回值通過cast、da、db三個應用返回,無顯式返回值
*********************************************************************************************/
void colorException(Mat InputImg,float& cast,float& da,float& db)
{
	Mat LABimg;
	cvtColor(InputImg,LABimg,CV_BGR2Lab);//參考http://blog.csdn.net/laviewpbt/article/details/9335767
	                                   //由於OpenCV定義的格式是uint8,這裡輸出的LABimg從標準的0~100,-127~127,-127~127,被對映到了0~255,0~255,0~255空間
	float a=0,b=0;
	int HistA[256],HistB[256];
	for(int i=0;i<256;i++)
	{
		HistA[i]=0;
		HistB[i]=0;
	}
	for(int i=0;i<LABimg.rows;i++)
	{
		for(int j=0;j<LABimg.cols;j++)
		{
			a+=float(LABimg.at<cv::Vec3b>(i,j)[1]-128);//在計算過程中,要考慮將CIE L*a*b*空間還原 後同
			b+=float(LABimg.at<cv::Vec3b>(i,j)[2]-128);
			int x=LABimg.at<cv::Vec3b>(i,j)[1];
			int y=LABimg.at<cv::Vec3b>(i,j)[2];
			HistA[x]++;
			HistB[y]++;
		}
	}
	da=a/float(LABimg.rows*LABimg.cols);
	db=b/float(LABimg.rows*LABimg.cols);
	float D =sqrt(da*da+db*db);
	float Ma=0,Mb=0;
	for(int i=0;i<256;i++)
	{
		Ma+=abs(i-128-da)*HistA[i];//計算範圍-128~127
		Mb+=abs(i-128-db)*HistB[i];
	}
	Ma/=float((LABimg.rows*LABimg.cols));
	Mb/=float((LABimg.rows*LABimg.cols));
	float M=sqrt(Ma*Ma+Mb*Mb);
	float K=D/M;
	cast = K;
    return;
}

3.亮度檢測。

        亮度檢測與色偏檢測相似,計算圖片在灰度圖上的均值和方差,當存在亮度異常時,均值會偏離均值點(可以假設為128),方差也會偏小;通過計算灰度圖的均值和方差,就可評估影象是否存在過曝光或曝光不足。函式如下:

/*********************************************************************************************************************************************************
*函式描述:	brightnessException 	計算並返回一幅影象的色偏度以及,色偏方向   
*函式引數:	InputImg 	需要計算的圖片,BGR存放格式,彩色(3通道),灰度圖無效
*			cast    	計算出的偏差值,小於1表示比較正常,大於1表示存在亮度異常;當cast異常時,da大於0表示過亮,da小於0表示過暗
*函式返回值:	返回值通過cast、da兩個引用返回,無顯式返回值
**********************************************************************************************************************************************************/
void brightnessException (Mat InputImg,float& cast,float& da)
{
	Mat GRAYimg;
	cvtColor(InputImg,GRAYimg,CV_BGR2GRAY);
	float a=0;
	int Hist[256];
	for(int i=0;i<256;i++)
	Hist[i]=0;
	for(int i=0;i<GRAYimg.rows;i++)
	{
		for(int j=0;j<GRAYimg.cols;j++)
		{
			a+=float(GRAYimg.at<uchar>(i,j)-128);//在計算過程中,考慮128為亮度均值點
			int x=GRAYimg.at<uchar>(i,j);
			Hist[x]++;
		}
	}
	da=a/float(GRAYimg.rows*InputImg.cols);
	float D =abs(da);
	float Ma=0;
	for(int i=0;i<256;i++)
	{
		Ma+=abs(i-128-da)*Hist[i];
	}
	Ma/=float((GRAYimg.rows*GRAYimg.cols));
	float M=abs(Ma);
	float K=D/M;
	cast = K;
   	return;
}

最後展示一下結果

 可以發現:當亮度變低時,失焦檢測顯示結果為:模糊。這是由於失焦檢測依賴於梯度統計,亮度變低時,會導致梯度值整體下降,從而導致檢測不正確。一種更好的方法是利用亮度檢測的結果,合理設定失焦檢測的報警閾值,避免這種情況。

 

From:視訊清晰度、色偏以及亮度異常檢測