基于opencv与机器学习的摄像头实时识别数字!附带完整的代码、数据集和训练模型!!

前言

使用摄像头实时识别数字算是目标检测任务,总体上分为两步,第一步是检测到数字卡片的位置,第二步是对检测到的数字卡片进行分类以确定其是哪个数字。在第一步中主要涉及opencv的相关功能,第二步则使用机器学习的方式进行分类。

一、使用opencv捕捉(检测)数字卡片

重点操作是使用轮廓查找函数,获取数字卡片的外轮廓。

在获取轮廓前的图像预处理步骤需要根据自己的实际应用场景进行调整。

import cv2
import imutils# 开启外接摄像头
cap = cv2.VideoCapture(1)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (11, 11))
while True:flag, frame = cap.read()if frame is None:continueif flag is True:frame_copy = frame.copy()frame_copy_2 = frame.copy()frame_copy_3 = frame.copy()# 自动阈值处理frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)frame_ths = cv2.threshold(frame_gray, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)[1]# 闭操作img_closed = cv2.morphologyEx(frame_ths, cv2.MORPH_CLOSE, rectKernel)# canny边缘检测;这里使用的imutils包,也可以使用opencv自带的cannytemp = imutils.auto_canny(img_closed)# 轮廓查找contours, hierarchy = cv2.findContours(temp, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 计算轮廓for index, c in enumerate(contours):area = cv2.contourArea(c)x, y, w, h = cv2.boundingRect(c)# 通过判断轮廓的外接矩形面积确定数字卡片的轮廓,实现过滤功能if area > 10000:# img_out = cv2.drawContours(frame_copy, contours, index, (0, 0, 255), 2)img_out = cv2.rectangle(frame_copy, (x, y), (x + w, y + h), (0, 0, 255), 2)cv2.imshow("ths", frame_ths)cv2.imshow("canny", temp)cv2.imshow("closed", img_closed)cv2.imshow("lun kuo", frame_copy)if cv2.waitKey(1) & 0xFF == 27:cap.release()cv2.destroyAllWindows()break

效果图如下:
在这里插入图片描述

二、制作数据集

在获取数字卡片轮廓的基础上,保存轮廓区域内的图片信息作为基础数据集。为了方便保存,可以使用pynput包完成键盘监控功能,按下一次回车即拍摄一张。

from pynput.keyboard import Key, Listener
import cv2
import imutils# 按键获取数据集
global res_img
counts = 0    # 图片计数
def on_press(key):global counts# 回车触发if key == Key.enter:# 保存图片路径cv2.imwrite(f"1/1_{counts}.png", res_img)counts += 1print(f"Save sucess {counts}")# 开启键盘监听
listener = Listener(on_press=on_press)
listener.start()cap = cv2.VideoCapture(1)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (11, 11))
while True:flag, frame = cap.read()if frame is None:continueif flag is True:frame_copy = frame.copy()frame_copy_2 = frame.copy()# 自动阈值处理frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)frame_ths = cv2.threshold(frame_gray, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)[1]# 闭操作img_closed = cv2.morphologyEx(frame_ths, cv2.MORPH_CLOSE, rectKernel)# canny边缘检测temp = imutils.auto_canny(img_closed)# 轮廓查找contours, hierarchy = cv2.findContours(temp, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 计算轮廓for index, c in enumerate(contours):area = cv2.contourArea(c)x, y, w, h = cv2.boundingRect(c)if area > 10000:img_out = cv2.rectangle(frame_copy, (x, y), (x + w, y + h), (0, 0, 255), 2)# 获取轮廓区域的图像res_img = frame_copy_2[y:y+h, x:x+w]cv2.imshow("lun kuo", frame_copy)if cv2.waitKey(1) & 0xFF == 27:cap.release()cv2.destroyAllWindows()listener.stop()break

每一个数字都要拍摄多张不同角度的图片,这个数据集的拍摄质量将影响最终识别的效果,所以拍摄时需要考虑实际的应用场景。

保存后的图片应该如下图所示。
在这里插入图片描述

拍摄完之后,最好再对数据集进行数据增强,以扩充数据集,提高模型的训练效果。

使用albumentations包进行数据增强,其具体的使用方式可以去Albumentations Documentation查看。

import albumentations as A
import cv2
import os# 设置需要使用的数据增强方式
transform = A.Compose([A.Resize(height=128, width=128),    # 图片缩放A.Rotate(limit=[-70, 70], p=0.5),   # 随机旋转A.RandomBrightnessContrast(p=0.3),  # 随机亮度对比度
])# 遍历每一个数字文件夹
for i in range(1, 9):# 图片计数counts = 0img_list = os.listdir(f"data/{i}")for temp in img_list:image = cv2.imread(f"data/{i}/{temp}")image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)transformed = transform(image=image)['image']# 保存数据增强后的图片cv2.imwrite(f"data/{i}/{i}_{counts}.png", transformed)counts += 1

在数据增强后,每个数字的数据集为220张。

三、使用sklearn建立机器学习模型实现数字分类

常用的机器学习分类模型有KNN和SVM等,可以都试一下,选择效果最好的一个。

首先需要对数据集进行预处理

import cv2
import os
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
import joblibX_img = []    # 用于存放图片信息
y_img = []    # 用于存放标签(label)信息# 遍历加载数据集
for i in range(1, 9):img_list = os.listdir(f"data/{i}")for temp in img_list:image = cv2.imread(f"data/{i}/{temp}")image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)image = cv2.resize(image, (128, 128))X_img.append(image)y_img.append(i)# 转换成二维数组   (1758, 128, 128) ==> (1758, 16384)
X_img = np.array(X_img).reshape(len(X_img), -1)
y_img = np.array(y_img)
print(X_img.shape)
print(y_img.shape)# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_img, y_img, test_size=0.2)# PCA降维 可以降低计算量,提高训练速度,减小模型大小
transfer = PCA(n_components=300)
X_train = transfer.fit_transform(X_train)
X_test = transfer.transform(X_test)
print(X_train.shape)
print(X_test.shape)# 保存PCA降维信息,后续在实时预测时会使用到该信息
joblib.dump(transfer, 'pca_model.joblib')

之后建立SVM分类模型并进行训练和测试。

from sklearn.svm import SVC
from sklearn.metrics import accuracy_score# 建立svm分类器
svm = SVC(kernel='linear')
# 使用训练数据来训练SVM分类器
svm.fit(X_train, y_train)# 使用测试数据进行预测
y_pred = svm.predict(X_test)# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
# 最终准确率为0.9573863636363636
print("Accuracy:", accuracy)
# 保存训练好的模型
joblib.dump(svm, 'svm_model_PCA300.joblib')

最后进行单张图片预测,查看预测效果。

import joblib
import cv2# 加载SVM分类模型
loaded_svm = joblib.load('svm_model_PCA300.joblib')
# 加载PCA降维模型
loaded_pca = joblib.load('pca_model.joblib')
# 读取图片并进行预处理
img = cv2.imread("data/4/4_39.png")
img = cv2.resize(img, (128, 128))
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
temp = img.reshape(1, -1)
# PCA降维,保证格式与训练数据相同
temp = loaded_pca.transform(temp)
print(temp.shape)
y_new_pred = loaded_svm.predict(temp)# 输出预测结果
print("Predictions for new data:", y_new_pred)

四、摄像头实时预测

将前面的部分结合起来就可以实现摄像头实时预测的任务了。

import cv2
import imutils
from pynput.keyboard import Key, Listener
import joblib# 加载SVM和PCA模型
loaded_svm = joblib.load('svm_model_PCA300.joblib')
loaded_pca = joblib.load('pca_model.joblib')# 显示字体配置
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
font_thickness = 2
color = (0, 255, 0)cap = cv2.VideoCapture(1)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (11, 11))
while True:flag, frame = cap.read()if frame is None:continueif flag is True:frame_copy = frame.copy()frame_copy_2 = frame.copy()# 自动阈值处理frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)frame_ths = cv2.threshold(frame_gray, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)[1]# 闭操作img_closed = cv2.morphologyEx(frame_ths, cv2.MORPH_CLOSE, rectKernel)# canny边缘检测temp = imutils.auto_canny(img_closed)# 轮廓查找contours, hierarchy = cv2.findContours(temp, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 计算轮廓for index, c in enumerate(contours):area = cv2.contourArea(c)x, y, w, h = cv2.boundingRect(c)if area > 10000:img_out = cv2.rectangle(frame_copy, (x, y), (x + w, y + h), (0, 0, 255), 2)res_img = frame_copy_2[y:y+h, x:x+w]# 图像预处理img = cv2.resize(res_img, (128, 128))img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)temp = img.reshape(1, -1)# PCA降维temp = loaded_pca.transform(temp)y_new_pred = loaded_svm.predict(temp)cv2.putText(frame_copy, f"Pred: {y_new_pred}", (int(x), int(y)),font, font_scale, color, font_thickness)cv2.imshow("lun kuo", frame_copy)if cv2.waitKey(1) & 0xFF == 27:cap.release()cv2.destroyAllWindows()break

在这里插入图片描述

五、完整的代码、数据集和训练模型下载地址

蓝奏云下载地址

CSDN下载地址

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

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

相关文章

源码学习初章-基础知识储备

文章目录 学前准备源码地址引言extern "C" 宏定义平台宏跨平台宏vstdio平台禁用警告宏 连接、双层宏定义函数宏系统函数宏自定义函数宏多语句执行宏do while0 普通宏定义 C的一些必备函数知识回调函数和函数指针回调函数wireshark-4.0.7源码例子函数指针wireshark4.0…

通讯录的实现(超详细)——C语言(进阶)

目录 一、创建联系人信息(结构体) 二、创建通讯录(结构体) 三、define定义常量 四、打印通讯录菜单 五、枚举菜单选项 六、初始化通讯录 七、实现通讯的的功能 7.1 增加加联系人 7.2 显示所有联系人的信息 ​7.3 单独查…

《MySQL45讲》笔记—索引

索引 索引是为了提高数据查询效率,就像书的目录一样。如下图,索引和数据就是位于存储引擎中: 索引常见模型 哈希表 以键值对存储的数据结构。适用于只有等值查询的场景。 有序数组 在等值查询和范围查询场景中性能都特别优秀。但是有…

开放自动化软件的硬件平台

自动化行业的产品主要以嵌入式系统为主,历来对产品硬件的可靠性和性能都提出很高的要求。最典型的产品要数PLC。PLC 要求满足体积小,实时性,可靠性,可扩展性强,环境要求高等特点。它们通常采用工业级高性能嵌入式SoC 实…

Vue 3:玩一下web前端技术(三)

前言 本章内容为VUE工作过程与相关使用讨论。 上一篇文章地址: Vue 3:玩一下web前端技术(二)_Lion King的博客-CSDN博客 下一篇文章地址: Vue 3:玩一下web前端技术(四)_Lion Ki…

SpringBoot 注解

SpringBoot SpringBoot(SpringBootApplication)问题引入我们的工程在引入spring-boot-starter-web依赖的时候,为什么没有指定版本(版本锁定)spring-boot-starter-web是个啥,为什么引入了它之后,…

【业务功能篇59】Springboot + Spring Security 权限管理 【下篇】

UserDetails接口定义了以下方法: getAuthorities(): 返回用户被授予的权限集合。这个方法返回的是一个集合类型,其中每个元素都是一个GrantedAuthority对象,表示用户被授予的权限。getPassword(): 返回用户的密码。这个方法返回的是一个字符…

springboot编写mp4视频播放接口

简单粗暴方式 直接读取指定文件,用文件流读取视频文件,输出到响应中 GetMapping("/display1/{fileName}")public void displayMp41(HttpServletRequest request, HttpServletResponse response,PathVariable("fileName") String fi…

stm32通过ESP8266接入原子云

1. ESP8266模块需要烧录原子云固件,此原子云固件和正常的ESP8266固件相比添加了ATATKCLDSTA 和 ATATKCLDCLS 这两条指令: 2. 原子云账号注册及设备建立 设备管理-新增设备-ESP8266 新建设备后新建分组,将设备加入到此分组中: 至此…

ICASSP 2023 | Cough Detection Using Millimeter-Wave FMCW Radar

原文链接:https://mp.weixin.qq.com/s?__bizMzg4MjgxMjgyMg&mid2247486540&idx1&sn6ebd9f58e9f08a369904f9c48e12d136&chksmcf51beb5f82637a3c65cf6fa53e8aa136021e35f63a58fdd7154fc486a285ecde8b8521fa499#rd ICASSP 2023 | Cough Detection Usi…

SwipeDelMenuLayout失效:Could not find SwipeDelMenuLayout-V1.3.0.jar

一、问题描述 最近在工作上的项目中接触到SwipeDelMenuLayout这个第三方Android开发库,然后我就根据网上的教程进行配置。这里先说一下我的开发环境:Android Studio版本是android-studio-2020.3.1.24-windows,gradle版本是7.0.2。 首先是在se…

RWEQ模型——土壤风蚀模拟

详情点击链接:基于“RWEQ”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写 前沿 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一,土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的…

【Docker】Docker应用部署之Docker容器安装Tomcat

目录 一、搜索镜像 二、拉取镜像 三、创建容器 四、测试使用 一、搜索镜像 docker search tomcat 二、拉取镜像 docker pull tomcat:版本 三、创建容器 首先在宿主机创建数据卷的目录 mkdir /root/tomcat # 创建目录 cd /root/tomcat # 进入目录 docker run -id -…

前端框架学习-Vue(二)

最近在学习Vue框架,Vue中的内容很多。相当于把之前后端的MVC,V层转移到前端来编写和部署。下面是学习Vue时的大纲。 Vue生命周期是Vue应用的生命周期Vue脚手架,即vue-cli,使用node.js 来创建和启动vue项目Vue组件知识,…

RS485/RS232自由转ETHERNET/IP网关profinet和ethernet区别

你是否曾经遇到过这样的问题:如何将ETHERNET/IP网络和RS485/RS232总线连接起来呢?捷米的JM-EIP-RS485/232通讯网关,自主研发的ETHERNET/IP从站功能,完美解决了这个难题。这款网关不仅可以将ETHERNET/IP网络和RS485/RS232总线连接起…

Zynq-Linux移植学习笔记之62- PL挂载复旦微flash

1、背景介绍 现在为了全国产化需要,之前所有的进口flash全部要换成国产flash 2、复旦微flash型号 其中EFM25QU256和EFM25QL256对标winbond的w25q256 nor flash 3、FPGA设置 复旦微flash只支持单线模式,当使用PL侧的IP核访问时,需要设置模式…

【系统架构】分布式系统架构设计

1 分布式系统是什么 分布式系统是指由多个计算机节点组成的一个系统,这些节点通过网络互相连接,并协同工作完成某个任务。 与单个计算机相比,分布式系统具有更高的可扩展性、可靠性和性能等优势,因此广泛应用于大规模数据处理、高…

IDEA代码自动格式化工具

1.自动import 在IDEA中,打开 IDEA 的设置,找到 Editor -> General -> Auto Import。勾选上 Add unambiguous imports on the flyOptimize imports on the fly (for current project) 2.gitee 提交格式化 设置方法如下: 1.打开设置 2.找到版本…

KMP算法总结

KMP算法总结 BF算法引导BF算法步骤(图片演示)代码演示 KMP算法推next数组代码演示 BF算法引导 BF算法是一个暴力的字符串匹配算法,时间复杂度是o(m*n) 假设主串和子串分别为 我们想要找到子串在主串的位置 BF算法核…

Spring Boot集成Swagger3.0,Knife4j导出文档

文章目录 Spring Boot集成Swagger3.0,Knife4j导出文档效果展示如何使用简要说明添加依赖添加配置类测试接口token配置位置 官网 说明情况 demo Spring Boot集成Swagger3.0,Knife4j导出文档 效果展示 如何使用 简要说明 Knife4j的前身是swagger-bootstrap-ui,前身swagger-boo…