图像处理之最大熵阈值处理(C++)

图像处理之最大熵阈值处理(C++)



前言

熵代表信息量,图像的信息量越大,熵就越大,最大熵算法的目的就是找一个最佳的阈值使得背景和前景两个部分的熵之和最大。应用场景:直方图多峰、自适应寻找阈值。


一、最大熵阈值原理

基本概念:
1.各个灰度级的概率(频率)p(i),h(i)是指灰度为i的像素的个数,M*N是整个图片的像素数之和。
在这里插入图片描述
2.累加概率P0(q)、P1(q)
公式1
3.背景和前景对应的熵分别为H0(q)、H1(q)
在这里插入图片描述
注意:S1(q)=S0(255)-S0(q);
4.图像的总熵值H(q)=H0(q)+H1(q).

二、代码实现

#include <iostream>
#include <opencv.hpp>
using namespace std;


const double g_EPSINON = 0.000001;
/*
* @param cv::Mat src 输入图像(CV_8U)
* @param cv::Mat dst 输出图像
* @param int	thresh OTSU最大类间方差的灰度值
* @brief 计算OTSU的灰度值并返回
*/
int MaxEntropyThreshold(const cv::Mat& src, cv::Mat& dst, int& thresh)
{
	int h = src.rows;
	int w = src.cols;
	const int grayscale = 256;
	// 利用查表法计算各个灰度级的概率p(i)
	double grayTable[grayscale] = { 0 };
	for (int i = 0; i < h; i++)
		for (int j = 0; j < w; j++)
			grayTable[src.at<uchar>(i, j)]++;

	for (int i = 0; i < grayscale; i++)
		grayTable[i] /= (h * w);

	// 建立各个灰度值对应的熵值表∑p(i)*log(p(i)),即S(q)
	double EntropyTable[grayscale] = { 0 };
	double entropySum = 0.;
	for (int i = 0; i < grayscale; i++)
	{
		if (grayTable[i] > g_EPSINON) {
			entropySum += (grayTable[i] * log(grayTable[i]));
		}
		EntropyTable[i] = entropySum;
	}

	// 计算各个灰度级的累加概率和,即P0(q)
	double p_sum = 0;
	double cumProba[grayscale];
	for (int q = 0; q < grayscale; q++)
	{
		p_sum += grayTable[q];			//  灰度级为k的累加概率p1
		cumProba[q] = p_sum;
	}

	// 计算图像的总熵值
	double allEntropyTable[grayscale] = { 0 };
	double h0 = 0;
	double h1 = 0;
	for (int q = 0; q < grayscale; q++)
	{
		double temp = cumProba[q];
		if (temp > g_EPSINON) {
			h0 = -EntropyTable[q] / temp + log(temp);
			h1 = -(EntropyTable[255] - EntropyTable[q]) / (1 - temp) + log(1 - temp);
			allEntropyTable[q] = h0 + h1;
		}
		else
		{
			allEntropyTable[q] = 0.;
		}
	}

	// 查找对应图像总熵最大的灰度值k
	double max = allEntropyTable[0];
	thresh = 0;
	for (int i = 1; i < grayscale; i++)
	{
		if (max < allEntropyTable[i])
		{
			max = allEntropyTable[i];
			thresh = i;
		}
	}

	// 进行图像二值化
	dst = src.clone();
	for (int i = 0; i < h; i++)
		for (int j = 0; j < w; j++) {
			if (src.at<uchar>(i, j) > thresh)
				dst.at<uchar>(i, j) = 255;
			else
				dst.at<uchar>(i, j) = 0;
		}

	return thresh;
}

int main()
{
	//读取图片
	string filepath = "F://work_study//algorithm_demo//baby.jpg";
	cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);
	if (src.empty())
	{
		std::cout << "imread error" << std::endl;
		return -1;
	}

	cv::Mat dst(src.size(), src.type());

	//最大熵阈值处理
	int thresh = 0;
	MaxEntropyThreshold(src, dst, thresh);
	std::cout << thresh << endl;

	//显示图片
	cv::imwrite("dst.bmp", dst);
	cv::waitKey(0);
	return 0;
}

三、结果展示

最大熵结果图


总结

本文介绍了最大熵阈值的原理和以及相对应的具体的C++代码实现,对数学公式进行优化,欢迎大家阅读。
因为笔者水平有限,有错误欢迎指出,代码本人均在本地运行实验正确,大家放心使用。

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
灰度图像的最大熵阈值分割是一种常用的图像分割方法,它可以将图像分成两类,以使得分割后的图像信息熵最大。以下是 MATLAB 实现最大熵阈值分割的基本步骤: 1. 读取灰度图像并将其转换为二维数组。 ```matlab img = imread('image.jpg'); gray_img = rgb2gray(img); [m, n] = size(gray_img); ``` 2. 计算图像直方图并归一化。 ```matlab histogram = imhist(gray_img); normalized_hist = histogram / (m * n); ``` 3. 初始化最大熵最大熵阈值。 ```matlab max_entropy = 0; max_threshold = 0; ``` 4. 遍历所有可能的阈值,并计算分割后的两个子图像的信息熵。 ```matlab for threshold = 1:255 % 计算两个子图像的像素个数和像素值出现次数 pixel_count = zeros(2, 256); for i = 1:m for j = 1:n pixel_value = gray_img(i, j); if pixel_value <= threshold pixel_count(1, pixel_value + 1) = pixel_count(1, pixel_value + 1) + 1; else pixel_count(2, pixel_value + 1) = pixel_count(2, pixel_value + 1) + 1; end end end % 归一化两个子图像的像素值出现次数 normalized_pixel_count = pixel_count / (m * n); % 计算两个子图像的信息熵 entropy = -sum(sum(normalized_pixel_count .* log2(normalized_pixel_count + eps))); % 更新最大熵最大熵阈值 if entropy > max_entropy max_entropy = entropy; max_threshold = threshold; end end ``` 5. 根据最大熵阈值对图像进行分割。 ```matlab binary_img = gray_img > max_threshold; ``` 完整的代码如下: ```matlab img = imread('image.jpg'); gray_img = rgb2gray(img); [m, n] = size(gray_img); histogram = imhist(gray_img); normalized_hist = histogram / (m * n); max_entropy = 0; max_threshold = 0; for threshold = 1:255 pixel_count = zeros(2, 256); for i = 1:m for j = 1:n pixel_value = gray_img(i, j); if pixel_value <= threshold pixel_count(1, pixel_value + 1) = pixel_count(1, pixel_value + 1) + 1; else pixel_count(2, pixel_value + 1) = pixel_count(2, pixel_value + 1) + 1; end end end normalized_pixel_count = pixel_count / (m * n); entropy = -sum(sum(normalized_pixel_count .* log2(normalized_pixel_count + eps))); if entropy > max_entropy max_entropy = entropy; max_threshold = threshold; end end binary_img = gray_img > max_threshold; figure; subplot(1, 2, 1); imshow(gray_img); title('原图'); subplot(1, 2, 2); imshow(binary_img); title('分割后的二值图'); ``` 运行结果如下图所示: ![最大熵阈值分割结果](https://img-blog.csdn.net/20180925102938416?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Rlc3Rfd2Vic2l0ZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/70)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值