您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關Serverless中火絨使用云函數SCF快速部署驗證碼識別接口,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
驗證碼識別是搞爬蟲實現自動化腳本避不開的一個問題。通常驗證碼識別程序要么部署在本地,要么部署在服務器端。如果部署在服務器端就需要自己去搭建配置網絡環境并編寫調用接口,這是一個極其繁瑣耗時的過程。
但是現在我們通過騰訊云云函數 SCF,就可以快速將本地的驗證碼識別程序發布上線,極大地提高了開發效率。
可以看到,識別效果還是蠻好的,甚至超過了肉眼識別率。
傳統的驗證碼識別流程是
圖像預處理(灰化,去噪,切割,二值化,去干擾線等)
驗證碼字符特征提取(SVM,CNN 等)
驗證碼識別
下面我就帶大家一起來創建、編寫并發布上線一個驗證識別云函數
參見系列文章《萬物皆可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, ...], # 其他字符特征... } # 灰度處理 def covergrey(img): return img.convert('L') # 去除驗證碼邊框 def clearedge(img): 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) # 輸出結果 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 def apiReply(reply, code=200): return { "isBase64Encoded": False, "statusCode": code, "headers": {'Content-Type': 'application/json', "Access-Control-Allow-Origin": "*"}, "body": json.dumps(reply, ensure_ascii=False) } 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) })
老規矩,先捋一下整個云函數的流程。
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]: # 比已有距離還要小(更加符合) diff_min[i] = diff[i] # 刷新最小距離 code[i] = char # 刷新最佳驗證碼 return ''.join(code) # 輸出結果
PS:文章中的字符特征 chars 并不完整,你可能需要自行提取所有特征。
最后來看一下驗證碼的識別過程:這里我們直接簡單粗暴地取處理后圖像數據的所有像素點作為字符的特征(所謂大道至簡),然后將每個待識別字符處理后圖像的數據與所有字符的特征逐個比較,取最相似的那個字符作為識別結果。
嗯,沒什么問題的話,你就可以得到正確的識別結果了。
看完上述內容,你們對Serverless中火絨使用云函數SCF快速部署驗證碼識別接口有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。