OUST实现图像分割

一、基本介绍
应用:求图像全局阈值,适用于大多需要求图像全局阈值的需求
优点:计算简单、快速,不受图像亮度和对比度影响
缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,效果不好

二、原理
OTSU算法假设存在阈值TH,将图像所有像素分为两类C1(小于TH)、C2(大于TH)。这两类像素各自的均值分别为m1、m2,图像全局均值为mG。同事像素被分为C1、C2类的概率分别为p1、p2.因此有:

p1*m1+p2*m2=mG											(1)
p1+p2=1															(2)

根据方差概念,类间方差表达式为:

σ^2=p1*(m1-mG)^2+p2*(m2-mG)^2					(3)

将(1)代入(3)得:

σ^2=p1*p2*(m1-m2)^2										(4)

其中:

在这里插入图片描述
根据文献,对式(4)进行变形
首先灰度级K的累加均值m和图像全局均值mG分别为:

在这里插入图片描述
根据式(6),m1、m2变形为:

m1=1/p1m (10)
m2=1/p2
(mG-m) (11)

式(10)、(11)代入(4),可得类间方差公式:

在这里插入图片描述

根据式(5)、(8)、(9)求得式上式(12)最大化的灰度级k就是OTSU阈值。

三、代码实现

//自适应阈值 传入图像为灰度图
int Otsu(Mat src)
{
	//传入的图像为灰度图
	//图像宽、高
	int width = src.cols;
	int height = src.rows;
	//对应像素值数量
	int pixelCount[256] = { 0 };
	//对应像素值占比
	float pixelPro[256] = { 0 };
	//图像像素数
	int pixelSum = width * height;
	int threshold = 0;

	//统计灰度级中每个像素在整幅图像中的个数
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			int pixel = (int)src.at<uchar>(i, j);
			pixelCount[pixel]++;
		}
	}

	//计算每个像素在整幅图像中的比例
	for (int i = 0; i < 256; i++)
	{
		pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
	}

	//经典ostu算法,得到前景和背景的分割
	//遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
	/*
	w0,w1:前景和背景所占整幅图像的比例
	u0,u1:前景和背景的平均灰度
	u:整幅图像平均灰度
	*/
	float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
	for (int i = 0; i < 256; i++)
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
		for (int j = 0; j < 256; j++)
		{
			if (j <= i) //背景部分
			{
				//以i为阈值分类,第一类总的概率
				w0 += pixelPro[j];
				u0tmp += j * pixelPro[j];
			}
			else
				//前景部分
			{
				//以i为阈值分类,第二类总的概率
				w1 += pixelPro[j];
				u1tmp += j * pixelPro[j];
			}
		}
		u0 = u0tmp / w0;        //第一类的平均灰度
		u1 = u1tmp / w1;        //第二类的平均灰度
		u = u0tmp + u1tmp;        //整幅图像的平均灰度
		//计算类间方差
		deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
		//找出最大类间方差以及对应的阈值
		if (deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			threshold = i;
		}
	}
	//返回最佳阈值;
	return threshold;

}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
传统的Canny算法使用固定的高斯滤波器和阈值来进行边缘检测。但是,在实际应用中,这种方法可能会导致一些问题,如噪声和边缘细节的丢失。因此,我们可以对传统的Canny算法进行改进,使用自适应高斯滤波器和模拟退火算法下的Oust阈值分割来提高边缘检测的精度。 自适应高斯滤波器可以根据图像中的局部特征调整高斯核的大小和方差。这样可以使滤波器更好地适应图像的特征,从而减少噪声的影响。同时,模拟退火算法可以通过模拟热力学中的过程来寻找最优解,从而得到更合适的阈值分割结果。 在MATLAB中,我们可以使用以下代码实现改进后的Canny算法: ```matlab img = imread('image.jpg'); % 读取图像 % 自适应高斯滤波 sigma = 0.5; hsize = round(2.5*sigma)*2+1; img_filtered = imgaussfilt(img, sigma, 'FilterSize', hsize); % 模拟退火算法下的Oust阈值分割 T = sa_otsu(img_filtered); img_binary = imbinarize(img_filtered, T); % Canny边缘检测 sigma_canny = 1; [~, threshold] = edge(img_binary, 'canny', [], sigma_canny); fudgeFactor = 0.5; threshold = threshold * fudgeFactor; img_edge = edge(img_filtered, 'canny', threshold, sigma_canny); % 显示结果 figure; subplot(1,2,1); imshow(img); title('原图'); subplot(1,2,2); imshow(img_edge); title('改进后的Canny算法'); ``` 其中,`sa_otsu`是利用模拟退火算法实现Oust阈值分割函数。整个算法的流程为:先对图像进行自适应高斯滤波处理,然后使用模拟退火算法下的Oust阈值分割得到二值图像,最后使用改进后的Canny算法进行边缘检测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忘·月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值