图像二值化阈值调整——Triangle算法,Maxentropy方法

一. Triangle方法

算法描述:三角法求分割阈值最早见于Zack的论文《Automatic measurement of sister chromatid exchange frequency》主要是用于染色体的研究,该方法是使用直方图数据,基于纯几何方法来寻找最佳阈值,它的成立条件是假设直方图最大波峰在靠近最亮的一侧,然后通过三角形求得最大直线距离,根据最大直线距离对应的直方图灰度等级即为分割阈值,图示如下:

三角几何化的过程。首先找到直方图中灰度值最高的一点并判别亮暗,然后找到最左边点,两点连接一条直线,求直方图上离直线最远的点,设置该点的灰度值为阈值。

有时候最大波峰对应位置不在直方图最亮一侧,而在暗的一侧,这样就需要翻转直方图,翻转之后求得值,用255减去即得到为阈值T。扩展情况的直方图表示如下:

算法特点:适用于单峰。这点和OTSU算法有很大区别,OTSU适用于双峰。

cv2中有三角分割的算法,直接使用即可。

import cv2
import matplotlib.pylab as plt

def main():
    img = cv2.imread('6.jpg', 0)
    ret, thresh1 = cv2.threshold(img, 0, 255, cv2.THRESH_TRIANGLE)
    print(ret)  # 结果是151.0

    titles = ['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()

main()

二. Maxentropy方法

最大熵阈值分割法和OTSU算法类似,假设将图像分为背景和前景两个部分。熵代表信息量,图像信息量越大,熵就越大,最大熵算法就是找出一个最佳阈值使得背景与前景两个部分熵之和最大。

给定一个大小为M*N的图像,直方图中所有矩形框所代表的数值之和,即为图像中的像素数量,设像素值i的像素在图中有h(i)个,即:

\sum_{i=0}^{K-1}h(i)=MN

相对应的归一化直方图表示为:

p(i)=\frac{h(i)}{MN}

其中0<=i<K。通常被解释为一个随机过程的概率分布或概率密度函数,p(i)表示的是图像中像素灰度值为i所出现的概率。i的累积概率值为1,即概率分布p必须满足以下关系:

\sum_{i=0}^{K-1}p(i)=1

与累积概率所对应的累积直方图H是一个离散的分布函数P()(通常也称为累积分布函数或cdf),P(i)表示像素值小于等于i的概率:

P(i)=\sum_{j=0}^{i}p(j)

在图像处理中,灰度图的熵定义如下:

Entropy=-\sum_{i=0}^{K-1}p(i)log_2p(i)

因为p(i)\in \left [ 0,1 \right ],所以log_2p(i)<0,-log_2p(i)>0

利用图像熵为准则进行图像分割有一定历史了,学者们提出了许多以图像熵为基础进行图像分割的方法。以下介绍一种由Kapuret al提出来,现在仍然使用较广的一种图像熵分割方法。

给定一个特定的阈值q(0<=q<K-1),对于该阈值所分割的两个图像区域C0,C1,这两部分的熵可写为:

H(0)=- \sum_{i=0}^{q}\frac{p(i)}{P_0(q)}log_2\frac{p(i)}{P_0(q)}

H(1)=- \sum_{i=q+1}^{K-1}\frac{p(i)}{P_1(q)}log_2\frac{p(i)}{P_1(q)}

其中:P_0(q)=\sum_{i=0}^{q}p(i)P_1(q)=\sum_{i=q+1}^{K-1}p(i)P_0(q)+P_1(q)=1

图像总熵为:H_q=H(0)+H(1)现在就是要遍历q(0<=q<K-1),使得Hq最大。

为了计算方便,对H(0)和H(1)的表达式进行优化:

H(0)=- \sum_{i=0}^{q}\frac{p(i)}{P_0(q)}\left ( log_2p(i)-log_2P_0(q) \right ) =-\frac{1}{P_0(q)}[\sum_{i=0}^{q}p(i)log_2p(i)-log_2P_0(q)\sum_{i=0}^{q}p(i)]

得到H(0)=\frac{1}{P_0(q)}S_0(q)+log_2P_0(q)

同理H(1)=\frac{1}{P_1(q)}S_1(q)+log_2P_1(q)

其中S_0(q)=-\sum_{i=0}^{q}p(i)log_2p(i)S_1(q)=-\sum_{i=q+1}^{K-1}p(i)log_2p(i)

import cv2
import matplotlib.pylab as plt
import numpy as np
import math

def calcGrayHist(image):
    rows, cols = image.shape[:2]
    grayHist = np.zeros([256], np.uint64)
    for row in range(rows):
        for col in range(cols):
            grayHist[image[row][col]] += 1
    return grayHist

def thresh_entropy(image):
    rows, cols = image.shape
    # 求灰度直方图
    grayHist = calcGrayHist(image)
    # 归一化灰度直方图,即概率直方图
    normGrayHist = grayHist / float(rows*cols)  # 就是上面讲的p(i)
    # 1.计算累加直方图
    zeroCumuMoment = np.zeros([256], np.float32) # 就是上面讲的P(i)
    for i in range(256):
        if i == 0:
            zeroCumuMoment[i] = normGrayHist[i]
        else:
            zeroCumuMoment[i] = zeroCumuMoment[i-1] + normGrayHist[i]
    # 2.计算各个灰度级的熵
    entropy = np.zeros([256], np.float32)  # 就是上面讲的S_0(q)
    for i in range(256):
        if i == 0:
            if normGrayHist[i] == 0:  # 0log2_0是0,但是对数在0处没有定义
                entropy[i] = 0
            else:
                entropy[i] = -normGrayHist[i] * math.log2(normGrayHist[i])
        else:
            if normGrayHist[i] == 0:
                entropy[i] = entropy[i-1] # 0log2_0是0,但是对数在0处没有定义
            else:
                entropy[i] = entropy[i-1] - normGrayHist[i] * math.log2(normGrayHist[i])
    # 3.找阈值
    fT = np.zeros([256], np.float32)
    ft1, ft2 = 0.0, 0.0
    totalEntropy = entropy[255]
    for i in range(255):
        # 找最大值
        ft1 = entropy[i] / zeroCumuMoment[i] + math.log2(zeroCumuMoment[i])
        ft2 = (entropy[255] - entropy[i]) / (1 - zeroCumuMoment[i]) + math.log2(1 - zeroCumuMoment[i])
        fT[i] = ft1 + ft2
    # 找最大值的索引,作为得到的阈值
    print(fT)
    threshLoc = np.where(fT == np.max(fT))
    thresh = threshLoc[0][0]
    # 阈值处理
    threshold = np.copy(image)
    threshold[threshold>thresh] = 255
    threshold[threshold<=thresh] = 0
    return thresh, threshold

def main():
    img = cv2.imread("6.jpg", 0)
    thresh, threshImg = thresh_entropy(img)
    print(thresh) # 结果是104.0
    titles = ['Original Image', 'After Binarization']
    images = [img, threshImg]

    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()

main()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt 项目实战 | 音乐播放器

Qt 项目实战 | 音乐播放器 Qt 项目实战 | 音乐播放器播放器整体架构创建播放器主界面媒体对象状态实现播放列表实现桌面歌词添加系统托盘图标 资源下载 官方博客&#xff1a;https://www.yafeilinux.com/ Qt开源社区&#xff1a;https://www.qter.org/ 参考书&#xff1a;《Q…

怎么建模HEC-RAS【案例-利用HEC-RAS分析河道建筑对洪水管控的作用】 洪水计算、堤防及岸坡稳定计算、冲淤分析、壅水计算、冲刷计算、水工构筑物建模

背景介绍 人口数量的增长、不合理的区域规划和无计划的工程实践&#xff0c;让洪水对于人类而言变得极具风险。 为了最大程度地减少洪水造成的损害&#xff0c;采取管控措施往往需要在初期执行&#xff0c;为了研究这些管控措施&#xff0c;需要确定河段桥梁和作为调节的水利设…

[工业自动化-7]:西门子S7-15xxx编程 - PLC主站 - 电源模块

目录 前言&#xff1a; 一、主站电源PM VS PS 1.1 主站PM电源模块(PM) 1.2 主站PS电源模块 1.3 PM/PS电源模块区别 1.4 如何选择PM/PS电源 1.5 什么时候必须使用PM模块 1.6 什么时候必须使用PS模块 二、背板总线 三、电源模块的安装 前言&#xff1a; 一、主站电源PM…

电商项目之Java8函数式接口落地实践

文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中&#xff0c;会调用很多第三方的云服务&#xff0c;比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动&#xff0c;有时候发起调用后会拿到500的状态码&#xf…

jquery的项目,html页面使用vue3 +element Plus

vue3&#xff0c;element引入 <script src"../vue3.3.8/vue.global.js"></script> <link rel"stylesheet" href"js/elementPlus/index.css"> <script src"js/elementPlus/index.full.js"></script>…

Flutter笔记:关于Flutter中的大文件上传(上)

Flutter笔记 关于Flutter中的大文件上传&#xff08;上&#xff09; 大文件上传背景与 Flutter 端实现文件分片传输 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#…

开发知识点-Pygame

Pygame Pygame最小开发框架与最小游戏游戏开发入门单元开篇 Pygame简介安装游戏开发入门语言开发工具的选择 Pygame最小开发框架与最小游戏 游戏开发入门单元开篇 Pygame简介安装 游戏开发入门语言开发工具的选择

【案例卡】clickhouse:多行数据拼接在一行

一、需求 针对clickhouse数据库中&#xff0c;group by 分组后的字符串字段&#xff0c;拼接处理在一行的问题实现。在mysql中&#xff0c;可以用group_concat()函数来实现&#xff0c;而clickhouse数据库不支持此函数&#xff0c;特此记录实现方式。 二、clickhouse相关函数…

FreeRTOS_内存管理

目录 1. 内存管理简介 2. 内存碎片 3. heap_1 内存分配方法 3.1 分配方法简介 4. heap_2 内存分配方法 4.1 分配方法简介 4.2 内存块详解 5. heap_4 内存分配方法 6. FreeRTOS 内存管理实验 6.1 实验程序 内存管理是一个系统基本组成部分&#xff0c;FreeRTOS 中大量…

【刚体姿态运动学】角速度和欧拉角速率的换算关系的详细推导

0 引言 本文以一种新的角度推导刚体姿态运动学&#xff0c;也即角速度和欧拉角速率之间的换算&#xff0c;不同于相似博文的地方在于&#xff0c;本文旨在从原理上给出直观清晰生动的解释。将详细过程记录于此&#xff0c;便于后续学习科研查找需要。 1 符号 符号含义 { E }…

STM32 GPIO

STM32 GPIO GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口&#xff0c;也就是我们俗称的IO口 根据使用场景&#xff0c;可配置为8种输入输出模式 引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V 数据0就是低电平&#xff0c…

一篇带你精通php

华子目录 什么是phpphp发展史平台支持和数据库支持网站静态网站和动态网站的区别静态网站动态网站的特点 关键名词解析服务器概念IP的概念域名DNS端口 web程序的访问流程静态网站访问流程动态网站访问流程 php标记脚本标记标准标记&#xff08;常用&#xff09; php注释 什么是…

Linux Hadoop平台伪分布式安装

Linux Hadoop 伪分布式安装 1. JDK2. Hadoop3. MysqlHive3.1 Mysql8安装3.2 Hive安装 4. Spark4.1 Maven安装4.2 Scala安装4.3 Spark编译并安装 5. Zookeeper6. HBase 版本概要&#xff1a; jdk&#xff1a; jdk-8u391-linux-x64.tar.gzhadoop&#xff1a;hadoop-3.3.1.tar.gzh…

Spring Ioc 容器启动流程

Spring容器的启动流程 本文基于 Spring 5.3.23 基于XML文件 public void test() {ApplicationContext applicationContext new ClassPathXmlApplicationContext("applicationContext.xml");User user applicationContext.getBean("user", User.class)…

MySQL大表数据导入到MongoDB

修改参数 &#xff0c;开启into outfile的功能 secure_file_priv/home/backups/mysql_outfile 重启数据库是参数生效 按条件导出MySQL数据 select * from receipt_receive_log where gmt_create > 2020-04-13 00:00:00 and gmt_create< 2020-07-13 00:00:00 INTO O…

微信小程序真机调试连接状态一直在正常和未链接之间反复横跳?

背景&#xff1a;小程序真机调试的时候&#xff0c;发现真机的network不显示接口调用情况&#xff0c;控制台也没有输出内容。具体如下所示&#xff1b; 解决方法&#xff1a; 1、确保手机端连接的网络和微信开发者工具网络一致&#xff0c;比如用同一个WiFi 2、真机自动调试…

极狐GitLab CI 助力 .Net 项目研发效率和质量双提升

目录 .NET nuget 自动生成测试包&#xff08;prerelease&#xff09;版本号 .NET 版本号规范 持续集成自动打包 持续集成自动修改版本号 .NET 行级增量代码规范——拯救老项目 本地全量代码规范 行级增量代码规范 很多团队或开发者都会使用 C#、VB 等语言开发 .Net 应用…

ROS源码安装应用,VSCode

ROS源码安装应用 安装一下VSCode 前置文章 到安装程序的目录中: 完成克隆 编译 catkin_make打开ros核心 roscore打开应用程序 rosrun turtlesim turtlesim_node安装一下VSCode deb下载地址 sudo dpkg -i code_1.84.1-1699275408_amd64.deb添加项目工程到工作空间&#xff…

MyBatis中文网

MyBatis中文网https://mybatis.net.cn/ MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Ja…

go语法入门2

字符串 使用双引号或反引号引起来的任意个字符。它是字面常量。 func main() {var a "abc\n测试" // \n换行fmt.Println(a) } abc 测试func main() {var a "abc\n\t测试" \\换行后在tabfmt.Println(a) } abc测试func main() {var a abc测试 …