Dockerfile部署OpenCV环境的闪烁验证码识别模块 | #打卡不停更# 原创
@[toc]
前言
本文章主要使用了开源项目带带弟弟ocr(ddddocr)的验证码识别功能,这个模块对于正常的英文数字的识别能力还是可以的。大家也可以自己试试。但是这几天有需求要识别闪烁验证码,可以说基本上是无法识别成功了。
就像这种。
我开始是使用了超级鹰,但是当我成功爬取之后我发现也不是不能自己解决这个问题,因为虽然ddddocr模块无法完全识别,但是却可以识别出最后三个字母,说明是有能力识别的只不过由于他闪烁的原因所以识别不全,经过百度之后找到了这篇博客也是从这个文章中得到了灵感,最终白嫖成功。
导包
import io
import cv2
import ddddocr
from PIL import Image
import requests
第一种方法
这个方法就是进行手动拼接,但是我觉得这种拼接因人而异,每个人遇到的情况是不同的。建议自行进行调整。
识别模块
def recognize(img):
ocr = ddddocr.DdddOcr()
with open(img, 'rb') as f:
img_bytes = f.read()
res = ocr.classification(img_bytes)
# print(res)
return res
识别模块接收图片文件,进行识别判断
拼接模块
拼接模块获取到图片的字节流后进行截图拼接
def splitImg(img_byte):
a = {'1': '', '2': '', '3': '', '4': ''} # 根据key值保存对应识别结果
img = Image.open(io.BytesIO(img_byte))
# 第一张截图
img.save('1.png')
r = recognize('1.png')
a['1'] = r
# 第二张截图
#Image.seek()在此序列文件中寻找给定的帧。
#Image.tell()返回当前帧号。
img.seek(im.tell() + 1)
img.save('2.png')
r = recognize('2.png')
a['2'] = r
# 第三张截图
img.seek(im.tell() + 1)
img.save('3.png')
r = recognize('3.png')
a['3'] = r
# 第四张截图
img.seek(im.tell() + 1)
img.save('4.png')
r = recognize('4.png')
a['4'] = r
print(a, "-->截图拼接数据")
# 获取结果数据后,拼接数据
res = ""
if a.get('2')[:2] == a.get('3')[:2] or a.get('1')[-2:] == a.get('4')[-2:]:
res = a.get('2')[:2]
res += a.get('1')[-2:]
elif a.get('1')[:2] == a.get('4')[:2] or a.get('1')[:2] == a.get('3')[:2]:
res = a.get('1')[:2]
res += a.get('2')[-2:]
print(res, "截图识别拼接")
return res
这些通过帧数进行截图保存,我们再讲截的图进行识别,然后大家就可以按照符合自身情况的方法去进行拼接。
第二种方法
同样我们第二种方法也是由ddddocr模块提供识别能力。第二种方法是我自己想尝试的但是最后发现效果还是非常不错的。通过cv模块将两张截图的图片进行重叠,这样就能拿到一个完整的静态的英文数字图片,想法是好,但是实际中也会出现截到的图都是刚好缺那一个字母或数字。但是这种情况也比较少,所以总体成功率还是非常高的。当然也还是很多地方可以进行优化的。大家可以自己试试然后进行优化。同时我也将重叠的图片进行了灰度处理。效果也不错
重叠识别模块
使用opencv将图片进行重叠,然后将完整的图片进行识别。
def writeImg():
# 图像融合
# 第一张图和第三张图进行重叠,随后进行识别
img1 = cv2.imread('1.png')
img2 = cv2.imread('3.png')
# 第二张图和第四张图进行重叠,随后进行识别
img3 = cv2.imread('2.png')
img4 = cv2.imread('4.png')
sp = img1.shape
print(sp, "图片大小")
print(sp[0], "height大小")
print(sp[1], "width大小")
# 将图片进行重叠 调整img2的大小与img1的大小一致,融合函数addWeighted()要求输入的两个图形尺寸相同
combine = cv2.addWeighted(cv2.resize(img1, (sp[1], sp[0])), 0.5, cv2.resize(img2, (sp[1], sp[0])), 0.5, 0)
combine1 = cv2.addWeighted(cv2.resize(img3, (sp[1], sp[0])), 0.5, cv2.resize(img4, (sp[1], sp[0])), 0.5, 0)
# cv2.imshow('combine', combine)
cv2.imwrite('cv2-1.png', combine)
cv2.imwrite('cv2-2.png', combine1)
# 将cv2-1.png 图片灰度化处理
img = cv2.imread('cv2-1.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
t, gray1 = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY)
cv2.imwrite('cv2-1.png', gray1)
例如
拼接的结果:
cv2-1的结果:
cv2-2的结果:
Dockerfile部署
首先
当我们准备好云服务器之后,并且测试接口代码是可以正常运作之后,我们就可以开始准备requirements.txt
了。
点击这个之后就会自动生成我们所需的库和对应的版本。
注意
这里注意把opencv-python这个模块删去,因为使用docker直接安装opencv-python模块会缺少很多 cv2 依赖项。
从而出现错误:
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
正常在本机pip install opencv-python是可以的
此命令仅安装本地计算机上正常存在的 cv2 依赖项,但可能会在您的 docker 中丢失,从而导致问题
这是在stackoverflow上找到的回答。所以我们这里将其删除,后面在下载适合docker环境的。
Dockerfile
然后我们使用编辑器进行编写Dockerfile文件。
# 先下载一个基础镜像
FROM python:3.8.0
# 设置作者信息
MAINTAINER Aasee<xxx@qq.com>
# 设置工作目录
WORKDIR /app
# 将当前目录下的所有文件复制到docker引擎中的工作目录
COPY . /app
# 安装依赖
RUN pip3 install -r requirements.txt -i https://pypi.douban.com/simple --trusted-host pypi.douban.com
# 安装适合docker环境的opencv依赖
RUN pip3 install opencv-python-headless==4.5.3.56 -i https://pypi.douban.com/simple --trusted-host pypi.douban.com
# 暴露端口
EXPOSE 5000
# 执行我们的脚本文件
CMD ["python3", "app.py"]
上云
使用xftp将文件上传到服务器。然后执行下面的命令
创建镜像:
docker build -t 镜像名 .
创建容器:
docker run -it --name 容器名 -p 4000:5000 镜像名
就上云了。
当然我们也可以对容器时间和主机进行挂载绑定,例如:
-v /etc/localtime:/etc/localtime
完整命令为
docker run -it --name 容器名 -v /etc/localtime:/etc/localtime -p 4000:5000 镜像名
这里也展示一下接口的接入方法。
python接入demo实例:
def Test():
url = "http://www.aasee.com.cn:4000/recognition"
files = {'userfile': ('flash_code.jpg', 闪烁验证码的字节流)}
res = requests.post(url=url, files=files)
print(res.json())
结果展示
拿到结果之后可以通过调用验证验证码的接口进行判断,返回验证通过的识别码即可。
使用方法
拿到你需要识别的闪烁验证码,将图片的流return到files下,就可以拿到数据,再调用验证码验证接口进行判断,即可拿到正确的验证码。
goooooooooooooooooooooooood