灰度化:在RGB模型中,如果R=G=B時,則彩色表示一種灰度顏色,其中R=G=B的值叫做灰度值,因此,灰度圖像每個像素值只需一個字節存放灰度值(又稱強度值、亮度值),灰度範圍爲0-255。
二值化:二值化可以把灰度圖片轉換成二值圖像,把大於某個臨界灰度值的像素灰度設置爲灰度極大值,把小於這個值的像素灰度設爲灰度極小值,從而實現二值化。
原始圖
灰度圖
二值化後的圖
我們可以看到對於這張驗證碼效果還不錯,接下來我們用代碼實現。
首先我們進行圖片轉灰度並二值化
def GrayscaleAndBinarization(image):
'''
灰度並二值化圖片,初步二值化後,會存在一些噪聲點,我們使用這樣一個方法進行去除(不能實現完全去除),
即當圖片中存在一個點灰度值爲0,但其周圍九宮格中像素點的灰度值均爲255時,我們認爲這個點爲孤立點,將其
灰度改爲255
:param image: 處理前的圖片
:return:處理後的圖片
'''
threshold = 17 # 需要自己調節閾值
tmp_image = image.convert('L') # 灰度化
new_image = Image.new('L', tmp_image.size, 0)
# 初步二值化
for i in range(tmp_image.size[1]):
for j in range(tmp_image.size[0]):
if tmp_image.getpixel((j, i)) > threshold:
new_image.putpixel((j, i), 255)
else:
new_image.putpixel((j, i), 0)
# new_image.show() # 去噪前
# 去噪,去除獨立點,將前後左右等九宮格中灰度通道值均爲255的像素點的通道值設爲255
for i in range(1, new_image.size[1] - 1):
for j in range(1, new_image.size[0] - 1):
if new_image.getpixel((j, i)) == 0 and new_image.getpixel((j - 1, i)) == 255 and new_image.getpixel((j + 1, i)) == 255 and \
new_image.getpixel((j, i - 1)) == 255 and new_image.getpixel((j - 1, i - 1)) == 255 and new_image.getpixel((j + 1, i - 1)) == 255 and\
new_image.getpixel((j, i + 1)) == 255 and new_image.getpixel((j - 1, i + 1)) == 255 and new_image.getpixel((j + 1, i + 1)) == 255:
new_image.putpixel((j, i), 255)
# new_image.show() # 去噪後
return new_image
接下來我們找到圖片切割點並對圖片進行切割,對於這種驗證碼,我們進行簡單的垂直切割。首先,我們找到需要進行切割的位置。
def SplitImage(image):
'''
切割圖像並保存,關鍵在於尋找切割位置
:param image: 待切割的圖片
:return: 無
'''
splitSite = [] # 記錄切割的位置
splitSite.append(0)
new_image = image
tmp_list = [0 for i in range(image.size[0])]
for i in range(image.size[0]):
for j in range(image.size[1]):
if image.getpixel((i, j)) == 0:
tmp_list[i] = 1
break
# print(tmp_list)
for index in range(0, len(tmp_list) - 1):
if tmp_list[index] == 1 and tmp_list[index + 1] == 0:
splitSite.append(index + 1)
plt.imshow(image)
for item in splitSite[1:]:
plt.plot([item for i in range(image.size[1])], [i for i in range(image.size[1])])
plt.show() # 使用 matplotlib 模塊進行預覽切割效果
splitSite.append(image.size[0])
# 對圖片進行切割
for index in range(1, len(splitSite) - 1):
box = (splitSite[index - 1], 0, splitSite[index], image.size[1]) # box中四個參數,分別爲距離圖片左側、上側、右側、下側的像素距離
new_image = image.crop(box)
new_image.save('./{}.gif'.format(str(index))) # 保存切割後的圖片,位置在當前目錄
切割後效果圖
- 第一個字母
- 第二個字母
- 第三個字母
- 第四個字母
源碼:https://github.com/kingdowliu/ImageProcessing