图像识别(12)——LED灯光点捕获+基于QT平台绘制轨迹
Posted somebot
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像识别(12)——LED灯光点捕获+基于QT平台绘制轨迹相关的知识,希望对你有一定的参考价值。
博主QQ:1356438802
QQ群:473383394——UVC&OpenCV473383394
平台:Win7 64bits + Qt 5.3.0 MinGW 32bit + OpenCV 2.4.10
1. 虽然在Windows64系统上运行,图像分析的帧率可以达到25FPM,但是如果做平均值滤波,手写笔运动速度较快时,首先会导致时间延迟, 滞后现象,另外滤波后导致采样点数量减少,最终绘制的轨迹不圆滑,呈线段型。
2. 鉴于人类视觉延迟要求大概就是25FPM,而且25FPM可能就是该摄像头的输出帧率,所以在捕捉到LED灯光点坐标后,进行滤波消除抖动的做法,并不可行!暂时思考后的解决办法是:
a. 改进硬件。当前实验使用是手机的闪光灯,有散光和手机外壳反射光的干扰,排除这些干扰,让LED灯的捕捉检测更加准确。另外还要求红外LED灯的各个方向一致性,因为在手写笔书写过程中,LED灯可能是倾斜的,对于图像识别会有影响,可以包裹漫反射材料解决。
但是这样的处理会导致整个绘制过程相比于手写笔的操作,整体滞后很多,估计印象的投影仪效果就是这样导致的。
下面是增加了平均值滤波的代码
mainwindow.cpp
#include <QMessageBox>
#include <QThread>
#include <QDebug>
#include "cfg.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
ui->setupUi(this);
mIsFirstPoint = true;
mCenterPoint = mPrevCenterPoint = QPointF(0.0, 0.0);
mPointsBuffer.clear();
mLines.clear();
//把LED灯追踪放入一个子线程里面运行
mTracker = new Track();
mTrackThread = new QThread(this);
mTracker->moveToThread(mTrackThread);
connect(this, SIGNAL(startTrack()), mTracker, SLOT(startTrack()));
connect(mTracker, SIGNAL(TrackPoint(QPointF)), this, SLOT(setPoints(QPointF)));
connect(mTracker, SIGNAL(errnum(int)), this, SLOT(errProc(int)));
mTrackThread->start();
MainWindow::~MainWindow()
//停止图像识别
mTracker->StopTrack();
//结束线程
mTrackThread->quit();
mTrackThread->wait();
delete mTrackThread;
delete mTracker;
mPointsBuffer.empty();
mLines.empty();
delete ui;
void MainWindow::paintEvent(QPaintEvent *event)
Q_UNUSED(event);
QPainter painter(this);
// 反走样 反锯齿
painter.setRenderHint(QPainter::Antialiasing, true);
QPen pen(QColor(0, 160, 230));
pen.setWidth(4);
// 设置画笔
painter.setPen(pen);
// 绘制所有直线
foreach (QLineF line, mLines)
painter.drawLine(line);
void MainWindow::setPoints(QPointF Point)
// 先将捕捉到的点坐标,存入缓冲区,待处理
mPointsBuffer.append(Point);
// ##滤波后轨迹不平滑
// 在缓冲区中进行--平均值滤波
// 滤波区间宽度取决于帧率(Windows64上帧率大概为25)。
const int WIDE = 2;
if(mPointsBuffer.size() >= WIDE)
qreal xpos = 0.0, ypos = 0.0;
foreach (QPointF point, mPointsBuffer)
xpos += point.x();
ypos += point.y();
qDebug() <<"mPointsBuffer.size() = " << mPointsBuffer.size();
qDebug() <<"xpos = " << xpos << " ypos = " << ypos;
// 求x/y的平均值
mCenterPoint = QPointF(xpos / mPointsBuffer.size(), ypos / mPointsBuffer.size());
qDebug() << "===========mCenterPoint: x = " << mCenterPoint.x() << " y = " << mCenterPoint.y();
if(true == mIsFirstPoint)
mPrevCenterPoint = mCenterPoint;
mIsFirstPoint = false;
// 将线段(两点构成一条线段)压入队列,待绘制
mLines.append(QLineF(mPrevCenterPoint, mCenterPoint));
// 保存当前点坐标,待下次使用
mPrevCenterPoint = mCenterPoint;
mPointsBuffer.clear(); //清空缓冲区
// 开始重绘
update();
void MainWindow::errProc(int err)
if(CFG::CAMERA_OPEN_FAILED == err)
QMessageBox::warning(this, "警告", "摄像头打开失败");
void MainWindow::on_btnStartTrack_clicked()
emit startTrack();
void MainWindow::on_btnClear_clicked()
mLines.clear();
mIsFirstPoint = true;
update();
完整源码打包下载:
特别补充:
==========20170217==========
1. 实验用的Camera参数:FPS=30; width=640; height=480;
2. 按照[20170210]2.b想法,对捕捉到的LED灯光点坐标,进行OpenCV中的图像平滑算法blur。经过实验,平滑区间设置为16或者8,对于正常的书写速度都不合适,会导致轨迹绘制呈现一阵一阵的阶段性绘制;设置为4,勉强接受;设置为1,也差不多!
3. 总结来说:由于摄像头帧率和图像处理速度的限制,每秒只有25个采样点坐标,这时再进行滤波平滑处理,就会导致轨迹绘制滞后。相比绘制轨迹不平滑有毛刺来说,轨迹绘制滞后的用户体验更差!
4. 所以唯一的办法就是改进硬件,提高LED灯光点的识别准确率!
以上是关于图像识别(12)——LED灯光点捕获+基于QT平台绘制轨迹的主要内容,如果未能解决你的问题,请参考以下文章
图像识别(13)——手势识别——用matchShapes识别手形数字