opencv之大津法Otsu介绍

来源:互联网 发布:常见的数据备份方式 编辑:程序博客网 时间:2024/06/05 05:29

一、大津法(Otsu)

        所谓大津法(Otsu)就是最大类间差方法,通过统计图像直方图信息来自动确定阈值T,从而来区分前景与背景,说白了就是能自动区分图像前景与背景的二值化。

算法流程描述:

1.遍历图像像素,统计每个像素值出现的次数,即255个bin,统计每个bin像素值的个数;

2.遍历0到255每个像素,以i像素值为当前分类的阈值,在(0~i)范围内计算前景像素平均灰度u0,前景部分像素点数所占比例w0;在(i~155)计算背景像素平均灰度u1,背景部分像素点数所占比例w1;

3.计算当前类间方差varValueI=w0*w1*(u1-u0)*(u1-u0);

4.选择最大类间方差varValueI时的i像素阈值作为区分前景与背景的最佳阈值;

       可喜可贺的是opencv已经把Ostu作为一个阈值分割方法写进了threshold函数;


#include "stdafx.h"#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;double Otsu(Mat&image) {int threshold=0;double maxVariance = 0;double w0=0,w1=0;//前景与背景像素点所占比例double u0=0,u1=0;//前景与背景像素值平均灰度double histogram[256]={0};double Num=image.cols*image.rows;//统计256个bin,每个bin像素的个数for(int i=0;i<image.rows;i++){const uchar * p = image.ptr<uchar>(i);      for(int j=0;j<image.cols;j++){histogram[int(*p++)]++; //cout<<"Histogram[data[i*image.step+j]]++:;"<<histogram[int(*p++)]++<<endl; }}//前景像素统计for(int i=0;i<255;i++){w0=0;w1=0;u0=0;u1=0;for(int j=0;j<=i;j++){w0=w0+histogram[j];//以i为阈值,统计前景像素个数u0=u0+j*histogram[j];//以i为阈值,统计前景像素灰度总和}w0=w0/Num;u0=u0/w0;//背景像素统计for(int j=i+1;j<=255;j++){w1=w1+histogram[j];//以i为阈值,统计前景像素个数u1=u1+j*histogram[j];//以i为阈值,统计前景像素灰度总和}w1=w1/Num;u1=u1/w1;double variance=w0*w1*(u1-u0)*(u1-u0); //当前类间方差计算 if(variance > maxVariance)             {                  maxVariance = variance;                  threshold = i;              }}cout<<"threshold:"<<threshold<<endl;return threshold;}int main(){       Mat img = imread("D://vvoo//fenge.jpg");Mat img1;img.copyTo(img1);cvtColor(img,img,CV_BGR2GRAY);cvtColor(img1,img1,CV_BGR2GRAY);double th=Otsu(img);cout<<"The return value of getOstu is: "<<th<<endl;  cout<<"The return value of opencv threshold is: "<<threshold(img1 , img1 ,0,255,CV_THRESH_OTSU);//opencv已实现的大津法  for(int i=0;i<img.rows;i++){    for(int j=0;j<img.cols;j++){if( img.data[i*img.step + j]<=th)img.data[i*img.step + j]=255;elseimg.data[i*img.step + j]=0;}}imshow("Ostu_img",img);imshow("Opencv_img",img1);    waitKey(0);      return 0;}

阈值是一样的。


1.http://blog.csdn.net/ap1005834/article/details/51452516
原创粉丝点击