当前位置: 首页 > news >正文

QT:用opencv的KNN识别图片中的LED数字(一)

前言

        一款功能测试的软件demo,使用了QT作为界面,主要使用了opencv的KNN识别,使用gstreamer作为管道,用来打开图片。后期会写一篇打开摄像头实时识别的文章。

(正在写,未完成,稍候)

效果一预览:

cb6d9c0afc4645ea9f322433c4b0a0f0.png

效果二预览:

dacbd92d102e4278b9777cee374fc5d3.png

效果三预览:

正在写。。。

设计思路

1. 软件UI设计

d209be7b6bb3421599b0fe81d6771231.png

2. 底层思路

    如下图,使用2个gstreamer管道,中间是opencv,最终显示在QT界面上。

    之所以看起来搞这么复杂,是为了以后方便扩展,否则其实不使用gstreamer,光使用opencv即可完成所有功能。以下是一些思路:

 1. opencv主要是图像处理和识别框架,而gstreamer是音视频框架,我们使用OpenCV作为图像处理和识别,使用gstreamer作为输入和输出的接口,使用封装好的类显示在QT上,这样以后可以对接更多格式的媒体数据,以及更简单的处理步骤。

 2. 框架设计了解耦,这样以后,不光可以识别LED,只要把训练资料替换,一样可以识别其他

 3. OpenCV因为功能强大,本次只作为 KNN训练和图像识别使用,以后可以根据需要添加其他

 4. 其中的knn_modle为解耦设计,可以作为其他项目使用,不必使用gstreamer和QT。

8519ce4dd6df42919592e947e2b0a4b2.png

3. opencv识别LED数字的原理

3.1 识别算法选择

        首先,请自行搜索:机器学习 和 深度学习的区别,我也是小白,但是我知道深度学习更加复杂,虽然它的准确度更高一些,但是我时间有限,就先试用机器学习来识别,挑了一个最简单的算法:KNN算法。

        KNN算法识别,需要先训练,然后再识别,在应用中,使用opencv 的 KNearest 即可创建KNN识别模型,只需要训练和识别即可。这个方向,我有demo,还有从别人那里捞过来的图片训练资料,小白也能直接上手使用。

        首先我们先来对一个简单的图片进行识别,以下是识别效果:

87337fb03f6044b4b8089c7639284c68.png

        我之前写过一篇文章,里面有demo 和 代码:

        使用gstreamer和opencv实时识别LED数码管数字的测试demo(QT)-CSDN博客

3.2 识别思路

        以下是我自己总结的思路:

f87abe166ec247afac63145a998964bb.png

       看完上一篇文章,已经可以实现简单图片LED数字的识别,那么可以总结出上述思路。

       于是在原有图片的基础上,修改图片,然后训练和识别,即可完成第一和第7步,而第8步比较简单,目前无需考虑。当然,自己也是需要动手改一下的:在Linux上,我使用的是GIMP画的:

d526799ddff04abb9fb64363804d965f.png

3c97559912ef407f9620d6e0530f1277.png

       然后,既然已经有了训练资料,而且对于比较简单的图片识别效果还行,那么就可以上手实现复杂的图片了。

        但是将复制图片导入,直接使用之前的代码会发现,根本无法识别出来,甚至连框都画不出来,为什么呢,原来,虽然KNN可以根据近似原理识别出结果,但是如果喂给KNN识别的图片本身就不对,那么自然KNN也没有办法识别,所以使用opencv对图片进行处理,也就是第三、四、五、六步,都是非常关键的,这里就需要去简单学习一下opencv了。

        考虑到使用的是QT,而且以后要进行实时识别,所以选择使用C++完成,而不是python完成

4.处理图片---第一次

        首先来看一下,我需要分析的图片:

e4bf66054eae42ad93c594ff463bc6e7.png

4.1 图片初步处理

        如此多的颜色和真实脑壳大,最开始我思考了转灰度图,但是发现根本无法区分颜色,因为红色、黄色、绿灯和散光的颜色是差不多的,于是放弃转灰度图:

e568a991ca254ace9f68abdefcb1bad0.png

        然后我开始使用RGB筛选,但是发现效果依然是不好。

81a71610ecfe4317b8cc88f8d48e7cad.png

        后来我思考到了使用HSV颜色空间的方法,参考文章:

三分钟带你快速学习RGB、HSV和HSL颜色空间 - 知乎 (zhihu.com)

ad54d259b0894c989dbedcf369c76e5c.png

        使用HSV进行区分的效果,可以看到,效果好了很多:

59ce2c5585e64e109b365f2cf745cb57.png

        但是此处,使用轮廓识别和KNN,依然是无法识别。

        而且,这里的HSV的上下限,一共6个数字,一个个实验,非常头疼,于是我自己写了一个demo:

4.2 测试demo进行HSV测试:

main.cpp源码:

#include <opencv2/opencv.hpp>cv::Mat mt; // 原图像
cv::Mat image_bin; // 二值化后的图像// 回调函数,用于更新图像
void updateImage(int, void*) {cv::Mat hsvImage;cv::cvtColor(mt, hsvImage, cv::COLOR_BGR2HSV);// 获取滑动条的参数值int hMin = cv::getTrackbarPos("Hue Min", "Trackbars");int sMin = cv::getTrackbarPos("Saturation Min", "Trackbars");int vMin = cv::getTrackbarPos("Value Min", "Trackbars");int hMax = cv::getTrackbarPos("Hue Max", "Trackbars");int sMax = cv::getTrackbarPos("Saturation Max", "Trackbars");int vMax = cv::getTrackbarPos("Value Max", "Trackbars");// 根据滑动条的参数值进行颜色范围选择cv::Scalar lower(hMin, sMin, vMin);cv::Scalar upper(hMax, sMax, vMax);cv::inRange(hsvImage, lower, upper, image_bin);// 显示二值化图像cv::resize(image_bin,image_bin,cv::Size(640,480));cv::imshow("Red Area", image_bin);
}int main() {mt = cv::imread("/home/enpht/Pictures/ocr_jpg/test4.jpg");cv::Mat orin;cv::resize(mt, orin, cv::Size(640, 480));cv::imshow("orin",orin);if (mt.empty()) {std::cerr << "Error loading image!" << std::endl;return 1;}cv::namedWindow("Trackbars"); // 创建窗口用于显示滑动条int hMin = 105;int sMin = 38;int vMin = 176;int hMax = 255;int sMax = 230;int vMax = 255;cv::createTrackbar("Hue Min", "Trackbars", &hMin, 255, updateImage);cv::createTrackbar("Saturation Min", "Trackbars", &sMin, 255, updateImage);cv::createTrackbar("Value Min", "Trackbars", &vMin, 255, updateImage);cv::createTrackbar("Hue Max", "Trackbars", &hMax, 255, updateImage);cv::createTrackbar("Saturation Max", "Trackbars", &sMax, 255, updateImage);cv::createTrackbar("Value Max", "Trackbars", &vMax, 255, updateImage);// 初始时更新一次图像updateImage(0, 0);cv::waitKey(0);return 0;
}

        效果:加入6个滑动槽,进行HSV上下限的改变,并且实时查看效果,这里我换了一副图,忘了换回来了,不过效果类似的:

696847f015f84dac88d26e21f9ed5353.gif

        从这里,我们可以自行实验出HSV的上下限的6个数值。

4.3 搭建QT项目

        如下所示,我搭建了一个测试项目:

e5766ae440854ec7bd35ece0769259fc.png

knnModel.h 

#ifndef KNNMODEL_H
#define KNNMODEL_H// 此处部分代码参考其他文章// knn:
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include 

相关文章:

QT:用opencv的KNN识别图片中的LED数字(一)

前言 一款功能测试的软件demo,使用了QT作为界面,主要使用了opencv的KNN识别,使用gstreamer作为管道,用来打开图片。后期会写一篇打开摄像头实时识别的文章。 (正在写,未完成,稍候) 效果一预览: 效果二预览: 效果三预览: 正在写。。。 设计思路 1. 软件UI设计 2. …...

leetcode72. 编辑距离

leetcode72. 编辑距离 题目 思路 dp[i][j] 代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数&#xff0c;所以&#xff0c; 当 word1[i] word2[j]&#xff0c;dp[i][j] dp[i-1][j-1]&#xff1b; 当 word1[i] ! word2[j]&#xff0c;dp[i][j] 1 min(dp[i-1][j-1]…...

R语言的数据类型与数据结构:向量、列表、矩阵、数据框及操作方法

R语言的数据类型与数据结构&#xff1a;向量、列表、矩阵、数据框及操作方法 介绍向量列表矩阵数据框 介绍 R语言拥有丰富的数据类型和数据结构&#xff0c;以满足各类数据处理和分析的需求。本文将分享R语言中的数据类型&#xff0c;包括向量、列表、矩阵、数据框等&#xff…...

第十六章 构建和配置 Nginx 以与 Web 网关配合使用 (Windows) - 将 NSD 与 Nginx 结合使用

文章目录 第十六章 构建和配置 Nginx 以与 Web 网关配合使用 (Windows) - 将 NSD 与 Nginx 结合使用将 NSD 与 Nginx 结合使用CSPNSD_pass hostname:portNum;CSP on; and CSP off;CSPFileTypes filetype1[ filetype2...];CSPNSD_response_headers_maxsize size;CSPNSD_connect_…...

数据中台:数字中国战略关键技术设施

文章目录 每日一句正能量前言为何要建设数据中台数据中台建设痛点数据中台学习资料聚焦前沿&#xff0c;方法论体系更新与时俱进&#xff0c;紧跟时代热点深入6大行业&#xff0c;提炼实践精华大咖推荐&#xff0c;数字化转型必备案头书购买链接赠书活动 每日一句正能量 人生之…...

mac上更改vscode快捷键

以移动当前行代码为例 mac上的vscode&#xff0c;默认移动当前行代码的快捷键是⌥↑即option↑按键 现在我想改成command↑ 步骤如下 1.打开vscode-code-首选项-键盘快捷键 2.打开快捷键列表 3.输入move line&#xff0c;找到要改动的这个快捷键 当前行-右键-更改键绑定&…...

Day18:信息打点-小程序应用解包反编译动态调试抓包静态分析源码架构

目录 小程序获取-各大平台&关键字搜索 小程序体验-凡科建站&模版测试上线 小程序抓包-Proxifier&BurpSuite联动 小程序逆向-解包反编译&动态调试&架构 思维导图 章节知识点 Web&#xff1a;语言/CMS/中间件/数据库/系统/WAF等 系统&#xff1a;操作系…...

真实案例分享:MOS管电源开关电路,遇到上电冲击电流超标

做硬件&#xff0c;堆经验。 分享一个案例&#xff1a;MOS管电源开关电路&#xff0c;遇到上电冲击电流超标&#xff0c;怎么解决的呢&#xff1f; 下面是正文部分。 —— 正文 —— 最近有一颗用了挺久的MOSFET发了停产通知&#xff0c;供应链部门找到我们研发部门&#xff0c…...

LCR 164. 破解闯关密码

解题思路&#xff1a; 贪心 class Solution {public String crackPassword(int[] password) {String[] strs new String[password.length];for(int i 0; i < password.length; i)strs[i] String.valueOf(password[i]);Arrays.sort(strs, (x, y) -> (x y).compareTo(…...

【鸿蒙 HarmonyOS 4.0】常用组件:List/Grid/Tabs

一、背景 列表页面&#xff1a;List组件和Grid组件&#xff1b; 页签切换&#xff1a;Tabs组件&#xff1b; 二、列表页面 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“…...

打造经典游戏:HTML5与CSS3实现俄罗斯方块

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

什么是系统工程(字幕)48

0 00:00:00,760 --> 00:00:03,550 那这里我们要说一下 1 00:00:04,050 --> 00:00:06,163 你看&#xff0c;刚才我们这里 2 00:00:06,163 --> 00:00:06,740 3 00:00:07,440 --> 00:00:13,460 这个我们把它说成&#xff0c;打开这个&#xff0c;关闭这个 4 00:00:…...

Jenkins发送邮件、定时执行、持续部署

集成Allure报告只需要配置构建后操作即可。但如果是web自动化&#xff0c;或是用HTMLTestRunner生成报告&#xff0c;构建后操作要选择Publish HTML reports&#xff0c;而构建中还要添加Execute system Groovy script插件&#xff0c;内容&#xff1a; System.setProperty(&q…...

Mysql的Cardinality值

什么是Cardinality值&#xff1f; Cardinality值是Mysql做索引优化时一个非常关键的值&#xff0c;优化器会根据这个值来判断是否使用这个索引&#xff0c;它表示索引中唯一值的数目估计值&#xff0c;该值应该尽可能接近1&#xff0c;如果非常小&#xff0c;则用户需要考虑是否…...

数据结构 - 栈和队列

本篇博客将介绍栈和队列的定义以及实现。 1.栈的定义 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除数据&#xff0c;插入数据的一端叫做栈顶&#xff0c;另一端叫做栈底。栈中的数据遵守后进先出的原则 LIFO (Last In First Out)。 插入数据的操作称为压…...

C++:模版进阶 | Priority_queue的模拟实现

创作不易&#xff0c;感谢三连支持 一、非类型模版参数 模板参数分类为类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&…...

【刷题记录】详谈设计循环队列

下题目为个人的刷题记录&#xff0c;在本节博客中我将详细谈论设计循环队列的思路&#xff0c;并给出代码&#xff0c;有需要借鉴即可。 题目&#xff1a;LINK 循环队列是线性表吗&#xff1f;或者说循环队列是线性结构吗&#xff1f; 对于这个问题&#xff0c;我们来看一下线…...

人工智能|机器学习——k-近邻算法(KNN分类算法)

1.简介 k-最近邻算法&#xff0c;也称为 kNN 或 k-NN&#xff0c;是一种非参数、有监督的学习分类器&#xff0c;它使用邻近度对单个数据点的分组进行分类或预测。虽然它可以用于回归问题&#xff0c;但它通常用作分类算法&#xff0c;假设可以在彼此附近找到相似点。 对于分类…...

乐得瑞 1C to 2C快充线:引领充电数据线新潮流,高效快充解决接口难题

随着科技的不断进步&#xff0c;数据线的接口种类也日渐繁多&#xff0c;但在早些时候&#xff0c;三合一和二合一的数据线因其独特的设计而备受欢迎。这类数据线通常采用USB-A口作为输入端&#xff0c;并集成了Micro USB、Lightning以及USB-C三种接口&#xff0c;满足了当时市…...

O2OA(翱途)开发平台如何在流程表单中使用基于Vue的ElementUI组件?

本文主要介绍如何在O2OA中进行审批流程表单或者工作流表单设计&#xff0c;O2OA主要采用拖拽可视化开发的方式完成流程表单的设计和配置&#xff0c;不需要过多的代码编写&#xff0c;业务人员可以直接进行修改操作。 在流程表单设计界面&#xff0c;可以在左边的工具栏找到Ele…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...