圖像處理庫 pillow應用-驗證碼去噪

前面咱們學習了 Python 的圖像處理庫 PIL,學會了一些相關的圖像處理方法,好多人內心會問:有什麼用呢?這一節咱們就拿實際的例子來回答你們。算法

識別驗證碼的原理

如今大多數網站登陸再也不是簡單地輸入用戶名密碼了,通常都伴隨着此兩者以外的驗證手段,目的是阻止一些居心不良的行爲。而圖片驗證碼是其中一種比較經常使用的手段。所謂道高一尺魔高一丈,在 IT 行業中,對於這種安全防守,確定會有針對性地破解勢力。對於圖片驗證碼的識別破解,目前已經有了不少成熟的方法。我想大概是從自動搶火車票興起以後快速發展而來的吧。安全

首先咱們來看一張未處理的驗證碼圖片:bash

image-vc.png

想要識別驗證碼,咱們須要有一套圖片識別算法(這個目前已經有成熟的應用,你們能夠自行搜索),而後拿到足夠多的樣本去餵養它,讓它不斷地自我學習,不斷提高識別準確率。在餵養算法以前,咱們首先要作的就是對原始圖片進行處理,通常包括的步驟是:app

  • 將彩色圖片轉換成灰度圖
  • 將灰度圖二值化處理
  • 去除圖片噪點

通過這三步處理以後,通常圖片的驗證碼數字或者字母會比較明顯好辨別了。函數

下面咱們以上面那張簡單的驗證碼圖片爲例,來運用 Python 的 PIL 庫的方法對圖片進行去噪處理。學習

1. 彩色圖片轉換成灰度圖

什麼事灰度圖呢?灰度圖,也能夠認爲是黑白圖。咱們知道彩色圖片是有不一樣的顏色的像素組合到一塊兒的,灰度圖能夠相似的認爲是由不一樣灰度值的像素組合在一塊兒後呈現出來的。網站

任何顏色都有紅、綠、藍三原色組成,假如原來某點的顏色爲 RGB(R,G,B),那麼,咱們能夠經過下面幾種方法,將其轉換爲灰度:ui

  • 1.浮點算法
Gray=R*0.3+G*0.59+B*0.11
複製代碼
  • 2.整數方法
Gray=(R*30+G*59+B*11)/100
複製代碼
  • 3.移位方法
Gray =(R*76+G*151+B*28)>>8
複製代碼
  • 4.平均值法
Gray=(R+G+B)/3
複製代碼
  • 5.僅取綠色
Gray=G
複製代碼

經過上述任一種方法求得Gray後,將原來的RGB(R,G,B)中的R,G,B統一用Gray替換,造成新的顏色RGB(Gray,Gray,Gray),用它替換原來的RGB(R,G,B)就是灰度圖了。spa

咱們用代碼實現很是簡單:3d

from PIL import Image

# 打開原始圖片
im = Image.open('vc.png')
# 展現原始圖片
im.show()

# 將原始圖片灰度化
grey_im = im.convert('L')
# 展現灰度化圖片
grey_im.show()
# 保存灰度化圖片
grey_im.save('grey.png')
複製代碼

運行上面代碼後,咱們能夠看到轉換後的灰度圖了,以下所示:

image-grey.png

2. 將灰度圖片二值化

咱們已經獲得了灰度圖,接下來就是將灰度圖二值化。所謂二值化就是將灰度圖像轉換成由黑白二色組成的圖像。思路就是肯定一個閾值,大於閾值的像素表示爲白色,小於閾值的像素表示爲黑色,以此將圖片的像素(灰度值)劃分爲兩部分:0和1,例如0表明黑色,1表明白色,而後咱們就能夠用一串0和1組成的數字來表示一張圖片。

from PIL import Image

# 二值處理
# 設定閾值threshold,像素值小於閾值,取值0,像素值大於閾值,取值1
# 閾值具體多少須要屢次嘗試,不一樣閾值效果不同
def get_table(threshold=115):
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    return table

# 打開灰度化圖片並進行二值處理
binary_im = Image.open('grey.png').point(get_table(120), "1")
# 展現二值化圖片
binary_im.show()
# 保存二值化圖片
binary_im.save('binary.png')
複製代碼

咱們首先定義了一個二值處理的方法,該方法就是根據傳入的一個閾值,將0到256之間的數進行分類,大於這個閾值取1,小於閾值取0。而後咱們使用 Image 的 point 方法,該方法針對傳入的函數對每個像素點進行操做。咱們傳入二值處理方法,對每一個像素點進行二值化處理,將圖片轉換成二值圖片。

這裏的閾值是須要你們嘗試以後才能肯定的,不一樣的圖片,在閾值不一樣時會出現不一樣的處理效果,你們須要用不一樣的閾值去處理,查看處理以後的效果圖,找到比較合理的閾值。本例中使用的是120。

通過二值化處理以後,咱們的圖片變成了下面這樣:

image-binary.png

3. 對圖片進行降噪處理

咱們看二值化後的圖片,能夠看到還有一些干擾線,這些線條也會影響算法的識別準確率,因此咱們須要想辦法去掉這些干擾線。

降噪的方法有不少,主要難點是判斷哪些點是噪點。因爲咱們這張驗證碼圖片上的數字和字母的線條比干擾線的線條粗,所以咱們認爲字母和數字線條上的點周圍8個點範圍內黑色點的個數應該比干擾線上的點要多。所以咱們這裏採用的思路是:

根據一個點 A 的 RGB 值,與周圍的8個點的 RBG 值比較,設定一個值 N(0 <N <8),當 A 的 RGB 值與周圍8個點的 RGB 相等數小於 N 時,此點爲噪點。

對應的程序代碼爲:

from PIL import Image, ImageDraw


# 判斷噪點,若是確認是噪點,用該點的上面一個點的灰度進行替換
# 根據一個點A的RGB值,與周圍的8個點的RBG值比較,設定一個值 N(0 <N <8),當A的RGB值與周圍8個點的RGB相等數小於N時,此點爲噪點
# x, y: 像素點座標
# G: 圖像二值化閥值
# N: 降噪率 0 < N <8
def get_pixel(image, x, y, G, N):
    # 獲取像素值
    L = image.getpixel((x, y))

    # 與閾值比較
    if L > G:
        L = True
    else:
        L = False

    nearDots = 0

    if L == (image.getpixel((x - 1, y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x - 1, y)) > G):
        nearDots += 1
    if L == (image.getpixel((x - 1, y + 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x, y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x, y + 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1, y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1, y)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1, y + 1)) > G):
        nearDots += 1

    if nearDots < N:
        return image.getpixel((x, y - 1))
    else:
        return None


# 降噪
# Z: 降噪次數
def clear_noise(image, G, N, Z):
    draw = ImageDraw.Draw(image)

    for i in range(0, Z):
        for x in range(1, image.size[0] - 1):
            for y in range(1, image.size[1] - 1):
                color = get_pixel(image, x, y, G, N)
                if color is not None:
                    draw.point((x, y), color)

# 打開二值化圖片
b_im = Image.open('binary.png')
# 將二值化圖片降噪
clear_noise(b_im, 50, 4, 4)
# 展現降噪後的圖片
b_im.show()
# 保存降噪後的圖片
b_im.save('result.png')
複製代碼

在本例中,咱們設置的二值化閾值爲50,降噪率爲4,降噪次數爲4.這幾個參數也是不一樣的圖片會有不一樣的值,你們須要根據不一樣的圖片自行設定。

降噪後的圖片效果以下:

image-result.png

咱們能夠看到,通過上面的處理以後,圖片上的字母和數字已經很清晰了,再使用圖片識別算法,準確率應該會很高。

除了上面的步驟,咱們還能夠經過 PIL 庫的 ImageEnhance 和 ImageFilter 對圖片作其餘處理,例如增長對比度、亮度、銳化等,最終的目的都是去除圖片的噪點,是圖片更容易辨別。你們若是感興趣的話能夠試試看。

總結

本節咱們經過使用 PIL 庫的一些簡單方法,對驗證碼圖片進行一系列的處理,從而達到降噪的目標。經過本節的學習,你們應該要學會學以至用,運用咱們學習的一些理論知識去解決工做或生活中遇到的實際問題。 PIL 庫還有不少其餘的方法均可以用來對圖片進行不一樣的處理,你們能夠本身去探索。

參考

www.osgeo.cn/pillow/refe…

相關文章
相關標籤/搜索