数字图像处理实验自动阈值迭代法及Otsu法姓名:学好:指导老师:王韬时间:2012年5月自动阈值迭代法及Otsu法实验报告一、实验原理大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。
图像的总平均灰度为:u=w0*u0+w1*u1。
从最小灰度值到最大灰度值遍历t,当t使得值g=w0*(u0-u)2+w1*(u1-u)2 最大时t即为分割的最佳阈值。
对大津法可作如下理解:该式实际上就是类间方差值,阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1,总均值为u,根据方差的定义即得该式。
因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。
二、实验步骤自动阈值(迭代法)步骤(1)估计一个阈值T(比如均值)(2)用阈值T将灰度直方图分割成两个区域R1、R2(3)分别计算两个区域R1、R2内的灰度平均值u1和u2(4)选择新阈值T=(u1+u2)/2(5)重复上述工作3~5次,直到前后两次的阈值不变自动阈值(Otsu法)步骤(1).计算直方图(2).设置初值:wi(0)以及ui(0)(3).从1到最大值设置阈值T。
更新wi (t)以及ui (t)。
计算σb(t) * σb(t)。
(4).选取最大σb(t) * σb(t)对应的T三、实验程序#include <afx.h>#include <windows.h>#include <iostream.h>#include <stdlib.h>#include <math.h>int nWidth; //图像宽度int nHeight; //图像高度int nColorBits; //每个像素所占位数int nColor; //图像颜色数int nLen; //图像文件大小,以字节数计int nByteWidth; //图像每行字节数BYTE *lpBitmap; //指向图像首字节的指针BYTE *lpBits; //指向图像实际数据的指针void OpenFile(CString FileName);void SaveFile(CString FileName);void OtusTHreshold(void);/*函数名称OpenFile() 功能:读取一幅BMP图像*/void OpenFile(CString FileName){//创建文件语句HANDLEhFile=::CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN _EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hFile==0){printf("不能打开文件,请重新选择!\n");return;}//读取图像文件DWORD WriteNum;BITMAPFILEHEADER BFH;//文件头ReadFile(hFile,&BFH,14,&WriteNum,NULL);//读取文件头,共14个字节if((BFH.bfType!='MB')||(WriteNum!=sizeof(BITMAPFILEHEADER))){printf("不是BMP位图文件或数据有误!\n");return;}nLen=GetFileSize(hFile,NULL)-sizeof(BITMAPFILEHEADER);//获取文件的长度lpBitmap=new BYTE[nLen];//存放图像,包括图像的信息头、调色板和像素数据ReadFile(hFile,lpBitmap,nLen,&WriteNum,NULL);//读取图像数据//设置全局变量的值BITMAPINFOHEADER *BIH=((BITMAPINFOHEADER *)lpBitmap);//图像文件的信息头nWidth=BIH->biWidth;//图像的宽度nHeight=BIH->biHeight;//图像的高度nColorBits=BIH->biBitCount;//图像的颜色数nByteWidth=(nWidth*nColorBits+31)/32*4;//图像的扫描宽度nColor=(nColorBits>8)?0:(1<<nColorBits);//调色板中的颜色数lpBits=lpBitmap+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*nColor;//指向图像数据的实际位置CloseHandle(hFile);//关闭文件句柄}/*函数名称SaveFile() 功能:保存一幅BMP图像*/void SaveFile(CString FileName){//创建一个文件来保存图像文件HANDLEhFile=::CreateFile(FileName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CR EATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(hFile==0){printf("不能创建文件,请重新选择!\n");return;}//创建一个文件头,并保存到创建的文件中unsigned long WriteNum;BITMAPFILEHEADER BFH;BFH.bfType='MB';BFH.bfSize=nLen+sizeof(BITMAPFILEHEADER);BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+n Color*sizeof(RGBQUAD);BFH.bfReserved1=BFH.bfReserved2=0;WriteFile(hFile,&BFH,sizeof(BITMAPFILEHEADER),&WriteNum,NULL);//保存改变的位图文件数据WriteFile(hFile,(BITMAPINFOHEADER*)lpBitmap,nLen,&WriteNum,NULL);CloseHandle(hFile);//关闭文件句柄}/*图像分割Otsu法*/void Otus(void){int i,j;//循环变量int nGrayHistogram[256];//灰度直方图数组,并初始化memset(nGrayHistogram,0,sizeof(nGrayHistogram));//统计各个灰度级对应的像素个数,并存放到灰度直方图数组中int nPixel;for(j=0;j<nHeight;j++){for(i=0;i<nWidth;i++){nPixel=lpBits[nByteWidth*j+i];//获取当前像素点的灰度值nGrayHistogram[nPixel]++;//对灰度值统计计数}}float u0,u1;//c0组和c1组的均值float w0,w1;//c0组和c1组的概率int nCount0;//c0组的像素总数int nT,nBestT;//阈值和最佳阈值(对应方差最大时的阈值)float fVaria,fMaxVaria=0;//方差和最大方差//统计直方图中像素点的总数,并存放到nSum中int nSum=0;for(i=0;i<256;i++)nSum+=nGrayHistogram[i];//令阈值nT从0遍历到255for(nT=0;nT<256;nT++){//当阈值为nT时,计算c0组的均值和概率u0=0;nCount0=0;for(i=0;i<=nT;i++){u0+=i*nGrayHistogram[i];nCount0+=nGrayHistogram[i];}u0/=nCount0;w0=(float)nCount0/nSum;//当阈值为nT时,计算c1组的均值和概率u1=0;for(i=nT+1;i<256;i++)u1+=i*nGrayHistogram[i];u1/=(nSum-nCount0);w1=1-w0;fVaria=w0*w1*(u0-u1)*(u0-u1);//计算两组间的方差if(fVaria>fMaxVaria)//记录最大方差和最佳阈值{fMaxVaria=fVaria;nBestT=nT;}}//利用最佳阈值对源图像作分割处理for(j=0;j<nHeight;j++){for(i=0;i<nWidth;i++){if(lpBits[j*nByteWidth+i]<nBestT)lpBits[j*nByteWidth+i]=0;elselpBits[j*nByteWidth+i]=255;}}}void main(){char OpenFileName[200];char SaveFileName[200];cout<<"请输入图像路径"<< endl;gets(OpenFileName);cout<<"请输入保存图像路径"<< endl;gets(SaveFileName);OpenFile(OpenFileName);Otus();cout<<"已完成!"<< endl;SaveFile(SaveFileName);delete []lpBitmap;}四、实验结果原图像:处理后图像:。