【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)

文章目录

  • 1 灰度直方图
    • 1.1 直方图理解
    • 1.2 直方图计算
    • 1.3 直方图均衡化
      • 1.3.1 全局均衡化
      • 1.3.2 自适应(局部)均值化
  • 2 图像二值化(阈值分割)
    • 2.1 二值化理解
    • 2.2 求取最优二值化阈值的算法(固定阈值)
      • 2.2.1 Isodata算法
      • 2.2.2 OTSU 算法
      • 2.2.3 Entropy 算法
      • 2.2.4 Triangle算法
    • 2.3 二值化代码实现
      • 2.3.1 全局阈值cv.threshold
      • 2.3.2 局部(自适应)阈值cv.adaptiveThreshold
      • 2.3.3 自定义阈值cv.threshold

1 灰度直方图

1.1 直方图理解

  灰度直方图: 灰度直方图是一个像素分布函数,基于每个灰度级(0-255)。横轴是灰度级0-255,纵轴是图像中每个灰度级像素点的数量。
【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第1张图片
  灰度直方图特点: 把整个图像浓缩在直方图中,丢失了所有的空间信息;灰度直方图按照x轴进行积分,就是图像的面积。
  灰度直方图应用:
  (1)设置图像的参数:
  (2)分析图像灰度的变化,确定最优二值化的值:因为灰度直方图通常有一个属性,双峰性(bimodal)(一个称为前景峰值,另一个为背景峰值)。通常两个峰值之间的最小值,为我们想找的最优二值化的分界点。

【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第2张图片

1.2 直方图计算

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
'''绘制每个通道的像素值的直方图:既每个通道下,每个像素出现的频次'''
def image_hist_demo(image):
    ''''''
    color=('blue','green','red')
    for i ,color in enumerate(color):
        hist=cv.calcHist(image,[i],None,[256],[0,255])#图像,通道,mask,bins(直方图size)、range[0,256]
        plt.plot(hist,color=color)
        plt.xlim([0,256])
    plt.show()


src=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
cv.imshow("origin image",src)

image_hist_demo(src)
cv.waitKey(0)

【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第3张图片

1.3 直方图均衡化

  直方图是图像的统计学特征。直方图举例:像素值直方图,边缘、方向,梯度直方图等等。
  直方图有很多应用:均衡化(增强对比度)、有颜色物体跟踪…

  图像直方图均值化都是基于灰度图。直方图均值化自动调整图像对比度,使图像清晰,是图像增强的一个手段

1.3.1 全局均衡化

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def equalHist_demo(image):
    ''''''
    gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)#图像转灰度图
    dst=cv.equalizeHist(gray)
    cv.imshow('equalHist',dst)


src=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
cv.imshow("origin image",src)

equalHist_demo(src)
cv.waitKey(0)

1.3.2 自适应(局部)均值化

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
"""全局均衡化"""
def equalHist_demo(image):
    ''''''
    gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)#图像转灰度图
    dst=cv.equalizeHist(gray)
    cv.imshow('equalHist',dst)

"""自适应(局部)均衡化"""
def clahe_demo(image):
    ''''''
    gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)#图像转灰度图
    clahe=cv.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
    dst=clahe.apply(gray)
    cv.imshow('clahe lHist',dst)


src=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
cv.imshow("origin image",src)
equalHist_demo(src)
clahe_demo(src)
cv.waitKey(0)

  (左)原图、(中)全局均衡化、(右)自适应或局部均衡化

2 图像二值化(阈值分割)

2.1 二值化理解

  上一部分依赖灰度直方图可以理解图像,灰度和像素之间的相关性,进而找到统计学的分布。
  二值化: 简单、没有前后关联的、基础、有效的图像分割算法。二值化实际上是通过对灰度直方图的分析,来实现二值化过程。
  图像二值化特点:
  (1)通常为灰度图的二值化
  (2)将图像像素分为两个类别
  (3)产生二值图像
  二值化分类:
  (1)固定阈值二值化(固定阈值,单一阈值或者区间阈值)
  固定或全局阈值,只需要一个值就完成整个图像分割。如何选择最优阈值是研究者一直关注的问题,怎么通过数学或模型的方法取得最优二值化的值。
在这里插入图片描述
在这里插入图片描述
【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第4张图片

在这里插入图片描述
【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第5张图片
  (2)自适应阈值(局部阈值)
  应用超过一个阈值;将图像切割多个子图像,对每个子图像求取阈值,将二值化后的图像进行拼接得到最终图像;

2.2 求取最优二值化阈值的算法(固定阈值)

  求取最优二值化阈值,实际求取灰度直方图双峰的最低点,但并不是所有图像具有双峰性(或不明显)。
  最优二值化的问题关键在于怎么找到评价函数,该评价函数既包含前景信息,又包括背景信息。通过评价函数求优——求最大值及最小值,最终获取最优二值化的值。
  评价函数经过对全部灰度值进行计算,求最大、最小,最为最优二值化阈值。

2.2.1 Isodata算法

  算法步骤:
  (1)选取初始阈值T0(例,图像灰度值的均值)
  (2)使用阈值T0将图像划分为两部分(R1和R2)
  (3)在R1、R2中分别求取灰度均值μ1和μ2
  (4)整个图像的新的二值化阈值:T1=(μ1+μ2)/2
  (5)重复(2)(3)(4)直至前一个T和当前T值相同
  

2.2.2 OTSU 算法

  OSTU算法思想: 在两个峰值之间找到相关性,进而求取函数最优值,获取两个峰值最低点。
  步骤:
  (1)类间方差在这里插入图片描述:每个类别的平均值与所有像素的总强度平均值的变化.(把整体前景和背景融合起来)
【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第6张图片
  w0,w1,u0,u1分别代表两个类别的频率、均值
  (2)评价函数: 类间方差除以总方差
在这里插入图片描述
  (3)求取最优二值化值:所有可能的阈值(0-255带入(1)(2)操作)通过上述方式进行评估,最大在这里插入图片描述为最优化二值化阈值。

2.2.3 Entropy 算法

  熵:用来衡量一个物体,或者图像,信息量的多少。
  步骤:
  (1)假设一个阈值将图像分为前景和背景两个部分,求取前景的熵和背景的熵:
在这里插入图片描述
  Hb和Hw衡量了,前景和背景的信息量的多少。
  (2)将前景的熵和背景的熵进行求和,得到整体熵
在这里插入图片描述
  (3)求取H最优值,获取最优二值化的值:所有可能的阈值(0-255带入上述(1)(2)操作)通过上述方式进行评估,最大H值为最优化二值化阈值。

2.2.4 Triangle算法

  原理:在灰度直方图中,找到灰度直方图中,最高峰值的顶点,和其左侧的最小值,在整个直方图中构成三角形,在三角形斜边做垂线,最长的d值为最优的二值化阈值。
【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第7张图片

2.3 二值化代码实现

2.3.1 全局阈值cv.threshold

  ret,binary=cv.threshold()

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
''''''
def threshold_demo():
    ''''''
    target=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
    """变为灰度图像"""
    gray=cv.cvtColor(target,cv.COLOR_BGR2GRAY)
    """变为二值图像"""
    #########方法1:此时cv.THRESH_OTSU计算阈值,0,255作废
    ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)#参数:原图像,0,255,二值化方法
    cv.imshow('origin', target)
    print('yuzhi:',ret)#自动计算的分割阈值
    cv.imshow('binary',binary)
    # #########方法2,自动全局阈值,此时cv.THRESH_TRIANGLE计算阈值,0,255作废
    # ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
    # cv.imshow('origin', target)
    # print('yuzhi:', ret)  # 自动计算的分割阈值
    # cv.imshow('binary', binary)
    # #########方法3,自动指定阈值,小于127是黑色,大于127是白色
    # ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY )
    # cv.imshow('origin', target)
    # print('yuzhi:', ret)  # 自动计算的分割阈值
    # cv.imshow('binary', binary)
    # #########方法4.取反.大于127是黑色,小于127是白色
    # ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
    # cv.imshow('origin', target)
    # print('yuzhi:', ret)  # 自动计算的分割阈值
    # cv.imshow('binary', binary)
    # #########方法5.截断阈值,大于127变成127,
    # ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC)
    # cv.imshow('origin', target)
    # print('yuzhi:', ret)  # 自动计算的分割阈值
    # cv.imshow('binary', binary)
    # #########方法6.小于127变为0
    # ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TOZERO)
    # cv.imshow('origin', target)
    # print('yuzhi:', ret)  # 自动计算的分割阈值
    # cv.imshow('binary', binary)

threshold_demo()
cv.waitKey(10000)

【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第8张图片

2.3.2 局部(自适应)阈值cv.adaptiveThreshold

  binary=cv.adaptiveThreshold()

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
''''''
def local_threshold():
    ''''''
    target=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
    """变为灰度图像"""
    gray=cv.cvtColor(target,cv.COLOR_BGR2GRAY)
    """变为二值图像"""
    #########自适应阈值
    ###方法1:cv.ADAPTIVE_THRESH_MEAN_C
    dst=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10)
    cv.imshow('target', target)
    cv.imshow('binary',dst)
    ###方法2:cv.ADAPTIVE_THRESH_GAUSSIAN_C
    # dst=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,25,10)
    # cv.imshow('target', target)
    # cv.imshow('binary',dst)

local_threshold()
cv.waitKey(10000)

2.3.3 自定义阈值cv.threshold

  ret,binary=cv.threshold()
  例使用均值阈值

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
''''''
def custom_threshold():
    ''''''
    target=cv.imread(r'D:\Project\Opencv\Learning01\angelababy.jpg')
    """变为灰度图像"""
    gray=cv.cvtColor(target,cv.COLOR_BGR2GRAY)
    """变为二值图像"""
    h,w=gray.shape[0:2]
    m=np.reshape(gray,[1,w*h])
    mean=m.sum()/(w*h)
    print('mean',mean)
    ret,binary=cv.threshold(gray,mean,255,cv.THRESH_BINARY)
    cv.imshow('target',target)
    cv.imshow('binary',binary)


custom_threshold()
cv.waitKey(10000)

【医学图像处理】 2 灰度直方图、图像二值化(阈值分割)_第9张图片
  
  
  
  
  
  
  
  
  
  

你可能感兴趣的:(医学图像处理,图像处理,opencv,计算机视觉)