在对图像进行预处理的过程中,经常会遇到对图像进行二值化,比如对图像轮廓进行提取时,是一种比较常规的方法。下面是通过是我通过网上搜集到的OSTU算法动态阈值二值化图像的方法,主要是将1.x接口,修改成了2.x版本的API,并对其中的部分代码进行了修改。
#include "opencv2/opencv.hpp"
#include <iostream>
/**
*@function OSTU_Region : used to get the threshold for image binary
*/
int OSTU_Region(cv::Mat& image)
{
assert(image.channels() == 1);
int width = image.cols ;
int height = image.rows ;
int x = 0,y = 0;
int pixelCount[256] = { 0 };
float pixelPro[256] = { 0 };
int i, j, pixelSum = width * height, threshold = 0;
uchar* data = image.ptr<uchar>(0);
//count every pixel number in whole image
for(i = y; i < height; i++)
{
for(j = x;j <width;j++)
{
pixelCount[data[i * image.step + j]]++;
}
}
//count every pixel's radio in whole image pixel
for(i = 0; i < 256; i++)
{
pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
}
// segmentation of the foreground and background
// To traversal grayscale [0,255],and calculates the variance maximum grayscale values for the best threshold value
float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;
for(i = 0; i < 256; i++)
{
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
for(j = 0; j < 256; j++)
{
if(j <= i) //background
{
w0 += pixelPro[j];
u0tmp += j * pixelPro[j];
}
else //foreground
{
w1 += pixelPro[j];
u1tmp += j * pixelPro[j];
}
}
u0 = u0tmp / w0;
u1 = u1tmp / w1;
u = u0tmp + u1tmp;
//Calculating the variance
deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
if(deltaTmp > deltaMax)
{
deltaMax = deltaTmp;
threshold = i;
}
}
//return the best threshold;
return threshold;
}
/**
*@function main
*/
int main(int argc, char* argv[])
{
//--1. load image
cv::Mat src;
src = cv::imread(argv[1],1);
if(!src.data)
{
std::cout << "Invalid image file!" << std::endl;
exit(-1);
}
cv::imshow("src",src);
//--2. use ostu get the threshold and applay binary
cv::Mat src_gray;
cv::cvtColor(src, src_gray, CV_BGR2GRAY);
int threshold = OSTU_Region(src_gray);
cv::threshold(src_gray,src_gray,threshold,255,CV_THRESH_BINARY);
cv::imshow("OSTU",src_gray);
cv::waitKey(0);
return 0;
}
关于OSTU的算法,它是1979年由日本大津提出的,在最小二乘法原理基础上推导出来的。适用于双峰的直方图。网上有很多类似的算法,上述采用的是最简单,也是最经典的的一种方法而已。
它的基本原理是:
目前理解还是比较模糊的……大概意思理解而已。
PS:最近正在自学py中,还处于非常迷茫的阶段,求指导,求批斗~
采用OSTU算法对图像进行动态阈值二值化(基于OpenCV)
