stm32f407使用OV7725使用迭代阈值法进行图像二值化,图像分割

stm32f407使用OV7725进行采集数据,显示到LCD屏幕上面,再进行灰度处理,然后再寻找图像分割的灰度阈值,进行图像二值化。

关于图像分科可以自己百度。。。。大笑大笑


首先进行摄像头的图像采集,使用的是野火带FIFO的OV7725摄像头,帧速率有点慢,但是勉强还能采集数据显示。

但是在采集数据的时候,注意读时序要时间问题,否则会因为时序问题导致图像漂移,如下图:

所以在代码里面的void ImagDisp(void)函数里面处理数据要少。


函数里面void OV7725_GRAY_Serial(void)函数是数据发送给上位机查看灰度图等级直方图和曲线,附件里面带labview的直方图上位机子VI。


接下来是重点,迭代阈值法。

首先来迭代阈值法的思想,主要是下面4条:

迭代法是基于逼近的思想,其步骤如下:


1.  求出图象的最大灰度值和最小灰度值,分别记为Pmax和Pmin,令初始阈值T0=(Pmax+Pmin)/2;


2.  根据阈值T(k)(k=0,1,2...,k)将图象分割为前景和背景,分别求出两者的平均灰度值H1和H2;


3.  求出新阈值T(k+1)=(H1+H2)/2;


4.  若 T(k)-T(k+1)=X  (一个预定义的参数范围内,自己设定),则所得即为阈值;否则转2,迭代计算。

这样就可以逐渐逼近图像二值化阈值,不必使用上位机查看大概的阈值,然后手动分割。

具体函数如下:


#define PIXEL_W      320      //设定的采集图像的长
#define PIXEL_H      180      //设定的采集图像的宽  


/****************************************************
* 函数名:Itera_Threshold
* 功  能:迭代阈值法,能够找到灰度图的最佳二值化点
****************************************************/
void Itera_Threshold(void)
{
  u16 i=0,j=0,k=0,cnt=0,mux=0,Camera_Data=0;
u8 newthreshold=0;
u16 Pmax=0,Pmin=0;
u32 sum_h1=0,sum_h2=0;


//数据清空
for( i=0; i<256; i++ )
{
 gray_test_value[i] = 0;
}

for( i=0; i<PIXEL_H; i++ )
{
 for( j=0; j<PIXEL_W; j++ )
{
 mux = pixel[i][j];                     //获取灰度图的数据

//像素点数自增       
gray_itera_threshold[mux]++;
}
}

Pmin = gray_itera_threshold[0];
Pmax = gray_itera_threshold[0];
for( cnt=0; cnt<256; cnt++ )
{
 if( Pmin>gray_itera_threshold[cnt] ){
 Pmin = gray_itera_threshold[cnt];
}
if( Pmax<gray_itera_threshold[cnt] ){
 Pmax = gray_itera_threshold[cnt];
}
}

printf("the Pmax is %d\n",Pmax);
printf("the Pmin is %d\n",Pmin);

//初始阈值
threshold_h[0] = ( Pmax + Pmin ) / 2;

//寻找最佳阈值
for( k=0; k<256; k++ )
{
//分割前景和背景
for( cnt=0; cnt<threshold_h[k]; cnt++ )
{
sum_h1 += gray_itera_threshold[cnt];
}
for( cnt=threshold_h[k]; cnt<256; cnt++ )
{
sum_h2 += gray_itera_threshold[cnt];
}
sum_h1 /= threshold_h[k];
sum_h2 /= (256-threshold_h[k]);

//计算出新的阈值
threshold_h[k+1] = ( sum_h1 + sum_h2 ) / 2; 

if( fabs(threshold_h[k]-threshold_h[k+1]) <= GRAY_BREAK_RANGE ){
newthreshold = threshold_h[k+1];
 break;
}

sum_h1 = 0;
sum_h2 = 0;
}


printf("the newthreshold is %d\n",newthreshold);

//在液晶屏上面写入图像分割后的图像
        LCD_SetCursor(0,0);
LCD_WriteIndex(0x22); //准备写入数据
//根据最佳阈值将图像二值化
for( i=0; i<PIXEL_H; i++ )
{
 for( j=0; j<PIXEL_W; j++ )
{
 mux = pixel[i][j];                     //获取灰度图的数据
 //图像二值化
if( mux > newthreshold ){
 mux = 255;
}
else{
 mux = 0;
}

Camera_Data =  GRAY_TO_RGB(mux);
                       LCD_WriteData(Camera_Data);

}
}
}


这样就能够找到阈值点,然后再进行图像二值化。

这里我使用的芯片是stm32f407ZET6,内部的RAM比较大,192K,所以能够存储 static u8 pixel[PIXEL_H][PIXEL_W];


程序里面的#define GRAY_BREAK_RANGE     1    //阈值允许参数   

可以微调阈值的大小


实验效果:

按键按下前,摄像头移植在采集数据并且在LCD上面显示,如下图:


图像分割按键按下后,出现的图片如下图:




由于这里不能上传代码文件,所以在资源里面上传了,代码和上位机的下载地址如下:

http://u.download.csdn.net/upload/success

希望能够帮助到一起学习的朋友大笑大笑

  • 19
    点赞
  • 141
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值