您的位置:首页 > 其它

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

2015-09-21 19:32 387 查看
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
希望能够帮助到一起学习的朋友


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息