欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > c/c++ >内容正文

c/c++

【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)

发布时间:2023/12/9 c/c++ 54 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

目录

  • 概念
  • C++源码
    • OtsuThreshold
    • 主函数
  • 效果
  • 完整源码

平台:Windows 10 20H2
Visual Studio 2015
OpenCV 4.5.3


本文所用源码修改自C++ opencv 图片二值化最佳阈值确定(大津法,OTSU算法)——Sharon Liu

概念

        Otsu算法,也叫最大类间方差法,是1979年由日本学者大津提出的(所以也叫大津法),是一种自适应阈值确定的方法,一种全局的二值化算法。
        它是根据图像的灰度特性,将图像分为前景背景两个部分。 当取最佳阈值时,两部分之间的差别应该是最大的。在Otsu算法中所采用的衡量差别的标准就是较为常见的最大类间方差。前景和背景之间的类间方差如果越大,就说明构成图像的两个部分之间的差别越大。
        当部分目标被错分为背景或部分背景被错分为目标,都会导致两部分差别变小。
        当所取阈值的分割使类间方差最大时,就意味着错分概率最小。

C++源码

OtsuThreshold

/****************************************************************************************** Function: OtsuThreshold Description: 图片二值化最佳阈值确定(大津法,OTSU算法) Input: src:原图片 Return: 阈值 ******************************************************************************************/ int OtsuThreshold(Mat src) {int threshold;try{int height = src.rows;int width = src.cols;//histogram float histogram[256] = { 0 };for (int i = 0; i < height; i++) {unsigned char* p = (unsigned char*)src.data + src.step*i;for (int j = 0; j < width; j++) {histogram[*p++]++;}}//normalize histogram int size = height*width;for (int i = 0; i < 256; i++) {histogram[i] = histogram[i] / size;}//average pixel value float avgValue = 0;for (int i = 0; i < 256; i++) {avgValue += i*histogram[i];}float maxVariance = 0;float w = 0, u = 0;for (int i = 0; i < 256; i++) {w += histogram[i];u += i*histogram[i];float t = avgValue*w - u;float variance = t*t / (w*(1 - w));if (variance > maxVariance) {maxVariance = variance;threshold = i;}}}catch (cv::Exception e){}return threshold; } //———————————————— //版权声明:本文为CSDN博主「Sharon Liu」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。 //原文链接:https ://blog.csdn.net/sylsjane/article/details/80872744

主函数

图片路径根据实际情况调整,注意反斜杠是转义字符的开头,故“\”应替换为“\\”

int main(int argc, char * argv[]) {Mat Image = imread("D:\\Work\\OpenCV\\Workplace\\Test_1\\1.jpg", 0);int thresholdValue = OtsuThreshold(Image);cout << "类间方差为: " << thresholdValue << endl;Mat imageOutput;threshold(Image, imageOutput, thresholdValue, 255, CV_THRESH_BINARY);Mat imageOtsu;threshold(Image, imageOtsu, 0, 255, CV_THRESH_OTSU); //Opencv Otsu算法imshow("原图", Image);imshow("Output Image", imageOutput);imshow("Opencv Otsu", imageOtsu);waitKey(0);return 0; }

效果

原图

效果

OpenCv自带的Otsu算法结果,与上图一致

完整源码

#include <opencv2\opencv.hpp> #include <iostream> #include <opencv2\imgproc\types_c.h>using namespace cv; using namespace std;/****************************************************************************************** Function: OtsuThreshold Description: 图片二值化最佳阈值确定(大津法,OTSU算法) Input: src:原图片 Return: 阈值 ******************************************************************************************/ int OtsuThreshold(Mat src) {int threshold;try{int height = src.rows;int width = src.cols;//histogram float histogram[256] = { 0 };for (int i = 0; i < height; i++) {unsigned char* p = (unsigned char*)src.data + src.step*i;for (int j = 0; j < width; j++) {histogram[*p++]++;}}//normalize histogram int size = height*width;for (int i = 0; i < 256; i++) {histogram[i] = histogram[i] / size;}//average pixel value float avgValue = 0;for (int i = 0; i < 256; i++) {avgValue += i*histogram[i];}float maxVariance = 0;float w = 0, u = 0;for (int i = 0; i < 256; i++) {w += histogram[i];u += i*histogram[i];float t = avgValue*w - u;float variance = t*t / (w*(1 - w));if (variance > maxVariance) {maxVariance = variance;threshold = i;}}}catch (cv::Exception e){}return threshold; } //———————————————— //版权声明:本文为CSDN博主「Sharon Liu」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。 //原文链接:https ://blog.csdn.net/sylsjane/article/details/80872744int main(int argc, char * argv[]) {Mat Image = imread("D:\\Work\\OpenCV\\Workplace\\Test_1\\1.jpg", 0);int thresholdValue = OtsuThreshold(Image);cout << "类间方差为: " << thresholdValue << endl;Mat imageOutput;threshold(Image, imageOutput, thresholdValue, 255, CV_THRESH_BINARY);Mat imageOtsu;threshold(Image, imageOtsu, 0, 255, CV_THRESH_OTSU); //Opencv Otsu算法imshow("原图", Image);imshow("Output Image", imageOutput);imshow("Opencv Otsu", imageOtsu);waitKey(0);return 0; }

总结

以上是生活随笔为你收集整理的【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。