前言
基于opencv的c++接口,實現(xiàn)常用的圖像二值化方法,包括了最大類間方差法(OTSU)、固定化閾值以及自適應(yīng)閾值。
相關(guān)的opencv接口解析
CV_EXPORTS_W double threshold( InputArray src, OutputArray dst,
double thresh, double maxval, int type );
該函數(shù)將固定級別的閾值應(yīng)用于多通道陣列。該函數(shù)通常用于從灰度圖像中獲取雙層(二進制)圖像(#compare 也可用于此目的)或用于去除噪聲,即過濾掉值過小或過大的像素.該函數(shù)支持幾種類型的閾值。它們由類型參數(shù)確定。
此外,特殊值#THRESH_OTSU 或#THRESH_TRIANGLE 可以與上述值之一組合。在這些情況下,該函數(shù)使用 Otsu 或 Triangle 算法確定最佳閾值,并使用它代替指定的閾值。
@param src 輸入數(shù)組(多通道、8 位或 32 位浮點)。
@param dst 與 src 具有相同大小和類型以及相同通道數(shù)的輸出數(shù)組。
@param thresh 閾值。
@param maxval 與 #THRESH_BINARY 和 #THRESH_BINARY_INV 閾值類型一起使用的最大值。
@param type 閾值類型(請參閱#ThresholdTypes)。
@return 如果使用 Otsu 或 Triangle 方法,則計算閾值。
enum ThresholdTypes {
THRESH_BINARY = 0, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{maxval}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
THRESH_BINARY_INV = 1, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{maxval}}{otherwise}\f]
THRESH_TRUNC = 2, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{threshold}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
THRESH_TOZERO = 3, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{src}(x,y)}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
THRESH_TOZERO_INV = 4, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
THRESH_MASK = 7,
THRESH_OTSU = 8, //!< flag, use Otsu algorithm to choose the optimal threshold value
THRESH_TRIANGLE = 16 //!< flag, use Triangle algorithm to choose the optimal threshold value
};
CV_EXPORTS_W void adaptiveThreshold( InputArray src, OutputArray dst,
double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C );
對數(shù)組應(yīng)用自適應(yīng)閾值。該函數(shù)根據(jù)公式將灰度圖像轉(zhuǎn)換為二值圖像:文章來源:http://www.zghlxwxcb.cn/news/detail-466576.html
-
THRESH_BINARY
\f[dst(x,y) = \fork{\texttt{maxValue}}{如果 (src(x,y) > T(x,y))}{0}{否則}\f] -
THRESH_BINARY_INV
\f[dst(x,y) = \fork{0}{如果 (src(x,y) > T(x,y))}{\texttt{maxValue}}{否則}\f]
其中 \fKaTeX parse error: Undefined control sequence: \f at position 7: T(x,y)\?f? 是為每個像素單獨計算的閾值(請參閱 AdaptiveMethod 參數(shù))。
該函數(shù)可以就地處理圖像。
@param src 源 8 位單通道圖像。
@param dst 與 src 大小和類型相同的目標圖像。
@param maxValue 分配給滿足條件的像素的非零值
@param AdaptiveMethod 要使用的自適應(yīng)閾值算法,請參閱#AdaptiveThresholdTypes。
#BORDER_REPLICATE | #BORDER_ISOLATED 用于處理邊界。
@param thresholdType 閾值類型,必須是#THRESH_BINARY 或#THRESH_BINARY_INV,請參閱#ThresholdTypes。
@param blockSize 用于計算像素閾值的像素鄰域的大小:3、5、7 等。
@param C 從平均值或加權(quán)平均值中減去常數(shù)。通常,它是正數(shù),但也可能為零或負數(shù)。
enum AdaptiveThresholdTypes {
/** the threshold value \f$T(x,y)\f$ is a mean of the \f$\texttt{blockSize} \times
\texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$ minus C */
ADAPTIVE_THRESH_MEAN_C = 0,
/** the threshold value \f$T(x, y)\f$ is a weighted sum (cross-correlation with a Gaussian
window) of the \f$\texttt{blockSize} \times \texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$
minus C . The default sigma (standard deviation) is used for the specified blockSize . See
#getGaussianKernel*/
ADAPTIVE_THRESH_GAUSSIAN_C = 1
};
示例代碼
binarizate.h
#pragma once
#include <iostream>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
#define PROCESS_IMG_SUCESS 0
#define PROCESS_IMG_FAIL 1
namespace ImgEnhance
{
//二值化
class Binarizate
{
public:
Binarizate() { cout << "Binarizate is being created" << endl; } // 這是構(gòu)造函數(shù)聲明
~Binarizate() { cout << "Binarizate is being deleted" << endl; } // 這是析構(gòu)函數(shù)聲明
int OTSU(cv::Mat srcImage);// 大律法函數(shù)實現(xiàn)
int OtsuBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int maxVal, int threshType);//大律法二值化
int FixedBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int thresh, int maxVal, int threshType);//固定化閾值
int AdaptiveBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int maxVal, int adaptiveMethod, int thresholdType, int blockSize, int constValue);//自適應(yīng)閾值化
};
}
binarizate.cpp
#include "binarizate.h"
int ImgEnhance::Binarizate::OTSU(cv::Mat srcImage)
{
int nCols = srcImage.cols;
int nRows = srcImage.rows;
int threshold = 0;
// 初始化統(tǒng)計參數(shù)
int nSumPix[256];
float nProDis[256];
for (int i = 0; i < 256; i++)
{
nSumPix[i] = 0;
nProDis[i] = 0;
}
// 統(tǒng)計灰度級中每個像素在整幅圖像中的個數(shù)
for (int i = 0; i < nCols; i++)
{
for (int j = 0; j < nRows; j++)
{
nSumPix[(int)srcImage.at<uchar>(i, j)]++;
}
}
// 計算每個灰度級占圖像中的概率分布
for (int i = 0; i < 256; i++)
{
nProDis[i] = (float)nSumPix[i] / (nCols * nRows);
}
// 遍歷灰度級[0,255],計算出最大類間方差下的閾值
float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp;
double delta_max = 0.0;
for (int i = 0; i < 256; i++)
{
// 初始化相關(guān)參數(shù)
w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;
for (int j = 0; j < 256; j++)
{
//背景部分
if (j <= i)
{
// 當前i為分割閾值,第一類總的概率
w0 += nProDis[j];
u0_temp += j * nProDis[j];
}
//前景部分
else
{
// 當前i為分割閾值,第一類總的概率
w1 += nProDis[j];
u1_temp += j * nProDis[j];
}
}
// 分別計算各類的平均灰度
u0 = u0_temp / w0;
u1 = u1_temp / w1;
delta_temp = (float)(w0 *w1* pow((u0 - u1), 2));
// 依次找到最大類間方差下的閾值
if (delta_temp > delta_max)
{
delta_max = delta_temp;
threshold = i;
}
}
return threshold;
}
int ImgEnhance::Binarizate::OtsuBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int maxVal, int threshType)
{
if (!srcImage.data || srcImage.channels() != 1)
{
return 1;
}
// 初始化閾值參數(shù)
int thresh = OTSU(srcImage);
// 初始化閾值化處理的類型
/* 0: 二進制閾值 1: 反二進制閾值 2: 截斷閾值
3: 0閾值 4: 反0閾值*/
//int threshType = 0;
// 預(yù)設(shè)最大值
//const int maxVal = 255;
// 固定閾值化操作
cv::threshold(srcImage, dstImage, thresh,
maxVal, threshType);
return 0;
}
int ImgEnhance::Binarizate::FixedBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int thresh, int maxVal, int threshType)
{
if (!srcImage.data || srcImage.channels() != 1)
{
return 1;
}
// 初始化閾值參數(shù)
//int thresh = 130;
// 初始化閾值化處理的類型
/* 0: 二進制閾值 1: 反二進制閾值 2: 截斷閾值
3: 0閾值 4: 反0閾值 8:大均法*/
//int threshType = 0;
// 預(yù)設(shè)最大值
//const int maxVal = 255;
// 固定閾值化操作
cv::threshold(srcImage, dstImage, thresh,
maxVal, threshType);
return 0;
}
int ImgEnhance::Binarizate::AdaptiveBinarizate(cv::Mat srcImage, cv::Mat &dstImage, int maxVal, int adaptiveMethod, int thresholdType, int blockSize, int constValue)
{
if (!srcImage.data || srcImage.channels() != 1)
{
return 1;
}
// 初始化自適應(yīng)閾值參數(shù)
//int blockSize = 5;
//int constValue = 10;
//const int maxVal = 255;
/* 自適應(yīng)閾值算法
0:ADAPTIVE_THRESH_MEAN_C
1: ADAPTIVE_THRESH_GAUSSIAN_C
閾值類型
0: THRESH_BINARY
1: THRESH_BINARY_INV */
//int adaptiveMethod = 0;
//int thresholdType = 1;
// 圖像自適應(yīng)閾值操作
cv::adaptiveThreshold(srcImage, dstImage, maxVal, adaptiveMethod, thresholdType, blockSize, constValue);
return 0;
}
test.cpp
#include"binarizate.h"
ImgEnhance::Binarizate ImgB;//二值化
int main()
{
// 讀取源圖像及判斷
cv::Mat srcImage = cv::imread("flower.jpg");
if (!srcImage.data)
{
return 1;
}
/*cv::namedWindow("原始圖", 0);
cv::imshow("原始圖", srcImage);*/
// 轉(zhuǎn)化為灰度圖像
cv::Mat srcGray;
if (srcImage.channels() == 3)
{
cv::cvtColor(srcImage, srcGray, COLOR_RGB2GRAY);
}
else
{
srcGray = srcImage.clone();
}
cv::namedWindow("灰度圖", 0);
cv::imshow("灰度圖", srcGray);
//最大類間方差二值化(OTSU)
Mat otsuImage;
const int maxVal = 255;
int threshType = 0;
// 初始化閾值化處理的類型
/* 0: 二進制閾值 1: 反二進制閾值 2: 截斷閾值
3: 0閾值 4: 反0閾值*/
ImgB.OtsuBinarizate(srcGray, otsuImage, maxVal, threshType);
cv::namedWindow("otsu二值化圖", 0);
cv::imshow("otsu二值化圖", otsuImage);
//固定化閾值
Mat fixedImage;
int thresh = 100;
int threshType2 = 0;
ImgB.FixedBinarizate(srcGray, fixedImage, thresh, maxVal, threshType2);//固定化閾值
cv::namedWindow("固定閾值二值化圖", 0);
cv::imshow("固定閾值二值化圖", fixedImage);
//自適應(yīng)閾值化
// 初始化自適應(yīng)閾值參數(shù)
Mat adaptiveImage;
int blockSize = 5;
int constValue = 10;
//const int maxVal = 255;
/* 自適應(yīng)閾值算法
0:ADAPTIVE_THRESH_MEAN_C
1: ADAPTIVE_THRESH_GAUSSIAN_C
閾值類型
0: THRESH_BINARY
1: THRESH_BINARY_INV */
int adaptiveMethod = ADAPTIVE_THRESH_GAUSSIAN_C;
int thresholdType = 0;
ImgB.AdaptiveBinarizate(srcGray, adaptiveImage, maxVal, adaptiveMethod, thresholdType, blockSize, constValue);
cv::namedWindow("自適應(yīng)閾值-高斯二值化圖", 0);
cv::imshow("自適應(yīng)閾值-高斯二值化圖", adaptiveImage);
cv::waitKey(0);
return 0;
}
結(jié)果展示
文章來源地址http://www.zghlxwxcb.cn/news/detail-466576.html
到了這里,關(guān)于基于opencv的c++圖像處理(圖像二值化)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!