2016/7/15
在处理视频中,需要对视频流中的图像帧进行区分,分离出其中的亮暗帧图像。区分亮暗图像,是依据图像的平均灰度值来实现的。
我们知道,对于一幅灰度图像,每个像素点的灰度值可以通过指针来访问( i, j )处的灰度值
(img->imageData+ i*img->widthStep)[j*img->nChannels+0]
当然,也可以通过cvGet2D()函数来获取该点的灰度值
cvGet2D(img, i , j).val[0] 或者cvGetReal2D(img , i , j)
对于彩色图像,由于图像具有R/G/B三个通道,所以像素的颜色分量可以通过以下方式来访问:
蓝色通道
(img->imageData+ i*img->widthStep)[j*img->nChannels+0]
绿色通道
(img->imageData+ i*img->widthStep)[j*img->nChannels+1]
红色通道
(img->imageData+ i*img->widthStep)[j*img->nChannels+2]
同理也可以通过函数来访问,如下所示:
蓝色通道
cvGet2D(img , i, j).val[0]
绿色通道
cvGet2D(img , i, j).val[1]
红色通道
cvGet2D(img , i, j).val[2]
一般取三个通道灰度值的平均值作为彩色三通道图像的灰度值
或者采用一种加权的浮点算法
Gray=R*0.299+G*0.587+B*0.114
那么,对于求取整幅图像的平均灰度值,直接的方法就是遍历整幅图像的所有像素点,累加求取所有像素点的灰度值总和,平均灰度值为灰度值总和与像素点个数之商,步骤如下
1) 遍历待处理的源图像src的像素;
2) 对每个像素点的灰度值进行累加求和sum;
3) 计算图像的像素点总个数:n = src->width*src->height;
4) 求图像的平均灰度值:avg_value = sum/n 。
函数代码:
/***求一副图像的平均灰度值*****/
double g_avg_pixel(IplImage *src )
{
if(src==NULL)
return -1;
double g_avg_pixel=0;
IplImage* dst=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src, dst, CV_RGB2GRAY );//彩色转换为灰度图像;
int width=dst->width;
int height = dst->height;
for (introw=0;row
{
for (intcols=0;cols
{
g_avg_pixel+=cvGet2D(dst,row,cols).val[0];
}
}
g_avg_pixel=g_avg_pixel/(width*height);
cvReleaseImage(&dst);//注意该处释放内存,否则循环调用函数时会导致Out Of Memory.
return g_avg_pixel;
}
当然,还有另一种方法,是利用先将彩色图像转为灰度图像,再利用cvAvg()函数进行的。
double get_avg_gray(IplImage *img)
{
IplImage*gray = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
cvCvtColor(img,gray,CV_RGB2GRAY);
CvScalarscalar = cvAvg(gray);
cvReleaseImage(&gray);
return scalar.val[0];
}
与get_avg_gray()函数对应的set_avg_gray(),我也顺手写了。
void set_avg_gray(IplImage *img,IplImage *out,doubleavg_gray)
{
double prev_avg_gray = get_avg_gray(img);
cvConvertScale(img,out,avg_gray/prev_avg_gray);
}
下图为两种方法处理一段视频流的运行结果,可见g_avg_pixel()函数和get_avg_gray()函数计算结果的差异并不明显