圖像二值化與otsu算法介紹

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

最簡單的圖像二值化的方法。就是先將圖像轉化為灰度圖,然后再設置一個閾值。小于這個閾值的像素點調(diào)整成0,而大于這個閾值的像素點調(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

當然,使用的時候,圖像首先要轉成灰度圖

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

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

不同圖的灰度直方圖

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

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

代碼如下:

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索引的像素值個數(shù)列表
    s_max = (0, -10)
    for threshold in range(256):
        # 遍歷所有閾值,根據(jù)公式挑選出最好的
        # 更新
        w_0 = sum(pixel_counts[:threshold])  # 得到閾值以下像素個數(shù)
        w_1 = sum(pixel_counts[threshold:])  # 得到閾值以上像素個數(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)

        # 類間方差等價公式
        # 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]

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

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

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