前言
一款功能测试的软件demo,使用了QT作为界面,主要使用了opencv的KNN识别,使用gstreamer作为管道,用来打开图片。后期会写一篇打开摄像头实时识别的文章。
(正在写,未完成,稍候)
效果一预览:
效果二预览:
效果三预览:
正在写。。。
设计思路
1. 软件UI设计
2. 底层思路
如下图,使用2个gstreamer管道,中间是opencv,最终显示在QT界面上。
之所以看起来搞这么复杂,是为了以后方便扩展,否则其实不使用gstreamer,光使用opencv即可完成所有功能。以下是一些思路:
1. opencv主要是图像处理和识别框架,而gstreamer是音视频框架,我们使用OpenCV作为图像处理和识别,使用gstreamer作为输入和输出的接口,使用封装好的类显示在QT上,这样以后可以对接更多格式的媒体数据,以及更简单的处理步骤。
2. 框架设计了解耦,这样以后,不光可以识别LED,只要把训练资料替换,一样可以识别其他
3. OpenCV因为功能强大,本次只作为 KNN训练和图像识别使用,以后可以根据需要添加其他
4. 其中的knn_modle为解耦设计,可以作为其他项目使用,不必使用gstreamer和QT。
3. opencv识别LED数字的原理
3.1 识别算法选择
首先,请自行搜索:机器学习 和 深度学习的区别,我也是小白,但是我知道深度学习更加复杂,虽然它的准确度更高一些,但是我时间有限,就先试用机器学习来识别,挑了一个最简单的算法:KNN算法。
KNN算法识别,需要先训练,然后再识别,在应用中,使用opencv 的 KNearest 即可创建KNN识别模型,只需要训练和识别即可。这个方向,我有demo,还有从别人那里捞过来的图片训练资料,小白也能直接上手使用。
首先我们先来对一个简单的图片进行识别,以下是识别效果:
我之前写过一篇文章,里面有demo 和 代码:
使用gstreamer和opencv实时识别LED数码管数字的测试demo(QT)-CSDN博客
3.2 识别思路
以下是我自己总结的思路:
看完上一篇文章,已经可以实现简单图片LED数字的识别,那么可以总结出上述思路。
于是在原有图片的基础上,修改图片,然后训练和识别,即可完成第一和第7步,而第8步比较简单,目前无需考虑。当然,自己也是需要动手改一下的:在Linux上,我使用的是GIMP画的:
然后,既然已经有了训练资料,而且对于比较简单的图片识别效果还行,那么就可以上手实现复杂的图片了。
但是将复制图片导入,直接使用之前的代码会发现,根本无法识别出来,甚至连框都画不出来,为什么呢,原来,虽然KNN可以根据近似原理识别出结果,但是如果喂给KNN识别的图片本身就不对,那么自然KNN也没有办法识别,所以使用opencv对图片进行处理,也就是第三、四、五、六步,都是非常关键的,这里就需要去简单学习一下opencv了。
考虑到使用的是QT,而且以后要进行实时识别,所以选择使用C++完成,而不是python完成
4.处理图片
首先来看一下,我需要分析的图片:
4.1 图片初步处理
如此多的颜色和真实脑壳大,最开始我思考了转灰度图,但是发现根本无法区分颜色,因为红色、黄色、绿灯和散光的颜色是差不多的,于是放弃转灰度图:
然后我开始使用RGB筛选,但是发现效果依然是不好。
后来我思考到了使用HSV颜色空间的方法,参考文章:
三分钟带你快速学习RGB、HSV和HSL颜色空间 - 知乎 (zhihu.com)
使用HSV进行区分的效果,可以看到,效果好了很多:
但是此处,使用轮廓识别和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::cvtCol