当前位置: 首页 > news >正文

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

一. Triangle方法

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

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

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

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

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

import cv2
import matplotlib.pylab as pltdef main():img = cv2.imread('6.jpg', 0)ret, thresh1 = cv2.threshold(img, 0, 255, cv2.THRESH_TRIANGLE)print(ret)  # 结果是151.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()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 mathdef 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]] += 1return grayHistdef 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] = 0else: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.0totalEntropy = 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] = 255threshold[threshold<=thresh] = 0return thresh, thresholddef main():img = cv2.imread("6.jpg", 0)thresh, threshImg = thresh_entropy(img)print(thresh) # 结果是104.0titles = ['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.lryc.cn/news/228196.html

相关文章:

  • 监控视频片段合并完整视频|FFmpeg将多个视频片段拼接完整视频|PHP自动批量拼接合并视频
  • client-go controller-runtime kubebuilder
  • 【vue 如何解决响应式丢失】
  • Selenium alert 弹窗处理!
  • 有关自动化的脚本思考 python 按键 javascript
  • CKA认证模块②-K8S企业运维和落地实战-2
  • SpectralDiff论文阅读笔记
  • selenium基本使用、无头浏览器(chrome、FireFox)、搜索标签
  • Html 引入element UI + vue3 报错Failed to resolve component: el-button
  • sen2cor安装
  • 通付盾Web3专题 | SharkTeam:Web3安全实践与创新
  • ARM Linux 基础学习 / Ubuntu 下的包管理 / apt工具
  • springcloudalibaba入门详细使用教程
  • C# DirectoryInfo类的用法
  • IDEA常用快捷键大全(详解)
  • 设计模式之解释器模式
  • 粉够荣获淘宝联盟区域理事会常务理事,携手共铸淘客新生态
  • Python爬虫是否合法?
  • 3.2 IDAPro脚本IDC常用函数
  • 用python将csv表格数据做成热力图
  • 【程序基础】递归法
  • AI 绘画 | Stable Diffusion WebUI的基本设置和插件扩展
  • 如何用自然语言 5 分钟构建个人知识库应用?我的 GPTs builder 尝试
  • rabbitmq启动异常解决
  • OpenGL_Learn08(坐标系统与3D空间)
  • github私有仓库开发,公开仓库发布版本
  • 绿色低碳 数字未来-辽宁省建筑电气2023年学术年会-安科瑞 蒋静
  • day55
  • 如何安装Node.js? 创建Vue脚手架
  • ASP.NETWeb开发(C#版)-day1-C#基础+实操