共计 5015 个字符,预计需要花费 13 分钟才能阅读完成。
今天就跟大家聊聊有关 Serverless 中火绒使用云函数 SCF 快速部署验证码识别接口,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
验证码识别是搞爬虫实现自动化脚本避不开的一个问题。通常验证码识别程序要么部署在本地,要么部署在服务器端。如果部署在服务器端就需要自己去搭建配置网络环境并编写调用接口,这是一个极其繁琐耗时的过程。
但是现在我们通过腾讯云云函数 SCF,就可以快速将本地的验证码识别程序发布上线,极大地提高了开发效率。
效果展示
可以看到,识别效果还是蛮好的,甚至超过了肉眼识别率。
操作步骤
传统的验证码识别流程是
图像预处理(灰化,去噪,切割,二值化,去干扰线等)
验证码字符特征提取(SVM,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]: # 比已有距离还要小(更加符合) diff_min[i] = diff[i] # 刷新最小距离
code[i] = char # 刷新最佳验证码
return .join(code) # 输出结果
PS:文章中的字符特征 chars 并不完整,你可能需要自行提取所有特征。
最后来看一下验证码的识别过程:这里我们直接简单粗暴地取处理后图像数据的所有像素点作为字符的特征(所谓大道至简),然后将每个待识别字符处理后图像的数据与所有字符的特征逐个比较,取最相似的那个字符作为识别结果。
嗯,没什么问题的话,你就可以得到正确的识别结果了。
看完上述内容,你们对 Serverless 中火绒使用云函数 SCF 快速部署验证码识别接口有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。