智能车制作
标题: 摄像头直方图阈值算法揭秘--DEMOk [打印本页]
作者: DEMOK 时间: 2014-9-18 17:23
标题: 摄像头直方图阈值算法揭秘--DEMOk
本帖最后由 DEMOK 于 2014-9-18 18:59 编辑
[attach]70225[/attach]
我去年做过一届摄像头,其中对于摄像头阈值的确定方法不断变化,最终采用了直方图二值化,这种动态阈值的适应性很好,我们之后就没有再调过阈值了。
我们采用的岱默公司的OV7620摄像头,摄像头数据隔行采集完毕之后存放于数组Pix_Data1[40][320],这就是一帧图像。
需要定义的变量很多,看起来有点恐怖呃!不着急且听我慢慢道来。。。。。。
unsigned char Num[256]={0};
//该数组用来统计一幅图像每个灰度值的点数,注释:灰度值0-255,比如Num[68]=50就是灰度值是68的像素点有50个
unsigned char *p_Bz;//用于指示某行首地址的指针
int p1;//普通变量
unsigned char Thr=100;//随便给阈值一个初始值
unsigned int total;
float TotalWeight=0,ForeWeight = 0;
float TotalPixels = 0; //进行统计的点数和
float sb;
float fmax1=-1 ;
unsigned int BackNum=0;//当前阈值遍前景图象的点数
unsigned int ForeNum=0;/当前阈值遍后景图象的点数
float BackAvg;//后景的平均灰度值
float ForeAvg;//
前景的平均灰度值
1.统计所选行(二值化为了节约时间只选了几行,不过够用了)中的各灰度值的数目
for(i=13;i<23;i=i+2) //
这里选择第13-23
奇数行,
一行320
的像素点,
{
p_Bz=&
ix_Data1[0][0] + i *320; // p_Bz
这个不用猜了,就是每一行的首地址
for (j = 0; j < 320; j+=2 ) //
为了节约时间也是两个像素统计一个
{
Num[*(p_Bz + j)]++; //
(p_Bz + j
)为每个像素的具体地址*
(p_Bz + j
)为灰度值
}
}
Num[256]
统计完毕哈哈!
2对Num[256]平滑滤波处理,基本思路是:
比如Num[0],Num[1],Num[2],Num[3],Num[4]灰度值0,1,2,3,4的像素点的个数
Num[2]=(Num[0]+Num[1]+Num[2]+Num[3]+Num[4])/5
然后每个点都是与他前后2个数一起平均作为最终值
上代码了!!!
for (i = 0;i<256;i++) //
从0
到第255
个灰度值之间的每一个数值
{
total = 0;
for(j = -2;j<3;j++) //
某灰度值对应的个数为改灰度值上下2
个(共5
个)的平均值
{
p1=i+j;
if(p1<0) //
越界处理
p1=0;
if(p1>255)
p1=255; //
越界处理
total+=Num[p1];
}
Num
=total/5;
}
3.数学计算,有点复杂!!;P
for (i= 0; i< 256; i++)
{
TotalWeight += i * Num;
// 质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),TotalWeight为其总和
TotalPixels +=Num;
// ,256个灰度值对应的像素点的总和 ,total为图象总的点数,归一化后就是累积概率
}
4.假定将某灰度值作为阈值,小于该灰度值的称为前景,大于该灰度值的称为后景,从0-255一个个试探,计算假定灰度得出的值,比较大小,取最小的。
for (i= 0; i< 256; i++) //
{
ForeNum += Num; //ForePixNum为在当前阈值遍前景图象的点数
if (ForeNum == 0)//将0作为阈值虽然肯定不对但都要给机会嘛!!!;P
continue;
BackNum =(int) (TotalPixels - ForeNum); //BackPixNum为背景图象的点数
if (BackNum == 0)
break;
//BackPixNum为0表示全部都是前景图象,与ForePixNum=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环
ForeWeight += i*Num; //前景图像质量矩
ForeAvg = (float)(ForeWeight/ForeNum);//
//前景对应灰度值*前景对应个数 /前景总个数 =前景平均灰度值
BackAvg = (float)(TotalWeight - ForeWeight)/BackNum;
//后景图像平均灰度
sb = (float)(ForeNum * BackNum * (ForeAvg- BackAvg) * (ForeAvg- BackAvg));
最后就是求一个x0(0~255)使得上述公式取得最大值,可以理解成方差最大时阈值上下的灰度值相对于阈值整体靠的更远,界限更加分明。差不多就是蓝布和赛道灰度值中间的数值。if (sb > fmax1) //////方差 { ///////取方差最大时候对应的灰度值为阈值fmax1 = sb;Thr = i; ///////for循环的作用就是取256个灰度值中方差最大时候对应的灰度值为阈值 } }
CCDGateVoltage=Thr;
//终于得到阈值了,好辛苦啊!!!!!!!!
有黄色标记的地方都是公式,无奈显示不了。直接上Word!!!!!!!
作者: Quixote 时间: 2014-9-18 18:24
点个赞、、
作者: 晒太阳的蘑菇 时间: 2014-9-18 19:23
点个赞
作者: mengchen 时间: 2014-9-18 19:41
顶。。。
作者: 何俊 时间: 2014-9-18 22:32
点个赞再保存!
作者: 逢缘 时间: 2014-9-18 22:33
点个赞
作者: 天翊 时间: 2014-9-19 08:01
作者: 六步上篮 时间: 2014-9-19 19:13
赞
作者: wshgdzh123 时间: 2014-9-22 20:24
mark
作者: M16贯穿伤 时间: 2014-9-22 22:47
点个赞
作者: shalian 时间: 2014-11-6 12:04
赞一个
作者: You_zixuan 时间: 2015-1-8 21:11
楼主是不是都把上面的Num[i]简写成Num了
作者: 风456 时间: 2015-3-30 19:27
顶
作者: 刘玉林 时间: 2015-4-8 12:51
赞一个
作者: 牧奎山谷 时间: 2015-4-9 17:22
我移植之后。。我的程序一直卡死。。求教
作者: Sτrīvé___ 时间: 2015-4-9 22:41
飘过的
作者: ℡黑禮服 时间: 2015-6-1 14:44
赞赞赞
作者: guojiawei23 时间: 2015-6-26 10:01
谢谢楼主
作者: 山广东 时间: 2015-8-20 09:22
:):):)
作者: YMH_smartcar 时间: 2015-8-31 09:23
虽然看不懂,但是感觉好厉害
作者: yutuo 时间: 2015-9-26 14:41
学习了
作者: Betic 时间: 2015-10-1 22:04
收藏一下·谢谢分享
作者: zss123 时间: 2016-1-10 11:26
6666666
作者: 公子阿志 时间: 2016-3-10 07:43
赞了再说 哈哈哈
作者: 空心砖君 时间: 2016-3-13 15:36
干货!!
作者: 846061912 时间: 2016-3-18 15:57
点个赞
欢迎光临 智能车制作 (http://dns.znczz.com/) |
Powered by Discuz! X3.2 |