文章目录

  • 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,纵轴是图像中每个灰度级像素点的数量。

医学图像处理 实验指导 python 医学图像处理实验二_opencv


  灰度直方图特点: 把整个图像浓缩在直方图中,丢失了所有的空间信息;灰度直方图按照x轴进行积分,就是图像的面积。

  灰度直方图应用:

  (1)设置图像的参数:

  (2)分析图像灰度的变化,确定最优二值化的值:因为灰度直方图通常有一个属性,双峰性(bimodal)(一个称为前景峰值,另一个为背景峰值)。通常两个峰值之间的最小值,为我们想找的最优二值化的分界点。

医学图像处理 实验指导 python 医学图像处理实验二_图像处理_02

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)

医学图像处理 实验指导 python 医学图像处理实验二_医学图像处理 实验指导 python_03

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)

医学图像处理 实验指导 python 医学图像处理实验二_图像处理_04

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)

医学图像处理 实验指导 python 医学图像处理实验二_二值化_05

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

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

2.1 二值化理解

  上一部分依赖灰度直方图可以理解图像,灰度和像素之间的相关性,进而找到统计学的分布。

  二值化: 简单、没有前后关联的、基础、有效的图像分割算法。二值化实际上是通过对灰度直方图的分析,来实现二值化过程。

  图像二值化特点:

  (1)通常为灰度图的二值化

  (2)将图像像素分为两个类别

  (3)产生二值图像

  二值化分类:

  (1)固定阈值二值化(固定阈值,单一阈值或者区间阈值)

  固定或全局阈值,只需要一个值就完成整个图像分割。如何选择最优阈值是研究者一直关注的问题,怎么通过数学或模型的方法取得最优二值化的值。

医学图像处理 实验指导 python 医学图像处理实验二_图像处理_06


医学图像处理 实验指导 python 医学图像处理实验二_opencv_07


医学图像处理 实验指导 python 医学图像处理实验二_医学图像处理 实验指导 python_08

医学图像处理 实验指导 python 医学图像处理实验二_医学图像处理 实验指导 python_09


医学图像处理 实验指导 python 医学图像处理实验二_图像处理_10


  (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)类间方差

医学图像处理 实验指导 python 医学图像处理实验二_opencv_11

:每个类别的平均值与所有像素的总强度平均值的变化.(把整体前景和背景融合起来)

医学图像处理 实验指导 python 医学图像处理实验二_二值化_12


  w0,w1,u0,u1分别代表两个类别的频率、均值

  (2)评价函数: 类间方差除以总方差

医学图像处理 实验指导 python 医学图像处理实验二_医学图像处理 实验指导 python_13


  (3)求取最优二值化值:所有可能的阈值(0-255带入(1)(2)操作)通过上述方式进行评估,最大

医学图像处理 实验指导 python 医学图像处理实验二_opencv_14

为最优化二值化阈值。

2.2.3 Entropy 算法

  熵:用来衡量一个物体,或者图像,信息量的多少。

  步骤:

  (1)假设一个阈值将图像分为前景和背景两个部分,求取前景的熵和背景的熵:

医学图像处理 实验指导 python 医学图像处理实验二_医学图像处理 实验指导 python_15


  Hb和Hw衡量了,前景和背景的信息量的多少。

  (2)将前景的熵和背景的熵进行求和,得到整体熵

医学图像处理 实验指导 python 医学图像处理实验二_二值化_16


  (3)求取H最优值,获取最优二值化的值:所有可能的阈值(0-255带入上述(1)(2)操作)通过上述方式进行评估,最大H值为最优化二值化阈值。

2.2.4 Triangle算法

  原理:在灰度直方图中,找到灰度直方图中,最高峰值的顶点,和其左侧的最小值,在整个直方图中构成三角形,在三角形斜边做垂线,最长的d值为最优的二值化阈值。

医学图像处理 实验指导 python 医学图像处理实验二_图像处理_17

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)

医学图像处理 实验指导 python 医学图像处理实验二_计算机视觉_18

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)

医学图像处理 实验指导 python 医学图像处理实验二_opencv_19

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)

医学图像处理 实验指导 python 医学图像处理实验二_图像处理_20