【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)
生活随笔
收集整理的這篇文章主要介紹了
【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
目錄
- 概念
- C++源碼
- OtsuThreshold
- 主函數(shù)
- 效果
- 完整源碼
平臺:Windows 10 20H2
Visual Studio 2015
OpenCV 4.5.3
本文所用源碼修改自C++ opencv 圖片二值化最佳閾值確定(大津法,OTSU算法)——Sharon Liu
概念
????????Otsu算法,也叫最大類間方差法,是1979年由日本學(xué)者大津提出的(所以也叫大津法),是一種自適應(yīng)閾值確定的方法,一種全局的二值化算法。
????????它是根據(jù)圖像的灰度特性,將圖像分為前景和背景兩個部分。 當(dāng)取最佳閾值時,兩部分之間的差別應(yīng)該是最大的。在Otsu算法中所采用的衡量差別的標準就是較為常見的最大類間方差。前景和背景之間的類間方差如果越大,就說明構(gòu)成圖像的兩個部分之間的差別越大。
????????當(dāng)部分目標被錯分為背景或部分背景被錯分為目標,都會導(dǎo)致兩部分差別變小。
????????當(dāng)所取閾值的分割使類間方差最大時,就意味著錯分概率最小。
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; } //———————————————— //版權(quán)聲明:本文為CSDN博主「Sharon Liu」的原創(chuàng)文章,遵循CC 4.0 BY - SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。 //原文鏈接:https ://blog.csdn.net/sylsjane/article/details/80872744主函數(shù)
圖片路徑根據(jù)實際情況調(diào)整,注意反斜杠是轉(zhuǎn)義字符的開頭,故“\”應(yīng)替換為“\\”
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算法結(jié)果,與上圖一致
完整源碼
#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; } //———————————————— //版權(quán)聲明:本文為CSDN博主「Sharon Liu」的原創(chuàng)文章,遵循CC 4.0 BY - SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。 //原文鏈接: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; }總結(jié)
以上是生活随笔為你收集整理的【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: luajit日记-FFI库
- 下一篇: [转]Displaying standa