上一篇我們聊到了圖片驗證碼處理的基本流程,已經可以應付絕大多數圖片驗證碼了。
驗證碼識別之圖片處理(基礎流程)------ 鏈接戳這裏
我們來看一下成果:
可以看到應付我們的學習算法需求已經足夠。
今天我們來看看一些特殊圖片的處理方法:
1、帶邊框驗證碼:
例如:
這種處理方式比較顯而易見,循環遍歷時直接將
i<2 or i>rows-3 or j<2 or j>cols-3
的點置爲白色即可,代碼我就不上了。
2、背景色爲深色的驗證碼:
例如:
背景顏色比字母顏色深一些,閾值不好定。
這時我們需要獲取圖片背景色,處理依據:
一般背景色都爲圖片中顏色佔比最多,我們只要獲取出現最多的顏色,然後全部置爲白色即可。
即將其變爲:
後續就都一樣了:
python代碼如下:
# 獲取圖片中像素點數量最多的像素並置爲白色
def get_threshold(image):
pixel_dict = defaultdict(int)
# 像素及該像素出現次數的字典
rows, cols = image.size
for i in range(rows):
for j in range(cols):
pixel = image.getpixel((i, j))
pixel_dict[pixel] += 1
count_max = max(pixel_dict.values()) # 獲取像素出現出多的次數
pixel_dict_reverse = {v:k for k,v in pixel_dict.items()}
threshold = pixel_dict_reverse[count_max] # 獲取出現次數最多的像素點
for i in range(rows):
for j in range(cols):
#剔除邊框
if image.getpixel((i, j)) == threshold or i<2 or i>rows-3 or j<2 or j>cols-3:
image.putpixel((i, j), (255, 255, 255, 255))
return image
3、驗證碼中帶有粗粗的干擾線:
我們之前的干擾線處理方式依據爲:
干擾線一般相比較於字母來說比較細,在去除噪點的時候就將其一起去除了。
比如這種:
或者是這種(紅線是我自己畫的。。):
可以看出,我們可以分爲兩種類型:
①顏色和字母同色
②顏色不和字母同色
1、先看第一種,既然顏色,粗細都和字母差不多,也就是說我們無法從外形上直接區分出來,就算是人工來看,區分的依據也是和我們腦海中的字母一個個匹配,這時候我們只能寄希望於我們的學習算法了,這時候我們圖片處理能做的只能是提高圖片切割時候的閾值,來保證圖片的正確切割:
2、再看第二種,粗細和字母差不多,但是顏色則可以有明顯的區分,這時候我們明顯第一感覺就可以將其過濾掉,那同樣,我們的代碼中也是可以實現的。
我們看看干擾線的特點:
①顏色有明顯區分度;
②跨X軸很長;
所以我們的處理依據就出來了:
除背景色外,在X軸上投影上出現次數最多的即爲干擾線,將該顏色轉爲白色即可。
注意,這裏是在X軸投影上出現過的次數,而不是總次數。(統計X=N的線上出現的顏色,不管在這條線上出現了多少個,都算1次)
python代碼如下:
def clear_node_rgb(image):
pixel_list = []
rows, cols = image.size
for i in range(rows):
pixel_rgb = []
for j in range(cols):
rgb = image.getpixel((i, j))
if rgb != (255,255,255) and rgb not in pixel_rgb:
pixel_list.append(rgb)
pixel_rgb.append(rgb)
max_rgb = Counter(pixel_list).most_common(1)[0][0]
for i in range(rows):
for j in range(cols):
pixel = image.getpixel((i, j))
if pixel == max_rgb:
image.putpixel((i, j), (255, 255, 255, 255))
return image
這裏我們處理後的圖片都有一個很明顯的問題:被分割線擋住的部分斷掉了。
那追求完美的我們就需要想辦法去彌補一下了。
在opencv中有一對圖片處理的方法,叫做腐蝕和膨脹。
腐蝕的意思爲將圖片上的內容邊界消除;
膨脹的意思爲將圖片上的內容邊界加粗。
舉個例子:
原圖:
膨脹後:
腐蝕後:
所以,先膨脹後腐蝕,就能消除圖片中的白點,斷層等等。
我們來看看效果:
先膨脹,消除斷層:
再腐蝕,回到原來的比例即可:
python代碼:
import cv2
import numpy as np
def ercode_dilate(img, threshold):
#腐蝕參數, (threshold, threshold)爲腐蝕矩陣大小
kernel = np.ones((threshold, threshold), np.uint8)
# 膨脹圖片
erosion = cv2.erode(img, kernel, iterations=1)
# 腐蝕圖片
eroded = cv2.dilate(erosion, kernel, iterations=1)
return eroded
img = cv2.imread('test.png', 0)
ercode_dilate(img, 6)