第六章DIP作业-RCOTSU图像分割

淋过雨的不退课人士

        OTSU图像分割算法使用最大类间方差作为标准,利用图像直方图的分布信息,计算出一个阈值,根据像素是否超过阈值将图像分为前景与背景。如下图分别为原图,调用open-cv的threshold接口的二值化图像及自己写的otsu算法所得二值化图像。使用OTSU算法可得出该图类间方差最大阈值为21。如图所得,直接实现的OTSU算法对图像进行二值化处理的结果和用OpenCV中OTSU阈值分割的方法对图像进行处理的结果相同

第六章DIP作业-RCOTSU图像分割_第1张图片

第六章DIP作业-RCOTSU图像分割_第2张图片第六章DIP作业-RCOTSU图像分割_第3张图片第六章DIP作业-RCOTSU图像分割_第4张图片

            我们输出原图的灰度直方图,可以看出原图灰度呈双峰,由图像信息可以大致推测,灰度值较低的峰值大部分为图像的黑色暗区域,然后出现的次低灰度峰值为非血管的区域,我们感兴趣的亮区域血管灰度值较高没有形成明显峰值,范围大概为(50,250)。

        RCOtsu算法的大致思路是在ROI,即血管区域使用Otsu算法,达到对算法的优化。我们将需要进行Otsu阈值计算的范围缩小,设定一个阈值下限和一个阈值上限。根据多次实验,选取的下限为15,选取的上限是150。可以得到下图,很清晰的分割出了血管区域。

第六章DIP作业-RCOTSU图像分割_第5张图片

        Otsu算法优点是计算简单快速,不受图像亮度和对比度的影响。缺点为对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。需要结合实际背景进行一些阈值调整才能得出更好的结果。

代码如下:

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


img = cv2.imread('MRA.pgm')
#img = cv2.imread('MRA_Reference.pgm')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_hist = cv2.calcHist([gray], [0], None, [256], [0,256], False)
plt.plot(gray_hist)
plt.show()

plt.imshow(img, "gray")
plt.title("source image"), plt.xticks([]), plt.yticks([])
plt.show()

ret1, th1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)  #方法选择为THRESH_OTSU
plt.imshow(th1, "gray")
plt.title("OTSU-opencv " + str(ret1)), plt.xticks([]), plt.yticks([])
plt.show()


# 大津二值化算法
def otsu(gray_img):
    h = gray_img.shape[0]
    w = gray_img.shape[1]
    threshold_t = 0
    max_g = 0

    # 遍历每一个灰度层
    for t in range(50,250):
        # 使用numpy直接对数组进行运算
        n0 = gray_img[np.where(gray_img < t)]
        n1 = gray_img[np.where(gray_img >= t)]
        w0 = len(n0) / (h * w)
        w1 = len(n1) / (h * w)
        u0 = np.mean(n0) if len(n0) > 0 else 0.
        u1 = np.mean(n1) if len(n0) > 0 else 0.

        g = w0 * w1 * (u0 - u1) ** 2
        if g > max_g:
            max_g = g
            threshold_t = t
    print('类间方差最大阈值:', threshold_t)
    gray_img[gray_img < threshold_t] = 0
    gray_img[gray_img >= threshold_t] = 255
    return gray_img



gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
otsu_img = otsu(gray_img)
plt.imshow(otsu_img , "gray")
plt.title("otsu"), plt.xticks([]), plt.yticks([])
plt.show()

你可能感兴趣的:(python)