赞
踩
@TOC
要达到的效果是使用算法预测中间圆形的角度,返回给服务器,实现自动完成验证码的问题。要实现的内容如下图所示。
但是实际应用的过程中,笔者发现这种算法逻辑执行效果较差。
因为RotNet要完成的是独立的圆预测角度,实现的是如下图所示的圆的角度预测,单独的圆就已经是独立出来的一张图像,因此直接输入进网络,预测效果会很好
但是我们要实现的相当于中间圆和外部图形的拼图操作,而不仅仅是简单的预测角度,所以直接把中间的圆拿出来进行角度预测,显然脱离了背景,而且有些题把中间独立的圆抠出来之后,很难对其角度进行定义,所以效果很差
网络上没有此类开源的数据集,因此笔者自行进行了制备,具体分为以下两种:
效果如下:
3eb50dabc910b6
import math import numpy as np import cv2 from ultralytics import YOLO import os yolo_model = YOLO(r"D:\kb\rotate-captcha-crack-master_my\yolo.pt") def code_dect(folder_path, output_path): files = [] current_index = 0 while True: if not files: print("文件夹中没有图像文件。") break img_path = os.path.join(folder_path, files[current_index]) img = cv2.imread(img_path) imgDoub = img # 检测出的box center_box = [] results = yolo_model.predict(img, stream=True) boxAll = [] for r in results: boxes = r.boxes for box in boxes: x1, y1, x2, y2 = box.xyxy[0] # 获取边界框的坐标 x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) w, h = x2 - x1, y2 - y1 bbox = (x1, y1, w, h) boxAll.append(bbox) # 计算图像中心坐标 width, height = img.shape[0], img.shape[1] image_center_x = width / 2 image_center_y = height / 2 # 找出距离图像中心最近的矩形框 min_distance = float('inf') for rectangle in boxAll: center_x, center_y = calculate_center(rectangle) distance = math.sqrt((center_x - image_center_x) ** 2 + (center_y - image_center_y) ** 2) if distance < min_distance: min_distance = distance center_box = rectangle if center_box == []: print(f"没有检测到目标:{img_path}") else: # 创建与图像相同大小的黑色背景 mask = np.zeros_like(imgDoub[:, :, 0]) # 定义圆的外接矩形坐标 x, y, w, h = center_box # 在掩码上绘制白色的圆形 cv2.circle(mask, (x + w // 2, y + h // 2), min(w, h) // 2, (255, 255, 255), -1) # 将掩码应用到白色背景上,保留圆形区域 onlyCircle = cv2.bitwise_and(imgDoub, imgDoub, mask=mask) mask2 = np.zeros_like(img, dtype=np.uint8) # 在掩码上绘制圆形区域 cv2.circle(mask2, (x + w // 2, y + h // 2), min(w, h) // 2, (255, 255, 255), -1) rotate = True reverse = False angle = 0 while rotate: # 获取图像的中心点坐标 height, width = onlyCircle.shape[:2] center = (width // 2, height // 2) # 定义旋转矩阵 rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # 进行旋转变换 rotated_image = cv2.warpAffine(onlyCircle, rotation_matrix, (width, height)) # 将圆形区域置为0 imgDoub[mask2 != 0] = 0 result = rotated_image + imgDoub cv2.imshow("result", result) # 添加按键监听 key = cv2.waitKey(1) # z、c分别是切换上一张或者下一张图 if key == ord('z'): current_index = (current_index - 1) % len(files) break # 按下 'c' 键逆时针旋转 elif key == ord('c'): current_index = (current_index + 1) % len(files) break # 按下 's' 键保存图像 elif key == ord('s'): output_img_path = os.path.join(output_path, files[current_index]) cv2.imwrite(output_img_path, result) print(f"图像已保存到:{output_img_path}") if key == ord('a'): angle += 1 # 按下 'd' 键逆时针旋转 elif key == ord('d'): angle -= 1 elif key == ord('q'): angle += 10 elif key == ord('e'): angle -= 10 if __name__ == '__main__': folder_path = input("请输入文件夹路径:") output_path = input("请输入输出路径:") code_dect(folder_path, output_path)
使用RotNet作为本算法的预测核心预测算法,把我们上文中生成的回正数据首先利用编写的脚本给每张图像生成360张不同角度的图像,文件名的后缀代表这张图象真实的偏转角度。
把生成的所有图像输入进改进的RotNet进行训练,由于这种类型的样本学习很容易出现过拟合的现象,因此笔者在网络中加了几个DropOut操作。
我们并没有简单把单张图像输入进算法来进行角度预测,这样360个类别误差太大效果会比较差,在应用的时候我们也是先把中间的圆形图像抠出来,然后对其使用算法旋转360度,把360张图像都进行角度预测,最后取出0到3度和357到359度的图像返回它的序列值,即真实的角度值。如果没有这些范围之内的图像,那就返回-1,切下一张图像,防止错误次数太多。代码如下所示:
import math import numpy as np import torch from PIL import Image from rotate_captcha_crack.common import device from rotate_captcha_crack.model import RotNetR from rotate_captcha_crack.utils import process_captcha import cv2 from ultralytics import YOLO yolo_model = YOLO(r"D:\chenjie\rotate-captcha-crack-master_my\yolo.pt") def calculate_center(rectangle): x, y, w, h = rectangle center_x = x + w / 2 center_y = y + h / 2 return center_x, center_y model = RotNetR(train=False, cls_num=360) model_path = r"D:\chenjie\rotate-captcha-crack-master_my\models\RotNetR\240316_17_14_23_006\best.pth" model.load_state_dict(torch.load(str(model_path))) model = model.to(device=device) model.eval() def predictAngle(img): img = Image.fromarray(img) img_ts = process_captcha(img) img_ts = img_ts.to(device=device) predict = model.predict(img_ts) return predict def code_dect(img): imgDoub = img # 检测出的box center_box = [] results = yolo_model.predict(img, stream=True) boxAll = [] for r in results: boxes = r.boxes for box in boxes: x1, y1, x2, y2 = box.xyxy[0] # Gives coordinates to draw bounding box x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) w, h = x2 - x1, y2 - y1 bbox = (x1, y1, w, h) boxAll.append(bbox) # 计算图像中心坐标 width, height = img.shape[0], img.shape[1] image_center_x = width / 2 image_center_y = height / 2 # 找出距离图像中心最近的矩形框 min_distance = float('inf') for rectangle in boxAll: center_x, center_y = calculate_center(rectangle) distance = math.sqrt((center_x - image_center_x) ** 2 + (center_y - image_center_y) ** 2) if distance < min_distance: min_distance = distance center_box = rectangle if center_box==[]: print("kong") else: # 把圆区域搞出来 # 创建与图像相同大小的黑色背景 mask = np.zeros_like(imgDoub[:, :, 0]) # 定义圆的外接矩形坐标 x, y, w, h = center_box # 在掩码上绘制白色的圆形 cv2.circle(mask, (x + w // 2, y + h // 2), min(w, h) // 2, (255, 255, 255), -1) # 将掩码应用到白色背景上,保留圆形区域 onlyCircle = cv2.bitwise_and(imgDoub, imgDoub, mask=mask) # 显示结果图像 # cv2.imshow('Only Circle', onlyCircle) # cv2.imshow('imgDoub', imgDoub) # cv2.waitKey(0) mask2 = np.zeros_like(img, dtype=np.uint8) # 在掩码上绘制圆形区域 cv2.circle(mask2, (x + w // 2, y + h // 2), min(w, h) // 2, (255, 255, 255), -1) angles = [] for angle in range(0, 360): # 获取图像的中心点坐标 height, width = onlyCircle.shape[:2] center = (width // 2, height // 2) # 定义旋转矩阵 rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # 进行旋转变换 rotated_image = cv2.warpAffine(onlyCircle, rotation_matrix, (width, height)) # 将圆形区域置为0 imgDoub[mask2 != 0] = 0 result = rotated_image+imgDoub predict = predictAngle(result) # cv2.imshow("sdf",result) # print(predict) # cv2.waitKey(10) angles.append(predict) minAngle = min(angles) maxAngle = max(angles) minAngleIdx = angles.index(min(angles)) maxAngleIdx = angles.index(max(angles)) finalAngleIdx = -1 if maxAngle>356: finalAngleIdx = maxAngleIdx elif minAngle<4: finalAngleIdx = minAngleIdx print(finalAngleIdx) return finalAngleIdx if __name__ == '__main__': # 测试整体 img = cv2.imread("D:\chenjie\\rotate-captcha-crack-master_my\images\e42c0939dc3bde88657a88ac07d59d6.png") code_dect(img)
最后可以达到80-90%的通过率,效果已经很不错了
演示效果如下:
ab7c1b94c3bc27b8
q:1831255794(有偿)制备数据集和写算法耗费了大量时间精力,因此收取点小费希望理解!!!
可接项目,大作业,毕设等
价格略贵,技术够硬,认真负责,保证质量
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。