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

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

[cpp] view plain copy
print ?
  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.     
  20.     for(i=0;i
  21.     {    
  22.         for(j=0;j
  23.         {    
  24.             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)));    
  25.             temp += abs(data[(i+1)*step+j]-data[i*step+j])+abs(data[i*step+j+1]-data[i*step+j]);    
  26.         }    
  27.     }    
  28.     DR = temp/num;    
  29.     return DR;    
  30. }    
/******************************************************************************** 
*函数描述:  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


        2.色偏检测。
        网上常用的一种方法是将RGB图像转变到CIE L*a*b*空间,其中L*表示图像亮度,a*表示图像红/绿分量,b*表示图像黄/蓝分量。通常存在色偏的图像,在a*和b*分量上的均值会偏离原点很远,方差也会偏小;通过计算图像在a*和b*分量上的均值和方差,就可评估图像是否存在色偏。计算CIE L*a*b*空间是一个比较繁琐的过程,好在OpenCV提供了现成的函数,因此整个过程也不复杂。
[cpp] view plain copy
print ?
  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
  22.     {    
  23.         for(int j=0;j
  24.         {    
  25.             a+=float(LABimg.at(i,j)[1]-128);//在计算过程中,要考虑将CIE L*a*b*空间还原 后同    
  26.             b+=float(LABimg.at(i,j)[2]-128);    
  27.             int x=LABimg.at(i,j)[1];    
  28.             int y=LABimg.at(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. }    
/******************************************************************************************** 
*函数描述:  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(i,j)[1]-128);//在计算过程中,要考虑将CIE L*a*b*空间还原 后同  
            b+=float(LABimg.at(i,j)[2]-128);  
            int x=LABimg.at(i,j)[1];  
            int y=LABimg.at(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),方差也会偏小;通过计算灰度图的均值和方差,就可评估图像是否存在过曝光或曝光不足。函数如下:

[cpp] view plain copy
print ?
  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
  16.     {    
  17.         for(int j=0;j
  18.         {    
  19.             a+=float(GRAYimg.at(i,j)-128);//在计算过程中,考虑128为亮度均值点    
  20.             int x=GRAYimg.at(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. }    
/********************************************************************************************************************************************************* 
*函数描述:  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(i,j)-128);//在计算过程中,考虑128为亮度均值点  
            int x=GRAYimg.at(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;  
}  


        最后展示一下结果

视频清晰度、色偏以及亮度异常检测_第1张图片视频清晰度、色偏以及亮度异常检测_第2张图片视频清晰度、色偏以及亮度异常检测_第3张图片视频清晰度、色偏以及亮度异常检测_第4张图片视频清晰度、色偏以及亮度异常检测_第5张图片视频清晰度、色偏以及亮度异常检测_第6张图片视频清晰度、色偏以及亮度异常检测_第7张图片



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

你可能感兴趣的:(视频清晰度、色偏以及亮度异常检测)