图像算法--图像分割(Otsu算法)

Otsu算法

图像分割是一个经典的图像任务,Otsu算法是借用图像的灰度值,计算几个阈值,然后起到分割图像的作用。本文介绍的Otsu算法常用于基于图像分割的聚类。该算法的理论依据是:假定图像包含两类像素(前景像素和背景像素),直方图为双峰直方图,然后计算使得两类像素能分开的最佳阈值(类内方差),或等价的间类间方差最大。

算法过程

对于图像 I(x,y)I(x,y),前景(即目标)和背景的分割阈值记作TT,属于前景的像素点数占整幅图像的比例记为 w0w_0,平均灰度为 μ0\mu_0;背景像素点数占整幅图像的比例为w1w_1,平均灰度为 μ1\mu_1;整幅图像的平均灰度记为μ\mu,类间方差记为gg

假设图像大小为M×NM \times N,图像中像素的灰度值小于阈值TT 的像素个数为 N0N_0,像素灰度大于阈值TT的像素个数为 N1N_1,那么:

w0=N0M×N(1.1)w_0=\frac{N_0}{M \times N} \tag{1.1}

w1=N1M×N(1.2)w_1=\frac{N_1}{M \times N} \tag{1.2}

N0+N1=M×N(1.3)N_0+N_1=M \times N \tag{1.3}

w0+w1=1(1.4)w_0 + w_1=1 \tag{1.4}

μ=w0μ0+w1μ1(1.5)\mu = w_0 * \mu_0 + w_1*\mu_1 \tag{1.5}

g=w0(μ0μ)2+w1(μ1μ)(1.6)g = w_0(\mu_0-\mu)^2+w_1(\mu_1-\mu) \tag{1.6}

g=w0w1(μ0μ1)2(1.7)g=w_0w_1(\mu_0-\mu_1)^2 \tag{1.7}

采用遍历的方法使得类间方差g最大的阈值T,即为所求。采用阈值的方法一定会存在边界问题,Otsu算法也是一样的,所以Otsu算法是有自己的应用场景的,例如Otsu算法常常用在车牌检测类型的任务上。

举个栗子

# coding=utf-8
import numpy as np


def OTSU(img_array):  # 传入的参数为ndarray形式
    height = img_array.shape[0]
    width = img_array.shape[1]
    count_pixel = np.zeros(256)
    for i in range(height):
        for j in range(width):
            count_pixel[int(img_array[i][j])] += 1
    max_variance = 0.0
    best_thresold = 0
    for thresold in range(256):
        n0 = count_pixel[:thresold].sum()
        n1 = count_pixel[thresold:].sum()
        w0 = n0 / (height * width)
        w1 = n1 / (height * width)
        u0 = 0.0
        u1 = 0.0
        for i in range(thresold):
            u0 += i * count_pixel[i]
        for j in range(thresold, 256):
            u1 += j * count_pixel[j]
        u = u0 * w0 + u1 * w1
        tmp_var = w0 * np.power((u - u0), 2) + w1 * np.power((u - u1), 2)
        if tmp_var > max_variance:
            best_thresold = thresold
            max_variance = tmp_var
    return best_thresold
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×