共計 5015 個字符,預計需要花費 13 分鐘才能閱讀完成。
今天就跟大家聊聊有關 Serverless 中火絨使用云函數 SCF 快速部署驗證碼識別接口,可能很多人都不太了解,為了讓大家更加了解,丸趣 TV 小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
驗證碼識別是搞爬蟲實現自動化腳本避不開的一個問題。通常驗證碼識別程序要么部署在本地,要么部署在服務器端。如果部署在服務器端就需要自己去搭建配置網絡環境并編寫調用接口,這是一個極其繁瑣耗時的過程。
但是現在我們通過騰訊云云函數 SCF,就可以快速將本地的驗證碼識別程序發布上線,極大地提高了開發效率。
效果展示
可以看到,識別效果還是蠻好的,甚至超過了肉眼識別率。
操作步驟
傳統的驗證碼識別流程是
圖像預處理(灰化,去噪,切割,二值化,去干擾線等)
驗證碼字符特征提?。⊿VM,CNN 等)
驗證碼識別
下面我就帶大家一起來創建、編寫并發布上線一個驗證識別云函數
第一步:新建 python 云函數
參見系列文章《萬物皆可 Serverless 之使用 SCF+COS 快速開發全棧應用》
第二步:編寫驗證識別云函數
Life is short, show me the code.
這里我就以一個最簡單的驗證碼識別程序為例,直接上代碼
import io
import os
import time
from PIL import Image as image
import json
#字符特征
chars = { 1 : [1, 1, 1, 0, 1, ...],
2 : [1, 0, 0, 1, 0, ...],
3 : [0, 1, 0, 0, 1, ...],
# 其他字符特征...
for y in range(img.size[1]):
img.putpixel((0, y), 255)
img.putpixel((1, y), 255)
img.putpixel((2, y), 255)
img.putpixel((img.size[0]-1, y), 255)
img.putpixel((img.size[0]-2, y), 255)
img.putpixel((img.size[0]-3, y), 255)
for x in range(img.size[0]):
img.putpixel((x, 0), 255)
img.putpixel((x, 1), 255)
img.putpixel((x, 2), 255)
img.putpixel((x, img.size[1]-1), 255)
img.putpixel((x, img.size[1]-2), 255)
img.putpixel((x, img.size[1]-3), 255)
return img
# 去除干擾線并轉換為黑白照片
def clearline(img):
for y in range(img.size[1]):
for x in range(img.size[0]):
if int(img.getpixel((x, y))) = 110:
img.putpixel((x, y), 0xff)
else:
img.putpixel((x, y), 0x0)
return img
# 去噪 /pnum- 去噪效率
def del_noise(im, pnum=3):
w, h = im.size
white = 255
black = 0
for i in range(0, w):
im.putpixel((i, 0), white)
im.putpixel((i, h - 1), white)
for i in range(0, h):
im.putpixel((0, i), white)
im.putpixel((w - 1, i), white)
for i in range(1, w - 1):
for j in range(1, h - 1):
val = im.getpixel((i, j))
if val == black:
cnt = 0
for ii in range(-1, 2):
for jj in range(-1, 2):
if im.getpixel((i + ii, j + jj)) == black:
cnt += 1
if cnt pnum:
im.putpixel((i, j), white)
else:
cnt = 0
for ii in range(-1, 2):
for jj in range(-1, 2):
if im.getpixel((i + ii, j + jj)) == black:
cnt += 1
if cnt = 7:
im.putpixel((i, j), black)
return im
# 圖片數據二值化
def two_value(code_data):
table = [serverless]
for i in code_data:
if i 140: # 二值化分界線 140
table.append(0)
else:
table.append(1)
return table
# 圖片預處理
def pre_img(img):
img = covergrey(img) # 去色
img = clearedge(img) # 去邊
img = clearline(img) # 去線
img = del_noise(img) # 去噪
return img
# 處理圖片數據
def data_img(img):
code_data = [serverless] # 驗證碼數據列表
for i in range(4): # 切割驗證碼
x = 5 + i * 18 # 可用 PS 確定圖片切割位置
code_data.append(img.crop((x, 9, x + 18, 33)).getdata())
code_data[i] = two_value(code_data[i]) # 二值化數據
return code_data
# 驗證碼識別
def identify(data):
code = [ ]*4 # 驗證碼字符列表
diff_min = [432]*4 # 初始化最小距離 -- 不符合的數據點個數(共 120 數據點) for char in chars: # 遍歷驗證碼字符(每個字符比較一次 4 個驗證碼) diff = [0]*4 # 各驗證碼差距值 (每個字符判斷前重置此距離)
for i in range(4): # 計算四個驗證碼
for j in range(432): # 逐個像素比較驗證碼特征
if data[i][j] != chars[char][j]:
diff[i] += 1 # 距離 +1
for i in range(4):
if diff[i] diff_min[i]: # 比已有距離還要小(更加符合) diff_min[i] = diff[i] # 刷新最小距離
code[i] = char # 刷新最佳驗證碼
return .join(code) # 輸出結果
img = image.open(io.BytesIO(img))
img = pre_img(img) # 預處理圖片
data = data_img(img) # 獲取圖片數據
code = identify(data) # 識別驗證碼
return code
statusCode : code,
headers : {Content-Type : application/json , Access-Control-Allow-Origin : *},
body : json.dumps(reply, ensure_ascii=False)
}
main_start = time.time()
flag = True if image in event[queryString] else False
code = predict(event[ queryString][image]) if image in event[queryString] else 無效的請求
return apiReply({
ok : flag,
code : code,
spendTime : str(time.time()-main_start)
})
老規矩,先捋一下整個云函數的流程。
def main_handler(event, context):
main_start = time.time()
flag = True if image in event[queryString] else False
code = predict(event[ queryString][image]) if image in event[queryString] else 無效的請求
return apiReply({
ok : flag,
code : code,
spendTime : str(time.time()-main_start)
})
首先,我們通過 event 事件拿到 api 請求的驗證碼 image 數據,然后判斷一下 image 參數是否存在,若不存在就返回請求無效的提示
def predict(imgs):
code =
img = imgs.read()
img = image.open(io.BytesIO(img))
img = pre_img(img) # 預處理圖片
data = data_img(img) # 獲取圖片數據
code = identify(data) # 識別驗證碼
return code
如果 image 請求參數存在就調用 predict 函數解析識別驗證碼,流程如下:
讀取驗證碼圖像
驗證碼圖像預處理
識別處理后的驗證碼
# 圖片預處理
def pre_img(img):
img = covergrey(img) # 去色
img = clearedge(img) # 去邊
img = clearline(img) # 去線
img = del_noise(img) # 去噪
return img
我們來看一下圖像預處理過程
將驗證碼去色,轉為灰度圖
去除驗證碼黑色邊框
去除驗證碼干擾線
去除驗證碼噪點
# 字符特征
chars = { 1 : [1, 1, 1, 0, 1, ...],
2 : [1, 0, 0, 1, 0, ...],
3 : [0, 1, 0, 0, 1, ...],
# 其他字符特征...
# 驗證碼識別
def identify(data):
code = [ ]*4 # 驗證碼字符列表
diff_min = [432]*4 # 初始化最小距離 -- 不符合的數據點個數(共 120 數據點) for char in chars: # 遍歷驗證碼字符(每個字符比較一次 4 個驗證碼) diff = [0]*4 # 各驗證碼差距值 (每個字符判斷前重置此距離)
for i in range(4): # 計算四個驗證碼
for j in range(432): # 逐個像素比較驗證碼特征
if data[i][j] != chars[char][j]:
diff[i] += 1 # 距離 +1
for i in range(4):
if diff[i] diff_min[i]: # 比已有距離還要?。ǜ臃希?nbsp;diff_min[i] = diff[i] # 刷新最小距離
code[i] = char # 刷新最佳驗證碼
return .join(code) # 輸出結果
PS:文章中的字符特征 chars 并不完整,你可能需要自行提取所有特征。
最后來看一下驗證碼的識別過程:這里我們直接簡單粗暴地取處理后圖像數據的所有像素點作為字符的特征(所謂大道至簡),然后將每個待識別字符處理后圖像的數據與所有字符的特征逐個比較,取最相似的那個字符作為識別結果。
嗯,沒什么問題的話,你就可以得到正確的識別結果了。
看完上述內容,你們對 Serverless 中火絨使用云函數 SCF 快速部署驗證碼識別接口有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注丸趣 TV 行業資訊頻道,感謝大家的支持。