您的位置:首页 > 编程语言

视频二值化处理基本方法以及简单代码实现

2015-05-27 15:22 183 查看
参考了网上的一些博客,基于opencv和vs2010的环境,将图像二值化应用到视频处理中去,下面将方法进行介绍。
方法一:
对RGB彩色图像灰度化以后,扫描图像的每个像素值,值小于127的
将像素值设为0(黑色),值大于等于127的像素值设为255(白色)。该方法的好处是计算
量少速度快。缺点更多首先阈值为127没有任何理由可以解释,其次完全不考虑图像的
像素分布情况与像素值特征。可以说该方法是史最弱智的二值处理方法一点也不为过。

方法二:
最常见的二值处理方法是计算像素的平均值K,扫描图像的每个像素值如像素值大于K
像素值设为255(白色),值小于等于K像素值设为0(黑色)。该方法相比方法一,阈值的
选取稍微有点智商,可以解释。但是使用平均值作为二值化阈值同样有个致命的缺点,
可能导致部分对象像素或者背景像素丢失。二值化结果不能真实反映源图像信息。
代码中大于平均值的设为0,小于设为255

方法三:http://en.wikipedia.org/wiki/Thresholding_(image_processing)
使用近似一维Means方法寻找二值化阈值,该方法的大致步骤如下:
1.一个初始化阈值T,可以自己设置或者根据随机方法生成。
2. 根据阈值图每个像素数据P(n,m)分为对象像素数据G1与背景像素数据G2。(n为
行,m为列)
3.G1的平均值是m1, G2的平均值是m2
4. 一个新的阈值T’ = (m1 + m2)/2
5. 回到第二步,用新的阈值继续分像素数据为对象与北京像素数据,继续2~4步,
直到计算出来的新阈值等于上一次阈值。

编程实现如下:

#include "highgui.h"
#include "cv.h"
//函数声明
void RGB_Gray_Typical(IplImage *tempFrame, IplImage *grayImage);
void BinaryFilter (IplImage *grayImage,IplImage *FliterImage);
void BinaryFilterTypical (IplImage *grayImage,IplImage *FliterImage);
void AverageBinaryFilter (IplImage *grayImage,IplImage *FliterImage);
void ThresholdBinaryFilter(IplImage *grayImage,IplImage *FliterImage);
int main()
{
//确定要读入的AVI视频
CvCapture *capture = cvCreateFileCapture("E:\\新建文件夹\\行车视频.avi");
//将视频文件的下一帧加载到内存
IplImage *tempFrame= cvQueryFrame(capture);
IplImage *grayImage,*FliterImage;
//创建头并分配数据,取与这一帧图大小一样的尺寸,数据类型为无符号8位整型,单通道
grayImage = cvCreateImage(cvSize(tempFrame->width, tempFrame->height),8,1);
FliterImage=cvCreateImage(cvSize(tempFrame->width,tempFrame->height),8,1);

while (IplImage *tempFrame = cvQueryFrame(capture))
{
cvShowImage("原始视频",tempFrame);
//播放原视频
RGB_Gray_Typical(tempFrame, grayImage);//得到灰度图
cvShowImage("灰度视频",grayImage);
BinaryFilter(grayImage,FliterImage);
char c = cvWaitKey(33);
if (c == 27)
{
return 0;
}
cvWaitKey(10);
}
cvReleaseCapture(&capture);
cvReleaseImage(&grayImage);
cvReleaseImage(&FliterImage);
cvDestroyAllWindows();

}
//二值化有很多方法,这里只调用一个二值化函数
void BinaryFilter (IplImage *grayImage,IplImage *FliterImage)
{
//BinaryFilterTypical(grayImage,FliterImage);

//AverageBinaryFilter(grayImage,FliterImage);
ThresholdBinaryFilter(grayImage,FliterImage);
}
void RGB_Gray_Typical(IplImage *tempFrame, IplImage *grayImage)
{
for(int j=0; j<tempFrame->height; j++)
for(int i=0; i<tempFrame->width; i++)
{
//int liv_size = j * img->width + i;//测试循环多少次
uchar *data=( uchar *)(tempFrame->imageData );
int step=tempFrame->widthStep;
//得到某个像素点bgr三个通道的像素值
double B = (double)data[j*step + i*3+0]; //B分量
double G= (double)data[j*step + i*3 + 1]; //G分量
double R = (double)data[j*step + i*3 + 2]; //R分量
//用灰度公式,计算出这个像素点转换后的灰度值GRAY
double GRAY = (double)(0.299 * R+ 0.587 * G + 0.114 * B+0.5);
//把GRAY的值赋给它对应的内存单元
long int index= j*tempFrame->width + i;
grayImage->imageData[index] = GRAY;
//cout<<"liv_size = "<<liv_size<<endl;
}

}
//方法一

void BinaryFilterTypical (IplImage *grayImage,IplImage *FliterImage)
{
for(int j=0; j<grayImage->height; j++)
for(int i=0; i<grayImage->width; i++)
{
uchar *data1=( uchar *)(grayImage->imageData );
if(data1[j*grayImage->width + i]>127)
{ FliterImage->imageData[j*grayImage->width + i]=255;}
else
{ FliterImage->imageData[j*grayImage->width + i]=0;}
}
cvShowImage("二值化视频",FliterImage);

}

//方法二
void AverageBinaryFilter (IplImage *grayImage,IplImage *FliterImage)
{

uchar *data1=( uchar *)(grayImage->imageData );
uchar sum=0;
for(int j=0; j<grayImage->height; j++)
{
for(int i=0; i<grayImage->width; i++)
{

sum=uchar(sum+data1[j*grayImage->width + i]);

}

}
uchar Average=uchar(sum/(grayImage->height*grayImage->width));
for(int j=0; j<grayImage->height; j++)
{
for(int i=0; i<grayImage->width; i++)
{

if(data1[j*grayImage->width + i]>Average)
{ FliterImage->imageData[j*grayImage->width + i]=0;}

else

{ FliterImage->imageData[j*grayImage->width + i]=255;}
}
}
cvShowImage("平均二值化视频",FliterImage);
}

//方法三
void ThresholdBinaryFilter(IplImage *grayImage,IplImage *FliterImage)
{
uchar inithreshold = 127; //初始化阈值设置为127
uchar finalthreshold =0;
//uchar newthreshold;
uchar sum1=0;
uchar sum2=0;
int number1=0;
int number2=0;
uchar *data1=( uchar *)(grayImage->imageData );
while(finalthreshold != inithreshold) {
finalthreshold = inithreshold;
//统计大于阈值的像素值总和,和小于阈值的像素值总和
for(int j=0; j<grayImage->height; j++)
{
for(int i=0; i<grayImage->width; i++)
{

if(data1[j*grayImage->width + i]>inithreshold)
{ sum1=uchar(sum1+data1[j*grayImage->width + i]);
}

else
{ sum2=uchar(sum2+data1[j*grayImage->width + i]); }
}
}
//统计大于阈值的个数,小于阈值的像素个数
for(int j=0; j<grayImage->height; j++)
{
for(int i=0; i<grayImage->width; i++)
{

if(data1[j*grayImage->width + i]>inithreshold)
{ number1=number1+1;
}

else
{ number2=number2+1; }
}
}
//分别计算这两种点的均值,再除以2,作为下一次的阈值
uchar Average1=uchar(sum1/number1);
uchar Average2=uchar(sum2/number2);
inithreshold =uchar(( Average1+Average2)/2);

for(int j=0; j<grayImage->height; j++)
{
for(int i=0; i<grayImage->width; i++)
{
if(data1[j*grayImage->width + i]>inithreshold)
{ FliterImage->imageData[j*grayImage->width + i]=0;}

else

{ FliterImage->imageData[j*grayImage->width + i]=255;}
}
}
}
cvShowImage("阈值二值化视频",FliterImage);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐