重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
今天就跟大家聊聊有关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快速部署验证码识别接口有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。