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

news2024/11/29 13:44:38

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

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

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

相关文章

基于ssm的线上旅行信息管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于ssm的线上旅行信息管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0…

为什么开源mes更有生命力?

所谓开源&#xff0c;就是软件的源码开放&#xff0c;大家都能下载到源代码&#xff0c;一起研究源代码并对软件进行优化和改进。越来越多的IT公司对开源持开放态度&#xff0c;一方面有了优秀的开源项目&#xff0c;就不用再重复造轮子&#xff0c;可以直接使用&#xff1b;另…

天池AI练习生计划 - 第一期Pyhton入门与实践 正式上线!通关赢取双重礼品!

天池AI练习生养成计划是为天池入门学习用户准备的训练营&#xff0c;用户通关后可获得学习奖励&#xff0c;从学习者蜕变为AI新星&#xff01; 轻松来闯关&#xff0c;即可领取双重礼品~ 实训培训证书&#xff1a;通关两个关卡即可领取 阿里云定制鼠标&#xff1a;通关全部关…

强化学习:原理与Python实战

文章目录 1. 引言2. 时间旅行和平行宇宙3. 强化学习4. 策略梯度算法5. 代码案例6. 推荐阅读与粉丝福利 1. 引言 时间循环是一类热门的影视题材&#xff0c;其设定常常如下&#xff1a;主人公可以主动或被动的回到过去。与此同时&#xff0c;主人公会希望利用这样的机会改变在之…

前端js实现将数组对象组装成自己需要的属性,或者去掉对象中不必要的属性

前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 需求&#xff1a;前端js实现将数组对象组装成自己需要的属性&#xff0c;或者前端js实现去掉对象中不必要的属性 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、示例数组对象…

mongodb通过mongoexport命令导出数据

一、mongoexport命令参数 我们通过mongoexport --help来查看这个命令支持的参数 二、mongoexport几个常用参数的演示 2.1、导出所有数据&#xff0c;格式为json格式 –type 用来指定导出的数据格式&#xff0c;可以导出为.json或者.csv mongoexport --host localhost --…

踩准AI时代风口,NFPrompt让人人都能成为赚取利润的创作者

★ AI寒武纪时代&#xff0c;抓住风口并不难 众所周知&#xff0c;随着ChatGPT的面世&#xff0c;AI在2023年快速爆发&#xff0c;不少人已经意识到AI将在未来能够影响到我们每个人生活方方面面&#xff0c;同时AI也将打破现有的经济与社会格局。对于普通人来说&#xff0c;如…

【Servlet】 三

本文主要介绍了基于serlvet的表白墙项目的编写. (附完整代码) 一.JS基础 作为后端开发,对于前端的要求是能前端代码能看懂七七八八 . JS是一个动态弱类型的编程语言 1. let/war定义变量 (推荐使用let) 2.querySelector是浏览器提供api , 能够获取到页面的元素的 (js的目的就…

aardio 去除收尾空格字符

废话不多说 直接开干&#xff01; 知识点 import console type 关键函数,用于获取对象的数据类型 eval 运行aardio代码&#xff0c;并计算表达式的值 assert 断言函数 assertf 反断言函数 error 抛出异常 tostring 用于转换参数为字符串 topointer 用于转换参数为指针 tonumber…

Nature Food | 南农蒋建东组揭示植物有益细菌的全球分布格局及未来变化(完整版)...

到2100年&#xff0c;化石燃料依赖性情景可能导致全球土壤中植物有益细菌丰度大幅下降 Fossil-fuel-dependent scenarios could lead to a significant decline of global plant-beneficial bacteria abundance in soils by 2100 Article&#xff0c;2023-10-30&#xff0c;Nat…

数据库存储过程

存储过程&#xff1a; 是一组为了完成特定功能的sql语句的集合。类似于函数。 写好了一个存储过程之后&#xff0c;我们可以像函数一样随时调用sql的集合。 复杂的&#xff0c;需要很多sql语句联合执行完成的任务。 存储过程在执行上比sql语句的执行速度要快&#xff0c;效率…

09 # 手写 some 方法

some 使用 some() 方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true&#xff0c;则返回 true&#xff1b;否则返回 false。它不会修改数组。 ele&#xff1a;表示数组中的每一个元素index&#xff1a;表示数…

IDA Pro正版多少钱?本文告诉你!

在软件反向工程和安全分析领域&#xff0c;IDA Pro无疑是一款标志性的工具。这款软件在全球范围内有广泛的应用&#xff0c;用于分析、审计和调试各类软件产品。但是&#xff0c;当我们决定购买这款业界顶级的反汇编和反编译软件时&#xff0c;一个最直接也是最现实的问题摆在面…

Oracle Unifier 22.12 ~ 23.10 功能改进清单表

序言 时隔近一年&#xff0c;Oracle Unifier 22还没握熟&#xff0c;新版本23便已迭代到23.10&#xff0c;根据甲骨文常规的发布规律&#xff0c;相信不久之后便会正式迎来正式本地版V23&#xff0c;了解Unfier的朋友或许知晓&#xff0c;本地版是云版迭代一年后的版本&#x…

怎样使用ovsyunlive在web网页上直接播放rtsp/rtmp视频

业务中需要在网页中直接播放rtsp和rtmp视频&#xff0c;多方比较测试发现ovsyunlive的播放器能直接播放rtsp/rtmp视频&#xff0c;还是非常方便简洁&#xff0c;使用过程如下&#xff1a; 1&#xff0c;Windows系统在github上面下载ovsyunlive绿色包下载解压。 github地址&am…

【中国知名企业高管团队】系列62:海信Hisense

昨天&#xff0c;华研荟介绍了海尔公司的发展历程和张瑞敏先生的创业故事&#xff0c;以及现在海尔集团的高管。今天为您介绍同处一地&#xff0c;发展模式类似的海信集团。 一、关于海信Hisense 海信成立于1969年&#xff0c;前身是“国营青岛无线电二厂”&#xff0c;从收音…

第二章《补基础:不怕学不懂线性代数》笔记

2.1 直观理解向量 2.1.1 理解向量加法与数乘 维度相同的向量之间才可以进行加法运算&#xff0c;向 量进行加法运算时只要将相同位置上的元素相加即可&#xff0c;结果向量的维度保持不变。 向量进行数乘运算时将标量与向量的每个元素 分别相乘即可得到结果向量。 2.1.2 理…

《向量数据库指南》——LlamaIndex 和 Milvus Cloud对于 Chat Towards Data Science 的作用

那么,LlamaIndex 是如何帮助我们协调数据检索?Milvus 又如何帮助搭建聊天机器人的呢?我们可以用 Milvus 作为后端,用于 LlamaIndex 的持久性向量存储(persistent vector store)。使用 Milvus Cloud 实例后,可以从一个 Python 原生且没有协调的应用程序转换到由 LlamaIn…

【代码随想录】算法训练计划15

兄弟们&#xff0c;写到了1点了快 1、层序遍历 题目&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 思路&#xff1a; 左侧也要加进去的&#xff0c;万有右侧没…

stm32 Bootloader设计(YModem协议)

stm32 Bootloader设计&#xff08;YModem协议&#xff09; Chapter1 stm32 Bootloader设计(YModem协议)YModem协议&#xff1a;STM32 Bootloader软件设计STM32 Bootloader使用方法准备工作stm32 Bootloader修改&#xff1a;stm32目标板程序.bin偏移地址修改&#xff1a; Chapt…