【项目】基于YOLOv8和RotNet实现圆形滑块验证码(拼图)自动识别(通过识别中间圆形的角度实现)

@TOC

一、引言

1.1 实现目标

要达到的效果是使用算法预测中间圆形的角度,返回给服务器,实现自动完成验证码的问题。要实现的内容如下图所示。
在这里插入图片描述

在这里插入图片描述

1.2 实现思路

思路1(效果较差):以RotNet要实现的验证码识别为灵感,先利用YOLO算法检测出中间圆,再把圆形图像输入给RotNet,让其预测角度,进而返回给服务器。

但是实际应用的过程中,笔者发现这种算法逻辑执行效果较差。
因为RotNet要完成的是独立的圆预测角度,实现的是如下图所示的圆的角度预测,单独的圆就已经是独立出来的一张图像,因此直接输入进网络,预测效果会很好
在这里插入图片描述
但是我们要实现的相当于中间圆和外部图形的拼图操作,而不仅仅是简单的预测角度,所以直接把中间的圆拿出来进行角度预测,显然脱离了背景,而且有些题把中间独立的圆抠出来之后,很难对其角度进行定义,所以效果很差
在这里插入图片描述

思路2:有了思路1的教训,我们要做的第一步就是把外部的背景图像引入进来进行训练

二、数据集制备

网络上没有此类开源的数据集,因此笔者自行进行了制备,具体分为以下两种:

  1. 一种是以下这种圆完全归位的一整张图,都是用美工P图的方法进行制备的在这里插入图片描述
  2. 第二种是直接截取的这种没有P图过的没有修正过的图像
    在这里插入图片描述
    此类数据集制备完成之后再用笔者编写的脚本使其归位,部分代码如下
    大致思路为:
  • 先使用YOLO算法检测出图像中的圆
  • 再利用算法使用a、d两个按键进行角度偏转,使用z、c两个按键进行切图
  • 观察到图像回正之后,按s键保存到指定文件夹下

效果如下:

3eb50dabc910b6

import math
import numpy as np
import cv2
from ultralytics import YOLO
import osyolo_model = YOLO(r"D:\kb\rotate-captcha-crack-master_my\yolo.pt")def code_dect(folder_path, output_path):files = []current_index = 0while True:if not files:print("文件夹中没有图像文件。")breakimg_path = os.path.join(folder_path, files[current_index])img = cv2.imread(img_path)imgDoub = img# 检测出的boxcenter_box = []results = yolo_model.predict(img, stream=True)boxAll = []for r in results:boxes = r.boxesfor 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 - y1bbox = (x1, y1, w, h)boxAll.append(bbox)# 计算图像中心坐标width, height = img.shape[0], img.shape[1]image_center_x = width / 2image_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 = distancecenter_box = rectangleif 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 = Truereverse = Falseangle = 0while 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))# 将圆形区域置为0imgDoub[mask2 != 0] = 0result = rotated_image + imgDoubcv2.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 -= 1elif key == ord('q'):angle += 10elif key == ord('e'):angle -= 10if __name__ == '__main__':folder_path = input("请输入文件夹路径:")output_path = input("请输入输出路径:")code_dect(folder_path, output_path)

三、算法逻辑

1、生成样本

使用RotNet作为本算法的预测核心预测算法,把我们上文中生成的回正数据首先利用编写的脚本给每张图像生成360张不同角度的图像,文件名的后缀代表这张图象真实的偏转角度。
,

2、训练算法

把生成的所有图像输入进改进的RotNet进行训练,由于这种类型的样本学习很容易出现过拟合的现象,因此笔者在网络中加了几个DropOut操作。

3、算法逻辑

我们并没有简单把单张图像输入进算法来进行角度预测,这样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 YOLOyolo_model = YOLO(r"D:\chenjie\rotate-captcha-crack-master_my\yolo.pt")def calculate_center(rectangle):x, y, w, h = rectanglecenter_x = x + w / 2center_y = y + h / 2return center_x, center_ymodel = 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 predictdef code_dect(img):imgDoub = img# 检测出的boxcenter_box = []results = yolo_model.predict(img, stream=True)boxAll = []for r in results:boxes = r.boxesfor box in boxes:x1, y1, x2, y2 = box.xyxy[0]  # Gives coordinates to draw bounding boxx1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)w, h = x2 - x1, y2 - y1bbox = (x1, y1, w, h)boxAll.append(bbox)# 计算图像中心坐标width, height = img.shape[0], img.shape[1]image_center_x = width / 2image_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 = distancecenter_box = rectangleif 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))# 将圆形区域置为0imgDoub[mask2 != 0] = 0result = rotated_image+imgDoubpredict = 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 = -1if maxAngle>356:finalAngleIdx = maxAngleIdxelif minAngle<4:finalAngleIdx = minAngleIdxprint(finalAngleIdx)return finalAngleIdxif __name__ == '__main__':# 测试整体img = cv2.imread("D:\chenjie\\rotate-captcha-crack-master_my\images\e42c0939dc3bde88657a88ac07d59d6.png")code_dect(img)

最后可以达到80-90%的通过率,效果已经很不错了
演示效果如下:

ab7c1b94c3bc27b8

三、代码、数据集获取

q:1831255794(有偿)制备数据集和写算法耗费了大量时间精力,因此收取点小费希望理解!!!
可接项目,大作业,毕设等 
价格略贵,技术够硬,认真负责,保证质量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/557152.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day-25 无重复字符的最长子串

思路&#xff1a;动态规划的思想&#xff0c;遍历字符串&#xff0c;每遇到一个新的字符&#xff0c;将其存入HashMap中&#xff0c;并给其一个唯一值value(value递增)&#xff0c;当前字符若与HashMap中的字符都不一样&#xff0c;则存入HashMap中&#xff0c;若已经存在&…

jscpd检测代码的重复率

官方文档&#xff1a;jscpd jscpd 是一个开源的代码重复检测工具&#xff0c;它用于查找代码中的重复部分并生成相应的报告 1、比较两个目录之间的差异 yarn jscpd --skipLocal sre/test1/** sre/test2 --reporters html生成报告文档在 ./report/html 下面&#xff0c;可以打开…

搭建Flutter开发环境、从零基础到精通(文末送书【北大出版社】)

目录 搭建开发环境 1. 下载Flutter SDK 2. 设置镜像地址及环境变量 3. 安装与设置Android Studio 4. 安装Visual Studio Code与Flutter开发插件 5. IDE的使用和配置 6. 安装Xcode 7. 检查Flutter开发环境 好书推荐 内容简介 作者简介 搭建开发环境 Flutter可以跨平…

有关Theano和PyTensor库

根据Github里面的介绍&#xff0c;PyTensor是源于Theano&#xff0c; Theano目前应该已经不再开发了&#xff0c;更新都是很多年前。 因此PyTensor在背景介绍中说 PyTensor is a fork of Aesara, which is a fork of Theano. Theano和PyTensor都是计算相关的库&#xff0c;可以…

数据库关系运算理论:传统的集合运算概念解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

数据结构面试常见问题之- Sort with Swap(0,*)

&#x1f600;前言 在数据结构面试中&#xff0c;排序算法是考察重点之一。传统的排序算法&#xff0c;例如冒泡排序、快速排序等&#xff0c;都依赖于元素之间的比较和交换操作。然而&#xff0c;在某些情况下&#xff0c;我们可能只允许使用特定的交换操作&#xff0c;例如只…

伊理威:开抖店新手能做好吗

在数字化浪潮的推动下&#xff0c;抖音平台不仅成为人们娱乐放松的去处&#xff0c;也孕育了新的商业模式——抖店。对于初入电商领域的新手来说&#xff0c;“开抖店能否成功”成为了一个值得关注的问题。 首要论点在于&#xff0c;抖店为新手提供了一个低门槛的创业环境。相较…

睿尔曼超轻量仿人机械臂之-灵巧手动作编写及程序调用

一、灵巧手动作编写 1.连接设备 2. 运动控制 3. 参数设置 4 动作库使用 本软件可以设置灵巧手内部第 1-第 13 套动作序列数据&#xff0c;每套动作序列最多能有 8 步 分解动作&#xff0c;每一步分解动作的手指角度、运动速度、力度以及等待时间都可以单独设置。 步骤数&…

C语言每日一题07

一、题目 二、解析 逻辑与 &&、逻辑或 || 均有“短路”特性: 逻辑与&&“短路”&#xff1a;当逻辑与&&的左操作数为逻辑 “假“ 时&#xff0c;就足以判断该逻辑运算的结果为假了&#xff0c;故右操作数就不再被执行。 逻辑或||“短路”&#xff1a…

矩形总面积(第十四届蓝桥杯JavaB组省赛真题)

测试用例范围比较大&#xff0c;所以全部用long类型&#xff0c;如果用int类型只能通过60%&#xff0c;建议在内存和运行时间允许的情况下&#xff0c;比赛题都用long。 重点在于计算相交的面积&#xff0c;这里找的两个相交点是左上角&#xff08;m1,n1&#xff09;和右下角&a…

环境变量配置

举一个小例子来演示一下环境变量配置。 在CMD中打开QQ界面&#xff0c;首先需要知道QQ.exe文件的完整路径。一旦有了这个路径&#xff0c;可以按照以下步骤操作&#xff1a; 打开CMD窗口。可以通过按下Windows键R&#xff0c;输入“cmd”并回车来打开它。在CMD窗口中&#xf…

排序算法:归并排序(非递归)

文章目录 一、非递归思路二、代码演示 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦&#xff01; 所属专栏:排序算法 一、非递归思路 步骤如下&…