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

news2024/11/19 2:23:07

前言

使用摄像头实时识别数字算是目标检测任务,总体上分为两步,第一步是检测到数字卡片的位置,第二步是对检测到的数字卡片进行分类以确定其是哪个数字。在第一步中主要涉及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:
        continue
    if 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自带的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.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 += 1
        print(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:
        continue
    if 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 = 0
    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)
        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 joblib


X_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:
        continue
    if 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.coloradmin.cn/o/813481.html

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

相关文章

求三个球面交点的高效解法

文章目录 一、问题描述二、推导步骤代数法几何法 三、MATLAB代码 一、问题描述 如图,已知三个球面的球心坐标分别为 P 1 ( x 1 , y 1 , z 1 ) , P 2 ( x 2 , y 2 , z 2 ) , P 3 ( x 3 , y 3 , z 3 ) P_1(x_1,y_1,z_1),P_2(x_2,y_2,z_2),P_3(x_3,y_3,z_3) P1​(x1​,…

浏览器访问nginx转发打开oss上的html页面默认是下载,修改为预览

使用阿里云盒OSS上传了html页面,在nginx里配置跳转访问该页面时,在浏览器里直接默认下载了该页面,现在想实现预览功能,只需在nginx里的location里修改消息头的Content-Disposition为inline即可 注意要隐藏头信息proxy_hide_header…

【机器学习】西瓜书习题3.3Python编程实现对数几率回归

参考代码 结合自己的理解,添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt from sklearn import linear_model导入数据,进行数据处理和特征工程 # 1.数据处理&#x…

ChatGPT炒股:爬取股票官方微信公众号的新闻资讯

上市公司的微信公众号,现在已经成为官网之外最重要的官方信息发布渠道。有些不会在股票公告中发布的消息,也会在微信公众号进行发布。所以,跟踪持仓股票的公众号信息,非常重要。 下面,以贝特瑞的官方公众号“贝特瑞新…

合并两个有序数组——力扣88

文章目录 题目描述法一 双指针法二 逆向双指针 题目描述 法一 双指针 使用双指针方法&#xff0c;将两个数组看作队列&#xff0c;每次从两个数组头部取出比较小的数字放到结果中。 void merge(vector<int>&nums1, int m,vector<int>&nums2, int n){int p1…

无涯教程-jQuery - Select menu组件函数

小部件选择菜单功能可与JqueryUI中的小部件一起使用&#xff0c;它提供了可替换样式的选择元素。一个简单的选择菜单如下所示。 Select menu - 语法 $( "#menu" ).selectmenu(); Select menu - 示例 以下是显示选择菜单用法的简单示例- <!doctype html> &…

关于Java的多线程实现

多线程介绍 进程&#xff1a;进程指正在运行的程序。确切的来说&#xff0c;当一个程序进入内存运行&#xff0c;即变成一个进程&#xff0c;进程是处于运行过程中的程序&#xff0c;并且具有一定独立功能。 线程&#xff1a;线程是进程中的一个执行单元&#xff0c;负责当前进…

大数据课程D11——hadoop的Ganglia

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念&#xff1b; ⚪ 掌握Ganglia的安装操作&#xff1b; ⚪ 掌握Ganglia的监控Flume操作&#xff1b; 一、概述 1. Ganglia是UC Berkeley发起的一个开源…

JVM基础篇-程序计数器

程序计数器 定义 Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用:记住下一条jvm指令的执行地址特点 是线程私有的:每个线程都有自己的程序计数器不会存在内存溢出(规定) 作用 左侧:jvm指令 右侧:java代码 0: getstatic #20 // PrintSt…

三维点云与深度图相互转换

点云转深度图 一、效果二、实现原理与代码2.1 获取点云边界2.2 确定图像大小2.3 稀疏点图像填充2.4 完整代码三、由深度图转换回点云信息丢失问题3.1 深度图转点云3.2 深度图转点云代码3.3 多视角的深度图融合一、效果 对点云进行转换,z向表示深度,转换效果如下 二、实现…

Docker安装配置启动Oracle11g容器解决ORA-12541:TNS: 无监听程序连接第三方客户端

Windows下安装可参考我这篇&#xff1a;win11&win7下安装oracle11g数据库全过程 一、下载与启动 前提&#xff1a;需要安装配置好docker(设置镜像源、配置阿里云加速)等&#xff0c;可参考我这篇 基于CentOS7安装配置docker与docker-compose 。 Docker容器相关操作可参考…

【自动化运维】playbook剧本

目录 一、Ansible 的脚本 playbook 剧本1.1playbooks的组成 二、剧本编写实验2.1定义、引用变量2.2使用远程主机sudo切换用户2.3whenn条件判断2.4迭代 三、Templates 模板四、Tags模板 一、Ansible 的脚本 playbook 剧本 1.1playbooks的组成 &#xff08;1&#xff09;Tasks&…

Diffusion扩散模型学习2——Stable Diffusion结构解析-以文本生成图像(文生图,txt2img)为例

Diffusion扩散模型学习2——Stable Diffusion结构解析-以文本生成图像&#xff08;文生图&#xff0c;txt2img&#xff09;为例 学习前言源码下载地址网络构建一、什么是Stable Diffusion&#xff08;SD&#xff09;二、Stable Diffusion的组成三、生成流程1、文本编码2、采样流…

Python自动化测试----生成测试报告

如何才能让用例自动运行完之后&#xff0c;生成一张直观可看易懂的测试报告呢&#xff1f; 对于自动化测试有兴趣的朋友可以观看这个视频&#xff1a; 【整整200集】超超超详细的Python接口自动化测试进阶教程&#xff0c;真实模拟企业项目实战&#xff01;&#xff01; 小编使…

【Ap模块EM】09- 什么是Manifest?

先直观感受一下下面的这个服务定义: -fidl文字描述版本: arxml版本: 了解Manifest之前,我们了解一下AutoSAR是怎么开发的? AUTOSAR方法论 AUTOSAR 提供了一种开发方法论,该方法描述了从抽象系统定义一直到最终 EUC 可执行文件的流程步骤,并包含设计步骤和工作产品列…

读取application-dev.properties的中文乱码【bug】

读取application-dev.properties的中文编码【bug】 2023-7-30 22:37:46 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN日星月云 博客主页是https://blog.csdn.net/qq_51625007 禁止其他平台发布时删除以上此话 bug 读取application-dev.propert…

详解Unity中的Nav Mesh|导航寻路系统 (一)

前言 在类RTS、RPG游戏中&#xff0c;都会提供自动寻路功能&#xff0c;当玩家下达指令后&#xff0c;NPC就会自动计算到达目标的路径&#xff0c;实现这种功能的方式有很多种&#xff0c;其中Unity本身也自带了一种导航寻路系统&#xff0c;该系统会将游戏场景中复杂的对象烘…

STM32入门学习之外部中断

1.STM32的IO口可以作为外部中断输入口。本文通过按键按下作为外部中断的输入&#xff0c;点亮LED灯。在STM32的19个外部中断中&#xff0c;0-15为外部IO口的中断输入口。STM32的引脚分别对应着0-15的外部中断线。比如&#xff0c;外部中断线0对应着GPIOA.0-GPIOG.0&#xff0c;…

SpaceX 摊上事?未获环境许可,星舰发射系统涉嫌违规排放污染物

马斯克“寄予厚望”的星舰SpaceX最近可能摊上事了&#xff0c;疑似未申请环境许可&#xff0c;星舰发射系统涉嫌违规排放污染物。 据报导&#xff0c;SpaceX可能在火焰偏转器系统方面存在环境许可问题&#xff0c;其在火箭发射时&#xff0c;可能涉及违反相关环境法规。 最近&a…

深入学习 Redis - 基于 Spring Data Redis 操作 Redis

目录 一、前置工作 1.1、引入 Spring Data Redis 依赖 1.2、编写配置文件 二、Spring Data Redis 2.1、前置知识 2.2、演示 Demo 一、前置工作 1.1、引入 Spring Data Redis 依赖 1.2、编写配置文件 spring:redis:host: 127.0.0.1port: 8888二、Spring Data Redis 2.1、…