图像二值化阈值调整——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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/126694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-table动态列设置列宽不生效的解决方法

问题 uni-th 在这边是不固定的列数的&#xff0c;即dataList会变 在uni-th 设置固定列宽width200,或者在uni-td 设置不生效&#xff0c;宽度不对 解决方法 在uni-td里面多包一层view,通过设置view的宽度来撑开uni-td <uni-td v-for"(item,index) in dataList"…

springboot打包时依赖jar和项目jar分开打包;jar包瘦身

概述 最近感觉项目在部署时时jar包传输太慢了&#xff1b; 看了下jar包内容&#xff0c;除了项目代码&#xff0c;其余大部分都是依赖jar&#xff1b; 平时改动较多的只是项目代码&#xff0c;依赖jar改动比较少&#xff1b; 所以就在想能不能分开打包&#xff1b;这样只部署项…

【机器学习】一、机器学习概述与模型的评估、选择

机器学习简介 由来 阿瑟.萨缪尔Arthur Samuel,1952年研制了一个具有自学习能力的西洋跳棋程序&#xff0c;1956年应约翰.麦卡锡John McCarthy&#xff08;人工智能之父&#xff09;之邀&#xff0c;在标志着人工智能学科诞生的达特茅斯会议上介绍这项工作。他发明了“机器学习…

uniapp跳转页面多种方式详细例子

Uniapp支持许多种不同的方式来跳转页面。以下是Uniapp中使用多种方式跳转页面的详细示例&#xff1a; 使用navigateTo/navigateBack来跳转页面 navigateTo可以让用户在当前页面打开一个新页面&#xff0c;用户可以返回原来的页面。navigateBack则是返回上一个页面。示例代码如…

Springboot项目Eureka安全加密

一、通过security增加账号密码登录 1、registry服务pom增加security依赖 2、registry 配置文件 指定security账号密码 3、http://账号:密码IP:PORT/eureka/ 4、重启 二、关闭节点 三、防火墙移除eureka端口访问 参考&#xff1a;Linux(Centos7)操作记录

opencv复习(很乱)

2-高斯与中值滤波_哔哩哔哩_bilibili 1、均值滤波 2、高斯滤波 3、中值滤波 4、腐蚀操作 卷积核不都是255就腐蚀掉 5、膨胀操作 6、开运算 先腐蚀再膨胀 7、闭运算 先膨胀再腐蚀 8、礼帽 原始数据-开运算结果 9、黑帽 闭运算结果-原始数据 10、Sobel算子 左-右&#x…

day02 矩阵 2023.10.26

1.矩阵 2.矩阵乘法 3.特殊矩阵 4.逆矩阵 5.正交矩阵 6.几何意义 7.齐次坐标 8.平移矩阵 9.旋转矩阵 10.缩放矩阵 11.复合运算

如何选择安全又可靠的文件数据同步软件?

数据实时同步价值体现在它能够确保数据在多个设备或系统之间实时更新和保持一致。这种技术可以应用于许多领域&#xff0c;如电子商务、社交媒体、金融服务等。在这些领域中&#xff0c;数据实时同步可以带来很多好处&#xff0c;如提高工作效率、减少数据不一致、提高用户体验…

网络编程套接字(一)

网络编程套接字 预备知识理解源IP地址和目的IP地址理解源MAC地址和目的MAC地址理解源端口号和目的端口号PORT VS PID认识TCP协议和UDP协议网络字节序 socket编程接口socket常见APIsockaddr结构 简单的UDP网络程序服务端创建套接字服务端绑定运行服务器客户端代码编写本地测试IN…

为什么在 Vue 的 v-for 循环中使用唯一的 key 可以提高性能?

✨ 为什么在 Vue 的 v-for 循环中使用唯一的 key 可以提高性能&#xff1f; &#x1f383; 简介 在 Vue 的开发中&#xff0c;我们经常使用 v-for 指令来循环渲染列表。然而&#xff0c;在 v-for 循环中为子元素添加唯一的 key 属性能够带来性能上的改进。本文将解释为什么具…

Java 17 有必要升级到Java 21吗?

Java 17 有必要升级到Java 21吗&#xff1f; Java 21是Java平台的12个功能版本之一&#xff0c;于2023年9月19日发布。这个版本主要带来了数千项性能、稳定性和安全更新&#xff0c;并包含了15个重大的新特性和增强。其中最重要的特性之一是虚拟线程的最终化&#xff0c;这些线…

C++-C(0)-字符串-vector-string-基本操作

在C里用C函数是常用的。有时分不清哪个是C哪个是C了。 CC内置整形 int、long、short、 unsigned、char、 unsigned long、long unsigned int、int、 unsigned short&#xff08;16&#xff09;、short、 unsigned char、signed char unsigned long&#xff08;32&#xff0…

02【保姆级】-GO语言开发注意事项(特色重点)

02【保姆级】-GO语言开发注意事项&#xff08;特色重点&#xff09; 一、Go语言的特性1.1 第一个hello word&#xff08;详解&#xff09;1.2 开发编译。&#xff08;重要点 / 面试题&#xff09;1.3 开发注意事项1.4 GO语言的转义字符1.5 注释1.6 API 文档 一、Go语言的特性 …

el-upload 组件上传/移除/报错/预览文件,预览图片、pdf 等功能

目录 页面代码样式代码页面展示 页面代码 dialog.vue <!-- 上传文件 --> <template><el-dialogtitle"上传文件":visible.sync"dialogVisible"width"60%"top"6vh":close-on-click-modal"false"close"h…

Python JSON 使用指南:解析和转换数据

JSON 是一种用于存储和交换数据的语法。JSON 是文本&#xff0c;使用 JavaScript 对象表示法编写。 Python 中的 JSON Python 有一个内置的 json 包&#xff0c;可用于处理 JSON 数据。 示例&#xff1a;导入 json 模块&#xff1a; import json解析 JSON - 从 JSON 转换为…

重温云栖,分享十年成长:我和云栖的故事

文章目录 前言活动背景我和云栖的交际历届峰会主题2009201020112012201320142015201620172018202120222023 技术带来的变化工作生活关注的领域 后记 前言 云栖大会&#xff0c;前身可追溯到2009年的地方网站峰会&#xff0c;2011年演变为阿里云开发者大会&#xff0c;2015年正式…

OpenCV标定演示,及如何生成标定板图片

标定的程序在官方的源码里有&#xff0c; opencv-4.5.5\samples\cpp\tutorial_code\calib3d\camera_calibration 很多小白不知道怎么跑起来&#xff0c;这个也怪OpenCV官方&#xff0c;工作没做完善&#xff0c;其实的default.xml是要自己手动改的&#xff0c;输入的图片也要…

在Maven中发布项目到Nexus私有服务器

一、测试环境 Sonatype Nexus 3.61.0-02 Maven 3.9.2 二、环境配置 2.1找到maven的配置文件 2.2添加私有仓库账户密码 <servers><server><id>nexus</id><username>admin</username><password>admin</password></server&…

rfsoc FPGA 49DR 16收16发模块

前面简单介绍过RFSOC板卡 https://blog.csdn.net/jingjiankai5228/article/details/114734631 整体来说RFSOC降低了传统AD DA软硬件开发难度&#xff0c;但是同样存在整数点FS/N谐波大的问题 交织采样是通过多个AD拼接完成的&#xff0c;所以校准比较关键&#xff0c;和以前常…

【React】03.脚手架的进阶应用

文章目录 暴露webpack配置暴露前后的区别config文件夹&#xff1a;scripts文件夹&#xff1a;package.json 常见的配置修改1.把sass改为less2.配置别名3.修改域名和端口号4.修改浏览器兼容5.处理Proxy跨域 2023年最新珠峰React全家桶【react基础-进阶-项目-源码-淘系-面试题】 …