视频清晰度、色偏以及亮度异常检测

昨天老板临时交代一个活,要求通过算法检测监控设备是否存在失焦、偏色、亮度异常等问题。问题本身不难,在网上查看了一些资料,自己也做了一些思考,方法如下:

        1.失焦检测。

        失焦的主要表现就是画面模糊,衡量画面模糊的主要方法就是梯度的统计特征,通常梯度值越高,画面的边缘信息越丰富,图像越清晰。需要注意的是梯度信息与每一个视频本身的特点有关系,如果画面中本身的纹理就很少,即使不失焦,梯度统计信息也会很少,对监控设备失焦检测需要人工参与的标定过程,由人告诉计算机某个设备正常情况下的纹理信息是怎样的。

  1. /********************************************************************************
  2. *函数描述: DefRto 计算并返回一幅图像的清晰度
  3. *函数参数: frame 彩色帧图
  4. *函数返回值:double 清晰度表示值,针对该视频,当清晰度小于10为模糊,大于14为清楚
  5. *********************************************************************************/
  6. double DefRto(Mat frame)
  7. {
  8. Mat gray;
  9. cvtColor(frame,gray,CV_BGR2GRAY);
  10. IplImage *img = &(IplImage(gray));
  11. double temp = 0;
  12. double DR = 0;
  13. int i,j; //循环变量
  14. int height=img->height;
  15. int width=img->width;
  16. int step=img->widthStep/ sizeof(uchar);
  17. uchar *data=(uchar*)img->imageData;
  18. double num = width*height;
  19. for(i= 0;i<height;i++)
  20. {
  21. for(j= 0;j<width;j++)
  22. {
  23. 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)));
  24. temp += abs(data[(i+ 1)*step+j]-data[i*step+j])+ abs(data[i*step+j+ 1]-data[i*step+j]);
  25. }
  26. }
  27. DR = temp/num;
  28. return DR;
  29. }

        2.色偏检测。

        网上常用的一种方法是将RGB图像转变到CIE L*a*b*空间,其中L*表示图像亮度,a*表示图像红/绿分量,b*表示图像黄/蓝分量。通常存在色偏的图像,在a*和b*分量上的均值会偏离原点很远,方差也会偏小;通过计算图像在a*和b*分量上的均值和方差,就可评估图像是否存在色偏。计算CIE L*a*b*空间是一个比较繁琐的过程,好在OpenCV提供了现成的函数,因此整个过程也不复杂。

  1. /********************************************************************************************
  2. *函数描述: calcCast 计算并返回一幅图像的色偏度以及,色偏方向
  3. *函数参数: InputImg 需要计算的图片,BGR存放格式,彩色(3通道),灰度图无效
  4. * cast 计算出的偏差值,小于1表示比较正常,大于1表示存在色偏
  5. * da 红/绿色偏估计值,da大于0,表示偏红;da小于0表示偏绿
  6. * db 黄/蓝色偏估计值,db大于0,表示偏黄;db小于0表示偏蓝
  7. *函数返回值: 返回值通过cast、da、db三个应用返回,无显式返回值
  8. *********************************************************************************************/
  9. void colorException(Mat InputImg,float& cast,float& da,float& db)
  10. {
  11. Mat LABimg;
  12. cvtColor(InputImg,LABimg,CV_BGR2Lab); //参考http://blog.csdn.net/laviewpbt/article/details/9335767
  13. //由于OpenCV定义的格式是uint8,这里输出的LABimg从标准的0~100,-127~127,-127~127,被映射到了0~255,0~255,0~255空间
  14. float a= 0,b= 0;
  15. int HistA[ 256],HistB[ 256];
  16. for( int i= 0;i< 256;i++)
  17. {
  18. HistA[i]= 0;
  19. HistB[i]= 0;
  20. }
  21. for( int i= 0;i<LABimg.rows;i++)
  22. {
  23. for( int j= 0;j<LABimg.cols;j++)
  24. {
  25. a+= float(LABimg.at<cv::Vec3b>(i,j)[ 1] -128); //在计算过程中,要考虑将CIE L*a*b*空间还原 后同
  26. b+= float(LABimg.at<cv::Vec3b>(i,j)[ 2] -128);
  27. int x=LABimg.at<cv::Vec3b>(i,j)[ 1];
  28. int y=LABimg.at<cv::Vec3b>(i,j)[ 2];
  29. HistA[x]++;
  30. HistB[y]++;
  31. }
  32. }
  33. da=a/ float(LABimg.rows*LABimg.cols);
  34. db=b/ float(LABimg.rows*LABimg.cols);
  35. float D = sqrt(da*da+db*db);
  36. float Ma= 0,Mb= 0;
  37. for( int i= 0;i< 256;i++)
  38. {
  39. Ma+= abs(i -128-da)*HistA[i]; //计算范围-128~127
  40. Mb+= abs(i -128-db)*HistB[i];
  41. }
  42. Ma/= float((LABimg.rows*LABimg.cols));
  43. Mb/= float((LABimg.rows*LABimg.cols));
  44. float M= sqrt(Ma*Ma+Mb*Mb);
  45. float K=D/M;
  46. cast = K;
  47. return;
  48. }

        3.亮度检测。

        亮度检测与色偏检测相似,计算图片在灰度图上的均值和方差,当存在亮度异常时,均值会偏离均值点(可以假设为128),方差也会偏小;通过计算灰度图的均值和方差,就可评估图像是否存在过曝光或曝光不足。函数如下:

  1. /*********************************************************************************************************************************************************
  2. *函数描述: brightnessException 计算并返回一幅图像的色偏度以及,色偏方向
  3. *函数参数: InputImg 需要计算的图片,BGR存放格式,彩色(3通道),灰度图无效
  4. * cast 计算出的偏差值,小于1表示比较正常,大于1表示存在亮度异常;当cast异常时,da大于0表示过亮,da小于0表示过暗
  5. *函数返回值: 返回值通过cast、da两个引用返回,无显式返回值
  6. **********************************************************************************************************************************************************/
  7. void brightnessException (Mat InputImg,float& cast,float& da)
  8. {
  9. Mat GRAYimg;
  10. cvtColor(InputImg,GRAYimg,CV_BGR2GRAY);
  11. float a= 0;
  12. int Hist[ 256];
  13. for( int i= 0;i< 256;i++)
  14. Hist[i]= 0;
  15. for( int i= 0;i<GRAYimg.rows;i++)
  16. {
  17. for( int j= 0;j<GRAYimg.cols;j++)
  18. {
  19. a+= float(GRAYimg.at<uchar>(i,j) -128); //在计算过程中,考虑128为亮度均值点
  20. int x=GRAYimg.at<uchar>(i,j);
  21. Hist[x]++;
  22. }
  23. }
  24. da=a/ float(GRAYimg.rows*InputImg.cols);
  25. float D = abs(da);
  26. float Ma= 0;
  27. for( int i= 0;i< 256;i++)
  28. {
  29. Ma+= abs(i -128-da)*Hist[i];
  30. }
  31. Ma/= float((GRAYimg.rows*GRAYimg.cols));
  32. float M= abs(Ma);
  33. float K=D/M;
  34. cast = K;
  35. return;
  36. }
        最后展示一下结果。

        可以发现:当亮度变低时,失焦检测显示结果为:模糊。这是由于失焦检测依赖于梯度统计,亮度变低时,会导致梯度值整体下降,从而导致检测不正确。一种更好的方法是利用亮度检测的结果,合理设定失焦检测的报警阈值,避免这种情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值