视频二值化处理基本方法以及简单代码实现
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);
}
方法一:
对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);
}
相关文章推荐
- 简单代码实现LCD菜单(C语言的实现方法---加强版 有视频教程)
- 图像处理中几个基本的处理方法c#代码实现
- 哈希表的【构造方法】【冲突处理方法】及【哈希拉链法的简单代码实现】
- 【iOS开发-113】在storyboard上用AutoLayout,纯代码实现AutoLayout布局方法以及简单动画
- 【iOS开发-113】在storyboard上用AutoLayout,纯代码实现AutoLayout布局方法以及简单动画
- Android平台Camera实时滤镜实现方法探讨(十)--代码地址以及简单介绍(20160118更新)
- HOG特征提取代码(opencv处理基本数据,c语言实现基本算法)
- 快速排序基本思想以及代码实现
- Javascript中获取数组最大值和最小值以及最大值和最小值的下标 没学对象前的最简单最基本的方法
- Android平台Camera实时滤镜实现方法探讨(八)--滤镜基本制作方法(二)简单美颜滤镜
- 8_14 日学到的新知识(简单的工厂模式的实现, MVC 模式的基本概念,软件工程中的四种开发模型, 以及软件工程中的一些小知识点)
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- QT类学习系列(6)- Qt多线程的简单实现以及不能同时处理UI的操作
- 素数判断的三种方法以及简单实现!
- HOG特征提取代码(opencv处理基本数据,c语言实现基本算法)
- A/B 测试的基本概念举例理解以及具体实现方法【传统A/B测试基于后端的 A/B 测试(Back-end AB test),现在基本上基于前端js在客户端进行分流,有更多优点,请看里面】
- JDBC的基本概念理解以及简单实现
- 图像处理基本算法(汇总)以及实现
- Android编程使用GestureDetector实现简单手势监听与处理的方法
- 巧用插件及代码实现VIP视频源码分析观看(基于油猴插件及各大接口网站)【PC以及安卓】