圖像二值化與otsu算法介紹

圖像的二值化,就是講圖像變成黑或者白兩種顏色。在很多場(chǎng)合,對(duì)圖像進(jìn)行二值化,可以忽略圖像的顏色信息,背景信息,保留更加重要的形態(tài)信息。并且圖像二值化處理之后,圖像的信息量大為減少,處理起來(lái)也更加方便。

最簡(jiǎn)單的圖像二值化的方法。就是先將圖像轉(zhuǎn)化為灰度圖,然后再設(shè)置一個(gè)閾值。小于這個(gè)閾值的像素點(diǎn)調(diào)整成0,而大于這個(gè)閾值的像素點(diǎn)調(diào)整成255。

在Python3下,用PIL做圖像處理,代碼如下:

from PIL import Image

def binarizing(image, threshold=200):
    pixdata = image.load()
    w, h = image.size
    for y in range(h):
        for x in range(w):
            if pixdata[x, y] < threshold:
                pixdata[x, y] = 0
            else:
                pixdata[x, y] = 255
    return image

當(dāng)然,使用的時(shí)候,圖像首先要轉(zhuǎn)成灰度圖

im = Image.open('1.png').convert('L')

這里的默認(rèn)閾值是200。這樣對(duì)處理已經(jīng)基本是黑白的情況(例如黑白的電子書(shū))效果比較好。但是如果要處理自帶底色的(例如火車票)等,直接使用默認(rèn)閾值就可能使得整張圖幾乎變成黑色或者白色。例如下圖,圖一的閾值取在160左右效果比較好,而如果取200,則圖像會(huì)變成純黑色。如果我們要處理更多種類的情況,默認(rèn)閾值法根本不適用。

不同圖的灰度直方圖

我們看到,文字圖片和背景通常會(huì)出現(xiàn)兩個(gè)駝峰。因此,我們需要有一個(gè)算法找到這兩個(gè)駝峰中間的最佳的閾值。otsu法(最大類間方差法,有時(shí)也稱之為大津算法)就是目前比較好的確定閾值的算法。

otsu算法的原理非常簡(jiǎn)單。首先,我們把圖像分成大于閾值和小于閾值的兩個(gè)部分,也就是前景與背景兩個(gè)部分。我們可以計(jì)算這兩個(gè)部分的類間方差。類間方差越大,就說(shuō)明兩個(gè)部分直接的灰度差距越大。將0~255這256個(gè)閾值都試用一遍,找到類間方差最大的值,通常就是我們要找的最佳閾值了。

代碼如下:

import numpy as np

def otsu_threshold(im):
    width, height = im.size
    pixel_counts = np.zeros(256)
    for x in range(width):
        for y in range(height):
            pixel = im.getpixel((x, y))
            pixel_counts[pixel] = pixel_counts[pixel] + 1
    # 得到圖片的以0-255索引的像素值個(gè)數(shù)列表
    s_max = (0, -10)
    for threshold in range(256):
        # 遍歷所有閾值,根據(jù)公式挑選出最好的
        # 更新
        w_0 = sum(pixel_counts[:threshold])  # 得到閾值以下像素個(gè)數(shù)
        w_1 = sum(pixel_counts[threshold:])  # 得到閾值以上像素個(gè)數(shù)
        
        # 得到閾值下所有像素的平均灰度
        u_0 = sum([i * pixel_counts[i] for i in range(0, threshold)]) / w_0 if w_0 > 0 else 0
        
        # 得到閾值上所有像素的平均灰度
        u_1 = sum([i * pixel_counts[i] for i in range(threshold, 256)]) / w_1 if w_1 > 0 else 0
        
        # 總平均灰度
        u = w_0 * u_0 + w_1 * u_1

        # 類間方差
        g = w_0 * (u_0 - u) * (u_0 - u) + w_1 * (u_1 - u) * (u_1 - u)

        # 類間方差等價(jià)公式
        # g = w_0 * w_1 * (u_0 * u_1) * (u_0 * u_1)

        # 取最大的
        if g > s_max[1]:
            s_max = (threshold, g)
    return s_max[0]

效果還是不錯(cuò)的。(把個(gè)人信息刪去了)

火車票二值化
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容