数字图像处理 - 实验作业六 - Python

第十章 图像分割

整体等于其部分之和
整体大于其部分之和

实现一种基于梯度算子的边缘检测

这里采用了拉普拉斯算子来进行边缘检测

Laplace算子作为边缘检测的方法之一,也是工程数学中常用的一种积分变换。把图像的像素值想象成一个变化的曲线。对应变化的曲线,一阶导数的极值位置,二阶导数为0,利用这个来检测边缘

实现的边缘检测效果如下所示

在这里插入图片描述

对应的代码为:

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image


def laplace_filter(image):
    kernel_size = 3
    height, width = image.shape
    padding_size = int((kernel_size - 1) / 2)
    template = np.array([[1, 1, 1],
                         [1, -8, 1],
                         [1, 1, 1]])

    padded_img = np.pad(image, padding_size, 'constant')
    edge_of_img = np.zeros_like(image, dtype=float)

    for i in range(height):
        for j in range(width):
            corr = padded_img[i:i + kernel_size, j:j + kernel_size]
            edge_of_img[i, j] = np.abs(np.sum(template * corr))

    return edge_of_img


def process():
    src = np.array(Image.open("man.jpg").convert("L"))
    edge = laplace_filter(src)

    plt.subplot(1, 2, 1)
    plt.imshow(src, cmap='gray')
    plt.axis("off")

    plt.subplot(1, 2, 2)
    plt.imshow(edge, cmap='gray')
    plt.axis("off")
    plt.show()


if __name__ == '__main__':
    process()

实现一种基于阈值的分割方法(利用简单的阈值确定方法)

这里采用的是全局阈值的方法进行分割

全局阈值的计算过程为

  1. 给出初始阈值T
  2. 用T分割图像得到G1和G2
  3. 计算两部分的均值μ1和μ1
  4. 计算新的阈值 T = 1 2 ( μ 1 + μ 2 ) T=\frac{1}{2}(\mu_1+\mu_2) T=21(μ1+μ2)
  5. 重复2-4,直到 ∣ T k − T k − 1 ∣ ≤ T 0 |T_k-T_{k-1}|≤T_0 TkTk1T0

全局阈值分割图像的实现效果如下所示

在这里插入图片描述

实现的代码如下所示:

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import cv2


def global_threshold(image):
    error = 1
    old_t = 127
    new_t = 0

    while True:

        m1 = image[image <= old_t]
        m2 = image[image > old_t]

        mean1 = np.mean(m1)
        mean2 = np.mean(m2)

        new_t = (mean1 + mean2) / 2

        if (np.abs(new_t - old_t)) <= error:
            break
        else:
            old_t = new_t

    return new_t


def process():
    src = np.array(Image.open("man.jpg").convert("L"))
    line = global_threshold(src)
    ret, dst = cv2.threshold(src, line, 255, cv2.THRESH_BINARY)

    plt.subplot(1, 2, 1)
    plt.imshow(src, cmap='gray')
    plt.axis("off")

    plt.subplot(1, 2, 2)
    plt.imshow(dst, cmap='gray')
    plt.axis("off")
    plt.show()


if __name__ == '__main__':
    process()

实现基于类间方差最大(otsu’s)的图像阈值分割

相对于上述方法来说,otus是一种找出全局最佳阈值的方法

大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。

它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小

其实现的效果如下所示

在这里插入图片描述
其实现的代码如下所示

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import cv2


def otsu(image):  # 传入的参数为ndarray形式
    height, width = image.shape
    pixels = np.zeros(256)

    for i in range(height):
        for j in range(width):
            pixels[int(image[i][j])] += 1

    var_best = 0.0
    current_best = 0
    for k in range(1, 256):

        front = pixels[:k].sum() / (height * width)
        back = pixels[k:].sum() / (height * width)
        front_mean = 0.0
        back_mean = 0.0

        for i in range(k):
            front_mean += i * pixels[i]
        for j in range(k, 256):
            back_mean += j * pixels[j]

        front_mean = front_mean / pixels[:k].sum()
        back_mean = back_mean / pixels[k:].sum()

        gray_sum = front_mean * front + back_mean * back
        tmp_var = front * np.power((gray_sum - front_mean), 2) + back * np.power((gray_sum - back_mean), 2)

        if tmp_var > var_best:
            current_best = k
            var_best = tmp_var

    return current_best


def process():
    src = np.array(Image.open("man.jpg").convert("L"))
    best = otsu(src)
    print(best)
    ret, dst = cv2.threshold(src, best, 255, cv2.THRESH_BINARY)

    plt.subplot(1, 2, 1)
    plt.imshow(src, cmap='gray')
    plt.axis("off")

    plt.subplot(1, 2, 2)
    plt.imshow(dst, cmap='gray')
    plt.axis("off")
    plt.show()


if __name__ == '__main__':
    process()
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值