图像二值化阈值调整——OTSU算法(大津法/最大类间方差法)

本文主要是介绍图像二值化阈值调整——OTSU算法(大津法/最大类间方差法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大津算法(OTSU算法)是一种常用的图像二值化方法,用于将灰度图像转化为二值图像。该算法由日本学者大津展之于1979年提出,因此得名。

大津算法的核心思想是通过寻找一个阈值,将图像的像素分为两个类别:前景和背景。具体步骤如下:

  1. 统计图像的灰度直方图,得到每个灰度级的像素数目。
  2. 遍历所有可能的阈值(0到255),计算根据该阈值将图像分为前景和背景的类内方差。
  3. 根据类内方差的最小值确定最佳阈值。

在大津算法中,类内方差是衡量前景和背景之间差异的度量。通过选择使类内方差最小的阈值,可以实现最佳的图像分割效果。

大津算法的优点是简单易懂,计算效率高。它适用于灰度图像的二值化处理,特别是对于具有双峰直方图的图像效果更好。然而,该算法对于具有非双峰直方图的图像可能产生较差的分割结果。因此,在应用大津算法之前,需要对图像的直方图进行分析,确保适用性。

大津算法在图像处理中被广泛应用,例如在文档图像处理、目标检测、图像分割等领域。

下面推导类间方差函数:

设阈值为灰度k(k\in \left [ 0,L-1 \right ],L=256)。这个阈值把图像像素分割成两类,C1类像素小于等于k,C2类像素大于k。设这两类像素各自的均值为m_1,m_2,图像全局均值为m_G。同时像素被分为C1和C2类的概率分别为p_1,p_2。则有:

p_1m_1+p_2m_2=m_G

p_1+p_2=1

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

\sigma ^2=p_1\left ( m_1-m_G \right )^2+p_2\left ( m_2-m_G \right )^2

展开:

\sigma ^2=p_1m_1^2+p_1m_G^2-2p_1m_1m_G+p_2m_2^2+p_2m_G^2-2p_2m_2m_G

合并2,5及3,6项可得:

\sigma ^2=p_1m_1^2+p_2m_2^2+m_G^2-2m_G^2=p_1m_1^2+p_2m_2^2-m_G^2

我们再把m_G=p_1m_1+p_2m_2代回得到:

\sigma ^2=(p_1-p_1^2)m_1^2+(p_2-p_2^2)m_2^2-2p_1p_2m_1m_2

再注意到p_1+p_2=1,所以p_1-p_1^2=p_1(1-p_1)=p_1p_2p_2-p_2^2=p_2(1-p_2)=p_1p_2,从而得到:

\sigma ^2=p_1p_2(m_1-m_2)^2

对于给定的阈值k,我们可以统计出灰度级的分布列:

灰度值01...255
p_ip_0p_1...p_{255}

显然根据分布列性质有\sum_{i=0}^{L-1}p_i=1(请注意这里的p_1,p_2是分布列中的,不是上面的定义)

那么有:

p_1=\sum_{i=0}^{k-1}p_i,p_2=\sum_{i=k}^{L-1}p_i,m_1=\sum_{i=0}^{k-1}ip_i,m_2=\sum_{i=k}^{L-1}ip_i

将k从\left [ 0,L-1 \right ]遍历,找出使得\sigma ^2最大的k值,这个k值就是阈值。

对于分割,这个分割就是二值化,OpenCV给了以下几种方式(同threshold):

cv2帮助文档:

Miscellaneous Image Transformations — OpenCV 3.0.0-dev documentationicon-default.png?t=N7T8https://docs.opencv.org/3.0-last-rst/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold代码实现:

首先是原理部分的实现,这部分我们使用numpy:

import cv2
import numpy as npdef OTSU(img_gray, GrayScale):assert img_gray.ndim == 2, "must input a gary_img"  # shape有几个数字, ndim就是多少img_gray = np.array(img_gray).ravel().astype(np.uint8)u1 = 0.0  # 背景像素的平均灰度值u2 = 0.0  # 前景像素的平均灰度值th = 0.0# 总的像素数目PixSum = img_gray.size# 各个灰度值的像素数目PixCount = np.zeros(GrayScale)# 各灰度值所占总像素数的比例PixRate = np.zeros(GrayScale)# 统计各个灰度值的像素个数for i in range(PixSum):# 默认灰度图像的像素值范围为GrayScalePixvalue = img_gray[i]PixCount[Pixvalue] = PixCount[Pixvalue] + 1# 确定各个灰度值对应的像素点的个数在所有的像素点中的比例。for j in range(GrayScale):PixRate[j] = PixCount[j] * 1.0 / PixSumMax_var = 0# 确定最大类间方差对应的阈值for i in range(1, GrayScale):  # 从1开始是为了避免w1为0.u1_tem = 0.0u2_tem = 0.0# 背景像素的比列w1 = np.sum(PixRate[:i])# 前景像素的比例w2 = 1.0 - w1if w1 == 0 or w2 == 0:passelse:  # 背景像素的平均灰度值for m in range(i):u1_tem = u1_tem + PixRate[m] * mu1 = u1_tem * 1.0 / w1# 前景像素的平均灰度值for n in range(i, GrayScale):u2_tem = u2_tem + PixRate[n] * nu2 = u2_tem / w2# print(u1)# 类间方差公式:G=w1*w2*(u1-u2)**2tem_var = w1 * w2 * np.power((u1 - u2), 2)# print(tem_var)# 判断当前类间方差是否为最大值。if Max_var < tem_var:Max_var = tem_var  # 深拷贝,Max_var与tem_var占用不同的内存空间。th = ireturn thdef main():img = cv2.imread('6.jpg', 0)# 将图片转为灰度图th = OTSU(img, 256)print("使用numpy的方法:" + str(th))  # 结果为 136main()

然后是基于cv2的OTSU实现,cv2可直接指定使用:

import cv2
import matplotlib.pylab as pltdef main2():img = cv2.imread('6.jpg', 0)ret, thresh1 = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)print(ret)  # 结果是135.0titles = ['Original Image', 'After Binarization']images = [img, thresh1]for i in range(2):plt.subplot(1, 2, i+1)plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()main2()

这篇关于图像二值化阈值调整——OTSU算法(大津法/最大类间方差法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327029

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

poj 3723 kruscal,反边取最大生成树。

题意: 需要征募女兵N人,男兵M人。 每征募一个人需要花费10000美元,但是如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干的男女之间的1~9999之间的亲密关系度,征募某个人的费用是10000 - (已经征募的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得征募所有人的费用最小。 解析: 先设想无向图,在征募某个人a时,如果使用了a和b之间的关系

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int