在对图像进行预处理的过程中,经常会遇到对图像进行二值化,比如对图像轮廓进行提取时,是一种比较常规的方法。下面是通过是我通过网上搜集到的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)