OTSU 演算法求最佳閾值,及opencv 二值化
- 前言
- 一、OTSU 演算法求最佳閾值
- 二、使用獲取的最佳閾值進行二值化
- 三、效果
前言
OTSU演算法,也就是大津演算法,屬于自適應的閾值確定方法,用該閾值進行的影像固定閾值二值化,類間方差最大,它是按影像的灰度特性,將影像分成背景和前景兩部分,使類間方差最大的分割意味著錯分概率最小,其核心思路是尋找一個閾值T,把影像的所有像素點分成兩類,一類的像素值均小于等于T(背景區域),另一類的像素值均大于T(前景區域),當這兩類的類間方差取得最大值時,則認為該T值為最合適的閾值,假設所有像素點的總和是Sum,背景區域所有像素點數為N1,其占影像總像素數的比例為w1,平均像素值為μ1;前景區域所有像素點數為N2,其占影像總像素數的比例為w2,平均像素值為μ2;μ 為0-255 的平均像素,那么有以下關系式:

提示:以下是本篇文章正文內容,下面案例可供參考
一、OTSU 演算法求最佳閾值
有著上面的演算法公式我們就可以很容易的把代碼寫出來了,下面是代碼,如果不需要用QImage的話可以直接使用Mat,選喲 轉換代碼的可以去轉換代碼
int ImageHandle::GetOptimalThreshold(QImage &image)//OTSU (大津法)
{
//首先先把QImage 轉為三通道并轉換為Mat
image = image.convertToFormat(QImage::Format_RGB888);
cv::Mat src = this->QImage2Mat(image);
//灰度處理,轉成單通道
cv::cvtColor(src,src,cv::COLOR_BGR2GRAY);
//圖片的寬,高
int nRows = src.rows;
int nCols = src.cols;
int threshold = 0; //最佳閾值
double temp = 0.0; //獲取
double AvePix[256];
int TotalPix[256];
double nProDis[256];
double nSumProDis[256];
//變數初始化
for (int i = 0; i < 256; i++)
{
AvePix[i] = 0.0;
TotalPix[i] = 0;
nProDis[i] = 0.0;
nSumProDis[i] = 0.0;
}
//計算0-255 每個像素值的像素點
for (int i = 0; i < nRows; i++)
{
for (int j = 0; j < nCols; j++)
{
TotalPix[(int)src.at<uchar>(i, j)]++;
}
}
//計算每個像素值的像素點 占 總像素點的比例
for (int i = 0; i < 256; i++)
{
nProDis[i] = (double)TotalPix[i] / (nRows*nCols);
}
AvePix[0] = 0;
nSumProDis[0] = nProDis[0];
//計算背景區域的像素比例 與 像素平均值
for (int i = 1; i < 256; i++)
{
nSumProDis[i] = nSumProDis[i - 1] + nProDis[i];
AvePix[i] = AvePix[i - 1] + i*nProDis[i];
}
double mean = AvePix[255];
//遍歷像素值 找到類間方差最大的像數值即為最佳閾值
for (int i = 1; i < 256; i++)
{
double Pback = nSumProDis[i];
double Pfront = 1 - nSumProDis[i];
double g= 0.0;
if (fabs(Pback ) > 0.000001 && fabs(Pfront ) > 0.000001)
{
double Mback = AvePix[i];
double Mfront = (mean - Pback *Mback)/Pfront ;
g= (double)(Pback * Pfront * pow((Mback - Mfront), 2)); //大津演算法 即(背景像素占總像素的比例 * 前景像素占總像素的比例 * (背景平均像素 - 前景平均像素)的平方)
if (g> temp)
{
temp = g;
threshold = i;
}
}
}
return threshold;
}
二、使用獲取的最佳閾值進行二值化
QImage ImageHandle::Binarization(QImage &image,int threshold)
{
image = image.convertToFormat(QImage::Format_RGB888);
cv::Mat src = this->QImage2Mat(image);
cv::cvtColor(src,src,cv::COLOR_BGR2GRAY);
cv::Mat dst;
cv::threshold(src,dst,threshold,255,CV_THRESH_BINARY);
return this->Mat2QImage(dst);
}
int main()
{
QApplication a(argc, argv);
QImage temp;
temp = QImage("temp.png");
ImageHandle f;
int i = f.GetOptimalThreshold(temp);
temp = f.Binarization(temp,i);
QLabel *m_label = new QLabel();
m_label->resize(1280,1024);
QPixmap I_map = QPixmap::fromImage(temp);
I_map = I_map.scaled(m_label->width(),m_label->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
m_label->setPixmap(I_map);
m_label->show();
return a.exec();
}
三、效果
1、二值化前

2、二值化后

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/339012.html
標籤:AI
