一维最大熵阈值分割法原理及实现
# 一維最大熵閾值分割法原理及實現(xiàn)|CSDN創(chuàng)作打卡
背景
閾值分割:閾值分割是圖像分割中的一種常用方法,通常是按閾值將圖像分割成幾個部分。
閾值分割方法的關(guān)鍵是閾值選取準則,常用的準則有最大類間方差(OTSU 大津法)和信息熵,其中大津法已經(jīng)在上一篇博文中實現(xiàn)
OTSU算法(大津法—最大類間方差法)原理及實現(xiàn)
熵( Entropy)
信息熵的概念是由信息論之父克勞德-香農(nóng)所提出來的,和由物理學(xué)中的熵具有類似的公式,信息熵是用來衡量信息量大小的一個概念,具體可以參考這位博主的文章信息熵及其相關(guān)概念或者去嗶哩嗶哩上搜索信息熵來理解他的概念。
其中最重要的的一個性質(zhì)就是:分布的越均勻,其熵越大,當系統(tǒng)內(nèi)部所有的事件都是等概率發(fā)生時,其信息量越大,也就是熵越大。抽象到物理層面反過來理解就是:一個箱子隔成兩個等體積部分,一邊放1000個具有一定初速度的粒子,在里面自由運動,且能量不衰減,當把中間的隔板拿開,最后1000個粒子總會在箱子中趨向均勻分布,這就是系統(tǒng)熵增的一個過程,反過來理解就是熵越大越趨向于均勻分布。
那這與我們的圖像分割有什么關(guān)系呢?閾值將圖像所有的像素分為兩類:前景和背景,當每一類像素中的像素在此類中趨向均勻分布時,此時這部分熵最大,當前景和背景兩類像素都趨向均勻分布時,前景的熵和背景的熵最大,由系統(tǒng)熵的累加性,此時整幅圖像的熵最大,即熵最大時將前景和背景區(qū)分開來。
使用最大閾值法時,當灰度直方圖為上圖時,此時閾值為115,可以看出此時小于115閾值的像素在這類像素中趨向均勻分布,大于115閾值的像素在另一類中趨向均勻分布。
公式推導(dǎo):
Opencv實現(xiàn):
#include<opencv2/opencv.hpp> #include<vector> #include<iostream>using namespace std; using namespace cv;void calcGrayHist(Mat& image, Mat& histImage) {Mat hist;//用于存放直方圖計算結(jié)果const int channels[1] = { 0 };//通道索引float inRanges[2] = { 0,255 };const float* ranges[1] = { inRanges };//像素灰度值范圍const int bins[1] = { 256 };//直方圖的維度,其實就是像素灰度值的最大值calcHist(&image, 1, channels, Mat(), hist, 1, bins, ranges);//計算圖像直方圖//準備繪制直方圖int hist_w = 256;int hist_h = 400;int width = 1;histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);for (int i = 1; i <= hist.rows; ++i) {rectangle(histImage, Point(width * (i - 1), hist_h - 1),Point(width * i - 1, hist_h - cvRound(hist.at<float>(i - 1))/2),//調(diào)整顯示高度Scalar(255, 255, 255), -1);}}void Max_entropy(Mat input, Mat& output, int& thres,int deviation) {const int Grayscale = 256;int width = input.cols;int height = input.rows;double Graystatistics[Grayscale] = { 0 };for (int i = 0; i < height; i++){for (int j = 0; j < width;j++){int Grayvalue = input.at<uchar>(i, j);Graystatistics[Grayvalue]++;//直方圖統(tǒng)計}}double allnum = width * height;double Pi[Grayscale] = { 0 };//單個個灰度的概率double PS[Grayscale] = { 0 };//累計灰度概率double Psum = 0;for (int i = 0; i < Grayscale; i++){Pi[i] = Graystatistics[i] / allnum;PS[i] = Pi[i] + Psum;Psum = PS[i];}double max_entropy = 0;for (int i = 0; i < Grayscale; i++){double HA = 0;double HB = 0;//求前景熵double probility = 0;for (int j = 0; j < i; j++){probility = 0;if (Pi[j] != 0){probility = Pi[j] / PS[i];HA = HA +probility * log(1/probility);}}//求背景熵for (int m = i; m < Grayscale; m++){probility = 0;if (Pi[m] != 0&&(1-PS[i])!=0){probility = Pi[m] / (1 - PS[i]);HB = HB +probility * log(1/probility);}}if ((HA + HB) > max_entropy){max_entropy = HA + HB;thres = i- deviation;}//cout << HA+HB << endl;}input.copyTo(output);for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){int value = output.at<uchar>(i, j);if (value >thres){output.at<uchar>(i, j) = 255;}else{output.at<uchar>(i, j) = 0;}}} }int main() {Mat a = imread("mayi.png");cvtColor(a, a, COLOR_RGB2GRAY);Mat b;int th = 0;Max_entropy(a, b, th,0);cout << th << endl;Mat hist;calcGrayHist(a, hist);imwrite("2.bmp", b);imshow("1", b);return 0; }最大熵閾值分割效果:
| 原圖 | 最大熵閾值分割 |
| 原圖 | 最大熵閾值分割 |
otsu分割效果:
| 原圖 | otsu分割 |
| 原圖 | otsu分割 |
?
原圖的灰度直方圖:
| 米粒的灰度直方圖 | 螞蟻灰度直方圖 |
效果對比:
由米粒的直方圖不是典型的雙峰圖像,最大熵閾值法對此的分割閾值更高,分割的更細,將米粒上的像素值更高的部分分割出來了,而對OTSU分割算法來說,其保留的米粒更加完整,分割效果更好。而對螞蟻這種典型雙峰灰度圖,兩種算法分割效果一致。
展望:對于多峰灰度圖怎么來選取閾值,怎么選取多個閾值進行分割?怎么引入優(yōu)化算法加快閾值的選取?如何提高分割效果?
總結(jié)
以上是生活随笔為你收集整理的一维最大熵阈值分割法原理及实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云信api_服务端API文档
- 下一篇: 为什么Stc-isp一直在检测单片机