旋转验证码截图识别
注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路
如有侵犯,请联系作者下架
本文识别已同步上线至OCR识别网站: http://yxlocr.nat300.top/ocr/other/27
之前写过一篇文章,某东黑边旋转验证码识别,识别思路还是一样,基于梯度的计算,大家看这篇文章可以复习下这篇,链接如下:京东黑边背景旋转验证码识别,本文开始前,先声明一下,本文提供思路,不会放完整代码,有的小伙伴拿我的思路去GPT或者别的大模型那反推,你推出来没有关系,但是你推出来准确率低,来找我要源码,说什么我推出来迟早能做出来,还不如给他源码,什么恶心人的逻辑,还是为了自己卖课用,如此自傲,能推出来一时推不了一世,换个样子你就不会做了,还是老老实实打基础学思路,才能灵活应变
先来看截图验证码部分数据集
这里讲解识别思路前,需要注意一个地方,因为是截图,每个设备分辨率以及截图方式的不同,会导致算法准确度有差异,所以在ocr的demo网站中我上传了三种思路方式,识别方式各有差异,可能你的第一种方式准确率有80,他的第二种方式有80,并且整体截图识别的准确率也无法保证到很高,原因除了上述讲的一种外,还有就是整体图库是很大的
识别思路
注意:本文解决方法为ocr识别网站第一种方式,切图边缘sobel梯度
1、取出旋转缺口
取出旋转接口只要根据黑边的特征去取就可以了,从图中心开始,往外计算黑边圆,使用霍夫圆检测,下面我直接放出代码,以下图作为demo演示
def get_radius(image):
center_tolerance = 10
height, width = image.shape[:2]
image_center = (width // 2, height // 2)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 2)
circles = cv2.HoughCircles(
blurred, # 输入图像
cv2.HOUGH_GRADIENT, # 检测方法
dp=1, # 分辨率与图像分辨率的反比
minDist=20, # 圆心之间的最小距离
param1=100, # Canny边缘检测的高阈值
param2=30, # 圆心检测的阈值
minRadius=90, # 最小半径
maxRadius=1100 # 最大半径
)
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
center = (i[0], i[1])
radius = i[2]
# 计算圆心与图像中心点的距离
distance = np.sqrt((center[0] - image_center[0]) ** 2 + (center[1] - image_center[1]) ** 2)
# 如果圆心距离图像中心在允许范围内,则保留该圆
if distance <= center_tolerance:
return radius
# 如果检测不到,则输出一个大部分通用半径
return 173
取出圆后,效果如下
2、边缘降噪
边缘降噪还是和之前的方式类似,从市面上这么多验证码来看,大致常用的几种方式为(切割小圆、消除黑边、色域转换),本文采用切割小圆+消除黑边的形式,具体为切割小圆后,去除小圆周围的黑边,并等比例放大
# 切割小圆
imagearray_que = split_cicle(imagearray_que, radius - 3)
imagearray_que = large_img(imagearray_que, 1.04)
# 缩小大图,消除黑边
imagearray_bg = bg_circle(imagearray_bg, radius, renum=.93)
通过上述方法后,小圆和背景图如下:
3、计算最小梯度
最小梯度还是和以前一样,万年不变的老套路,具体步骤思路可以看下代码
def merge_img(que_result, bg_image, radius, angle):
# 根据角度将圆放置到背景图中
que_height, que_width = que_result.shape[:2]
# 计算旋转矩阵
rotation_matrix = cv2.getRotationMatrix2D((que_width / 2, que_height / 2), angle, 2)
# 应用旋转矩阵进行旋转
xuanzhuan_result = cv2.warpAffine(que_result, rotation_matrix, (que_width, que_height))
center = (bg_image.shape[1] // 2, bg_image.shape[0] // 2)
# 创建掩膜图像,尺寸与背景图像一致
mask = np.zeros_like(bg_image[:, :, :])
cv2.circle(mask, center, radius, 255, 0) # 在掩膜中画圆
# 计算旋转后的图像放置位置
bg_height, bg_width = bg_image.shape[:2]
circle_height, circle_width = xuanzhuan_result.shape[:2]
# 创建掩膜区域
mask_overlay = np.zeros_like(bg_image[:, :, 0])
# 将掩膜区域扩展到三通道
mask_overlay = cv2.merge([mask_overlay] * 1)
# 创建一个与背景图像相同尺寸的全透明图像
result_with_que = np.copy(bg_image)
return result_with_que
def calculate_gradient_difference(result, circle_radius):
"""计算内外圆的梯度差异"""
center_x = result.shape[1] // 2
center_y = result.shape[0] // 2
# 创建内外圆遮罩
circle_inner_mask = np.zeros_like(result, dtype=np.uint8)
cv2.circle(circle_inner_mask, (center_x, center_y), circle_radius - 10000, 255, 255)
circle_outer_mask = np.zeros_like(result, dtype=np.uint8)
cv2.circle(circle_outer_mask, (center_x, center_y), circle_radius + 10000, 255, 255)
# 分别计算内外圆的梯度
inner_pixels = cv2.bitwise_and(result, circle_inner_mask)
outer_pixels = cv2.bitwise_and(result, circle_outer_mask)
inner_sobel_x = cv2.Sobel(inner_pixels, cv2.CV_64F, 255, 255)
inner_sobel_y = cv2.Sobel(inner_pixels, cv2.CV_64F, 255, 255)
inner_gradient_magnitude = cv2.magnitude(inner_sobel_x, inner_sobel_y)
gradient_diff = np.sum(inner_gradient_magnitude)
return gradient_diff
for angle in range(0, 360, 5):
# 将圆叠加到
背景图中
image = merge_img(imagearray_que, imagearray_bg, int(radius), angle)
gradient_diff = calculate_gradient_difference(image, int(radius))
if gradient_diff < min_diff:
min_diff = gradient_diff
min_l = angle
pred_str = min_l
通过计算后,再将正确角度覆盖到背景中展现,如下
4、结语
如果使用原图,准确率至少可达到90,所以能拿到原图不要死磕截图了,不过截图的识别整体过程确实更有意思,因为你不知道你的图像算法对于整体体征到底好不好用,有时候可能不是你的算法不要用,是截图截的太屎了,如果本文还有没有介绍到的地方,欢迎提出