C++ image processing based on opencv (image binarization)

foreword

Based on the c++ interface of opencv, commonly used image binarization methods are implemented, including the maximum between-class variance method (OTSU), fixed threshold and adaptive threshold.

Related opencv interface analysis

CV_EXPORTS_W double threshold( InputArray src, OutputArray dst,
                               double thresh, double maxval, int type );

This function applies a fixed level of thresholding to a multi-channel array. This function is usually used to obtain a bilayer (binary) image from a grayscale image (#compare can also be used for this purpose) or to remove noise, i.e. filter out pixels with values ​​that are too small or too large. The function supports several types threshold. They are determined by type parameters.
Additionally, the special values ​​#THRESH_OTSU or #THRESH_TRIANGLE can be combined with one of the above values. In these cases, the function uses the Otsu or Triangle algorithm to determine the optimal threshold and uses it instead of the specified threshold.

@param src input array (multi-channel, 8-bit or 32-bit float).
@param dst Output array with same size and type and same number of channels as src.
@param thresh threshold.
@param maxval Maximum value to use with #THRESH_BINARY and #THRESH_BINARY_INV threshold types.
@param type Threshold type (see #ThresholdTypes).
@return If Otsu or Triangle method is used, computes the threshold.

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 );

Applies an adaptive threshold to an array. This function converts a grayscale image to a binary image according to the formula:

  • THRESH_BINARY
    \f[dst(x,y) = \fork{\texttt{maxValue}}{if (src(x,y) > T(x,y))}{0}{otherwise}\f]
  • THRESH_BINARY_INV
    \f[dst(x,y) = \fork{0}{if(src(x,y) > T(x,y))}{\texttt{maxValue}}{otherwise}\f]where\
    f KaTeX parse error: Undefined control sequence: \f at position 7: T(x,y)\̲f̲ is a threshold calculated individually for each pixel (see AdaptiveMethod parameter).
    This function can process images in-place.
    @param src source 8 bit single channel image.
    @param dst Destination image of the same size and type as src.
    @param maxValue The non-zero value to assign to pixels meeting the condition
    @param AdaptiveMethod The adaptive thresholding algorithm to use, see #AdaptiveThresholdTypes.
    #BORDER_REPLICATE | #BORDER_ISOLATED for processing borders.
    @param thresholdType threshold type, must be #THRESH_BINARY or #THRESH_BINARY_INV, see #ThresholdTypes.
    @param blockSize The size of the pixel neighborhood used to calculate the pixel threshold: 3, 5, 7, etc.
    @param C Subtracts a constant from the average or weighted average. Usually, it is a positive number, but it can also be zero or negative.
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
};

sample code

binarized.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; } // 这是构造函数声明
		~Binarizate() {
    
     cout << "Binarizate is being deleted" << endl; } // 这是析构函数声明

		int OTSU(cv::Mat srcImage);// 大律法函数实现
		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);//自适应阈值化

	};
}

binarized.cpp

#include "binarizate.h"

int ImgEnhance::Binarizate::OTSU(cv::Mat srcImage)
{
    
    
	int nCols = srcImage.cols;
	int nRows = srcImage.rows;
	int threshold = 0;
	// 初始化统计参数
	int nSumPix[256];
	float nProDis[256];
	for (int i = 0; i < 256; i++)
	{
    
    
		nSumPix[i] = 0;
		nProDis[i] = 0;
	}
	// 统计灰度级中每个像素在整幅图像中的个数 
	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++)
	{
    
    
		// 初始化相关参数
		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;
	}
	// 初始化阈值参数
	int thresh = OTSU(srcImage);
	// 初始化阈值化处理的类型 
	/* 0: 二进制阈值 1: 反二进制阈值 2: 截断阈值
	3: 0阈值   4: 反0阈值*/
	//int threshType = 0;
	// 预设最大值
	//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;
	}
	// 初始化阈值参数
	//int thresh = 130;
	// 初始化阈值化处理的类型 
	/* 0: 二进制阈值 1: 反二进制阈值 2: 截断阈值
	3: 0阈值   4: 反0阈值 8:大均法*/
	//int threshType = 0;
	// 预设最大值
	//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;
	}
	// 初始化自适应阈值参数
	//int blockSize = 5;
	//int constValue = 10;
	//const int maxVal = 255;
	/* 自适应阈值算法
	0:ADAPTIVE_THRESH_MEAN_C
	1: ADAPTIVE_THRESH_GAUSSIAN_C
	阈值类型
	0: THRESH_BINARY
	1: THRESH_BINARY_INV */
	//int adaptiveMethod = 0;
	//int thresholdType = 1;
	// 图像自适应阈值操作
	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);*/
	// 转化为灰度图像
	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);

	//自适应阈值化
	// 初始化自适应阈值参数
	Mat adaptiveImage;
	int blockSize = 5;
	int constValue = 10;
	//const int maxVal = 255;
	/* 自适应阈值算法
	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("自适应阈值-高斯二值化图", 0);
	cv::imshow("自适应阈值-高斯二值化图", adaptiveImage);

	cv::waitKey(0);

	return 0;

}

Result display

insert image description here

Guess you like

Origin blog.csdn.net/qq_40118285/article/details/126943293