【图像分割】使用Otsu 算法及迭代计算最佳全局阈值估计并实现图像分割(代码实现与分析)

        本实验要求理解全局阈值分割的概念,并实现文本图像分割。需要大家深入理解Ostu 算法的实现过程及其迭代原理,同时通过学习使用Otsu 算法及其迭代,实践图像分割技术在文本图像处理中的应用。

        以下将从实验原理、实验实现、实验结果分析三部分对整个实验进行阐述

实验原理

全局阈值分割原理

        全局阈值分割是一种基于灰度图像的简单分割方法。其基本思想是根据一个固定的阈值T,将图像中的每个像素点的灰度值与阈值T进行比较。如果像素点的灰度值大于或等于T,则将其归为前景(通常表示感兴趣的物体或区域);否则,将其归为背景。

Otsu算法原理

        Otsu算法是一种自动选择全局阈值的方法,它通过最大化类间方差(inter-class variance)来确定最优的阈值。类间方差反映了前景和背景两类像素之间的差异程度,差异越大,说明分割效果越好。

以下是Otsu算法的具体步骤:

        a. 计算图像的灰度直方图:直方图表示了图像中各个灰度级像素出现的频率。

        b. 计算各类别的概率:对于每一个可能的阈值T,可以将图像分为两个类别,一类是灰度值小于T的像素,另一类是灰度值大于或等于T的像素。计算这两个类别的像素数(或者像素的概率)。

        c. 计算类间方差:类间方差定义为两类像素的平均灰度值之差的平方乘以两类像素的概率之和。类间方差越大,说明两类像素的差异越大,分割效果越好。

        d. 寻找最优阈值:遍历所有可能的阈值,对于每个阈值,计算其对应的类间方差。选择使类间方差最大的那个阈值作为最佳全局阈值。

图像分割实现

        利用计算出的最佳全局阈值,对原始图像进行二值化处理,即根据阈值将每个像素点的灰度值转换为0(背景)或1(前景),从而实现图像的分割。

实验实现

输入图像

在本次实验中,小组选取了三幅灰度图片作为实验的输入图像,如下图所示。

实验代码 

        利用Python实现Otsu算法及其迭代方法。对于输入的图像,首先生成它的一个渐变灰度图像,接着计算图像的直方图,并基于直方图使用Otsu方法和迭代方法分别寻找最佳的阈值。

import cv2
import numpy as np
import osdef get_file_paths(folder_path):# 获取文件夹内所有文件的路径file_paths = [os.path.join(folder_path, file) for file in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, file))]return file_pathsdef generate_gradient_image(width, height):# 生成渐变灰度图像数据gradient_image = np.zeros((height, width), dtype=np.uint8)# 计算每一列的亮度值for col in range(width):brightness = int(255 * col / width)gradient_image[:, col] = brightnessreturn gradient_imagedef save_image(image, file_path):# 保存图像cv2.imwrite(file_path, image)def iterative_thresholding(image, epsilon=1e-6, max_iter=100):# 初始阈值threshold = 128.0for _ in range(max_iter):# 根据当前阈值将图像二值化binary_image = image > threshold# 计算前景和背景的平均灰度mean_foreground = np.mean(image[binary_image])mean_background = np.mean(image[~binary_image])# 计算新的阈值new_threshold = 0.5 * (mean_foreground + mean_background)# 如果新旧阈值之间的差异小于 epsilon,停止迭代if abs(new_threshold - threshold) < epsilon:breakthreshold = new_thresholdreturn thresholddef otsu_thresholding(image): # 计算otsu全局最优阈值# 计算直方图hist, bins = np.histogram(image.flatten(), 256, [0, 256])# 归一化直方图hist = hist.astype(float) / sum(hist)# 初始化类内方差和类间方差var_within = np.zeros(256)var_between = np.zeros(256)for t in range(1, 256):# 类内方差w0 = sum(hist[:t])w1 = sum(hist[t:])mu0 = sum(i * hist[i] for i in range(t)) / w0 if w0 > 0 else 0mu1 = sum(i * hist[i] for i in range(t, 256)) / w1 if w1 > 0 else 0var_within[t] = w0 * w1 * (mu0 - mu1) ** 2# 类间方差var_between[t] = w0 * w1 * (mu0 - mu1) ** 2# 找到最佳阈值optimal_threshold = np.argmax(var_between)return optimal_thresholddef threshold(image_path): # 生成阈值化图像# 读取图像img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)image_path=image_path[5:]# 应用Otsu方法获取最佳阈值otsu_threshold = otsu_thresholding(img)# print(f"threshold:{threshold}")# 使用阈值进行二值化print(f'otsu_threshold:{otsu_threshold}')_, binary_image = cv2.threshold(img, otsu_threshold, 255, cv2.THRESH_BINARY)# 保存阈值化图像save_image(binary_image, f'Otsu_{image_path}')iterative_threshold = iterative_thresholding(img)# print(f"threshold:{threshold}")# 使用阈值进行二值化print(f'iterative_threshold:{iterative_threshold}')_, binary_image = cv2.threshold(img, iterative_threshold, 255, cv2.THRESH_BINARY)# 保存阈值化图像save_image(binary_image, f'iterative_{image_path}')print(f'{image_path[:-4]}测试已完成')if __name__ == '__main__':# # 设置图像的宽度和高度# width = 640# height = 480# # 生成渐变图像# image = generate_gradient_image(width, height)# # 保存图像# save_image(image, 'exam0.jpg')folder_path = 'exam'# 获取文件夹内所有文件的路径exam_paths = get_file_paths(folder_path)# 依次测试图像for image_path in exam_paths:print(f'image_name:{image_path[5:]}')threshold(image_path)

实验结果分析 

对于三幅图像使用Otsu方法和迭代方法进行全局阈值分割的实验结果和分析如下:

(1)图像一处理结果

        由上图第一组实验结果可以看出,对于灰度分布规律简单的图像,全局分割的阈值寻找较为简单,利用Otsu算法和迭代算法的效果几乎没有区别。 

(2)图像二处理结果

        如上图所示,第二组实验中,Otsu算法和迭代方法在作用于灰度值分界较为明显的图像上时均取得了很好的分割效果。 

(3)图像三处理结果

        由上图所示第三组实验可以看出,即使是边界并不是非常清晰的图片,Otsu方法和迭代方法也都能取得很好的分割效果。


以上为本次实验的全部内容~

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

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

相关文章

(黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

&#xff08;黑马出品_高级篇_01&#xff09;SpringCloudRabbitMQDockerRedis搜索分布式 微服务技术——保护 今日目标1.初识Sentinel1.1.雪崩问题及解决方案1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel 1.…

Mock.js了解(Mock就是模拟一个后端,Postman模拟前端)

Mock.js 基于 数据模板 生成模拟数据。基于 HTML模板 生成模拟数据。拦截并模拟 ajax 请求。 基本语法 DTD&#xff08;数据模板定义规范&#xff09; 数据模板的每个属性由3部分构成&#xff1a;属性名、生成规则、属性值&#xff08;‘name|rule’: value&#xff09; 属性名…

Elasticsearch:调整搜索速度

在我之前的文章 “Elasticsearch&#xff1a;如何提高查询性能” 及 “Elasticsearch&#xff1a;提升 Elasticsearch 性能” 里&#xff0c;我详细描述了如何提高搜索的性能。在今天的文章里&#xff0c;我从另外一个视角来描述如何调整搜索的速度。希望对大家有所帮助&#x…

基于springboot+vue的早餐店点餐系统(源码+论文)

作者主页&#xff1a;Java程序员老张 主要内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;…

Python基础综合案例-数据可视化

一、数据可视化 - 折线图可视化 1.1、json数据格式 """ 演示JSON数据和Python字典的相互转换 """ import json # 准备列表&#xff0c;列表内每一个元素都是字典&#xff0c;将其转换为JSON data [{"name": "张大山", &quo…

dp入门:从暴力dfs 到 dp

本篇为小金鱼大佬视频的学习笔记&#xff0c;原视频链接&#xff1a;https://www.bilibili.com/video/BV1r84y1379W?vd_source726e10ea5b787a300ceada715f64b4bf 基础概念 暴力dfs很多时候仅能过部分测试点&#xff0c;要想将其优化&#xff0c;一般以 dfs -> 记忆化搜索 …

JavaEE—— HTTP协议(上篇)

文章目录 一、认识什么是 HTTP 协议二、HTTP 抓包工具1.了解使用哪种工具2.了解抓包工具抓包的原理3.简单使用抓包工具 三、解释 HTTP 中的报文格式1.认识 URL2. 认识 HTTP 请求解释首行 "方法"解释 请求头(header)空行body 3、总结 一、认识什么是 HTTP 协议 HTTP …

PS学习 - 抠图-通道-主题颜色和背景颜色不能相近

抠出蝴蝶 1.通道抠图 套索工具 这里需要圈住你要的&#xff0c;注意尽量小点 ctrl j 复制 然后去掉背景 点击通道 找到明暗对比最大的通道&#xff0c;这里我理解为颜色反差最大的那个&#xff0c;突出你要抠的东西 搜了下说是一般为蓝色 复制通道 ctrll调出色阶 通过移…

一文总结python的异常数据处理示例

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

springboot278基于JavaWeb的鲜牛奶订购系统的设计与实现

鲜牛奶订购系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统鲜牛奶订购信息管理难度大&…

VMwareWorkstation16与Ubuntu 22.04.6 LTS下载与安装

一、准备工作 VMware Workstation Pro 16官网下载&#xff1a; https://customerconnect.vmware.com/cn/downloads/info/slug/desktop_end_user_computing/vmware_workstation_pro/16_0。下载需要账号登录。 二、安装 双击exe文件稍等一会会弹出安装程序&#xff0c;如图 这…

Airtest-Selenium升级兼容Selenium 4.0,给你全新体验!

一、前言 在上期更新推文中提到&#xff0c;我们Airtest-Selenium更新到了1.0.6版本&#xff0c;新增支持Selenium4.0的语法&#xff0c;那么我们来看一下Airtest-Selenium更新后有什么新的内容吧~ 二、selenium 4.0有什么新功能 selenium4.0最主要的还是定位元素方法的更新…

力扣--最小覆盖子串--双端队列+滑动窗口

滑动窗口思路&#xff08;双端队列实现&#xff09;&#xff1a; 可以参考一下&#xff1a;力扣hot8---滑动窗口-CSDN博客以及力扣hot9---滑动窗口-CSDN博客。 使用滑动窗口有以下几个步骤&#xff1a;初始化双端队列&#xff08;将s的前t_len个元素入队&#xff0c;此时检验是…

spring源码分析-事务的底层源码-1

这里写自定义目录标题 spring事务的源码分析阅读spring事务源码的前置知识JDBC的事务spring当中和事务相关的对象spring应用程序编码spring事务的源码如何开始研究spring源码当中如何代理bean spring事务的源码分析 最近在研究seata&#xff1b;看了一下spring当中的事务有一点…

第十三届蓝桥杯(C/C++ 大学B组)

目录 试题 A: 九进制转十进制 试题 B: 顺子日期 试题 C: 刷题统计 试题 D: 修剪灌木 试题 E: X 进制减法 试题 F: 统计子矩阵 试题 G: 积木画 试题 H: 扫雷 试题 I: 李白打酒加强版 试题 J: 砍竹子 试题 A: 九进制转十进制 九进制正整数 ( 2022 )转换成十进制等于多…

Hypermesh碰撞安全之安全带缠绕建模

进入安全带建模&#xff08;Analysis→safety→belt routing) ①肩带的创建 注&#xff1a;end types: 表示2D和1D单元的过渡方式 ②腰带的创建 ③修改接触系数

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Tabs)

通过页签进行内容视图切换的容器组件&#xff0c;每个页签对应一个内容视图。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件从API Version 11开始默认支持安全区避让特性(默认值为&#x…

【老旧小区用电安全谁能管?】安科瑞智慧用电安全管理系统解决方案

行业背景 电气火灾指由电气故障引发的火灾。每年以30%的比例高居各类火灾原因之首。以50%到80%的比例高居重特大火灾之首。已成为业界重点关注的对象并为此进行着孜孜不倦的努力。 国务院安委会也于2017年5月至2020年4月年开展了为期3年的电气火灾综合治理工作。在各界努力的…

HJ212协议C#代码解析实现

HJ212协议C#代码解析实现 HJ212协议是环保中一个非常重要的标准协议&#xff08;字符串协议&#xff09;&#xff0c;之前写了两篇C HJ212协议解析的相关博文&#xff1a; 环保 HJ212协议解析基于Qt5.14.2的HJ212 TCP服务端接收解析入库程序 最近在学习C#&#xff0c;所以打算…

接口幂等性问题和常见解决方案

接口幂等性问题和常见解决方案 1.什么是接口幂等性问题1.1 会产生接口幂等性的问题1.2 解决思路 2.接口幂等性的解决方案2.1 唯一索引解决方案2.2 乐观锁解决方案2.3 分布式锁解决方案2.4 Token解决方案(最优方案) 3 Token解决方案落地3.1 token获取、token校验3.2 自定义注解,…