图像处理之最大熵阈值处理(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
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值