在这种特定条件下有没有其他的方法能在MainWindow主体下重启在其他Class线程下的KCF跟踪器的init()函数与update()函数呢?
项目采用QT使用FFmpeg线程拉取网络摄像头的RTSP流转入Opencv线程进行实时(100ms延迟内)的KCF算法跟踪,对于目标跟踪后的图像显示到主线程的ui界面上来。
void MyThread::GotMatimg(cv::Mat img) //目标跟踪显示画面
{
targetstatus = "3";
if(successTrack && !Tack) //鼠标框选判别
{
targetstatus = "2";
tracker->init(img,SignPoint);
Tack = true;
}
else if(Tack)
{
tracker->update(img,SignPoint);
rectangle(img,SignPoint, Scalar(255, 0, 0), 2, 3);
trackx = SignPoint.x + (SignPoint.width /2);
tracky = SignPoint.y + (SignPoint.height /2);
if(!tracker->update(img,SignPoint))
{
targetstatus = "丢失";
}
else
{
targetstatus = "跟踪";
}
}
emit SendMatimg(img); //发送图片数据
}
void MainWindow::GainMatimg(cv::Mat img)
{
showImage(img,QImage::Format_RGB888,ui->label); //显示视频
}
void MainWindow::on_btnsign_clicked()
{
if(ui->btnsign->text() == "识别")
{
threeD->Track_Sign = true;//切换为opencv鼠标框选功能
Tack = false;
targetstatus = "4";
NET_DVR_StopRealPlay(IRealPlayHandle);
struPlayInfo.hPlayWnd = NULL;//需要 SDK 解码时句柄设为有效值,仅取流不解码时可设为空
IRealPlayHandle = NET_DVR_RealPlay_V40(userID,&struPlayInfo,NULL,NULL);
connect(m_trad, SIGNAL(SendMatimg(cv::Mat)), this, SLOT(GainMatimg(cv::Mat)),Qt::AutoConnection); //连接发送跟踪处理后的图片信号与接收图片显示槽
connect(m_ffmpeg, SIGNAL(SigGetOneFrame(cv::Mat)), m_trad, SLOT(GotMatimg(cv::Mat)),Qt::AutoConnection);//连接发送原始图片信号与获取图片进行跟踪处理槽
ui->btnsign->setText("定位");
}
else if(ui->btnsign->text() == "定位")
{
threeD->Track_Sign = false;//关闭opencv鼠标框选功能
successTrack = false; //关闭跟踪处理
struPlayInfo.hPlayWnd = hWnd;//需要 SDK 解码时句柄设为有效值,仅取流不解码时可设为空
IRealPlayHandle = NET_DVR_RealPlay_V40(userID,&struPlayInfo,NULL,NULL);
disconnect(m_trad, SIGNAL(SendMatimg(cv::Mat)), this, SLOT(GainMatimg(cv::Mat)));//断开连接
disconnect(m_ffmpeg, SIGNAL(SigGetOneFrame(cv::Mat)), m_trad, SLOT(GotMatimg(cv::Mat)));
ui->btnsign->setText("识别");
}
}
必须单独使用FFmpeg作为子线程拉取流来进行处理才能达到实时的要求,使用Opencv自带拉流(VideoCapture)无法做到实时要求
鼠标框选子线程来实现要求的目标框选功能,并该子线程需要具备多功能,所以该功能无法改变
在OpenCV子线程将获得到的FFmpeg框选的图像进行KCF初始化(init())后实时更新跟踪图像(update()),KCF跟踪算法对于项目的契合度更高
尝试过在父线程使用KCF算法中的release()、reset()函数进行关闭跟踪,但这两种函数都无法关闭跟踪;无法关闭跟踪就无法进行下一步的操作,请帮我解答一下如何C++下在父线程重新开启在子线程的KCF算法。
使用 OpenCV 进行 KCF 目标跟踪时如果想要在主线程中重新开始跟踪,可以在主线程中重新调用 KCF 跟踪器的 init() 函数。要确保跟踪器在主线程之外的线程中的 update() 函数是在安全的方式下被调用的。
如果你使用的是 QThread 来运行 OpenCV 线程,可以使用 QMetaObject::invokeMethod() 函数来从主线程安全地调用 update() 函数。例如:
QMetaObject::invokeMethod(opencvThread, "update", Qt::QueuedConnection);
这样就可以在主线程中安全地调用 update() 函数了。
如果你使用的是其他线程库,可以使用相应的同步机制来保证 update() 函数在安全的方式下被调用。
1.将新对象的Rect2d直接传递给update()函数;
2.再次使用tracker的init()函数。
如果想要在 MainWindow 主线程中重启在 MyThread 线程中运行的 KCF 跟踪器的 init() 函数和 update() 函数,可以在 MainWindow 中添加一个信号,连接到 MyThread 中的一个槽函数,并在这个槽函数中执行重启操作。
具体来说,可以在 MainWindow 中定义一个信号:
signals:
void resetTracker();
然后在 MyThread 中添加一个槽函数来接收这个信号:
public slots:
void onResetTracker();
在 onResetTracker() 函数中,可以执行重启 KCF 跟踪器的操作:
void MyThread::onResetTracker()
{
tracker->init(currentFrame, SignPoint);
}
最后,在 MainWindow 中,可以连接 resetTracker() 信号与 MyThread 中的 onResetTracker() 槽函数:
connect(this, SIGNAL(resetTracker()), m_trad, SLOT(onResetTracker()));
然后在需要重启 KCF 跟踪器时,可以调用 emit resetTracker() 来发送信号,从而在 MyThread 中重启 KCF 跟踪器。
仅供参考,望采纳,谢谢。
目标跟踪的深度学习方法与opencv下的KCF方法
借鉴下
https://blog.csdn.net/LOVE1055259415/article/details/81006596
我看到一篇类似的文章希望对你有所帮助,目标跟踪的深度学习方法与opencv下的KCF方法
借鉴下:《目标跟踪的深度学习方法与opencv下的KCF方法》
在您的项目中,您使用QT作为前端界面开发框架,并使用OpenCV作为图像处理库,并使用KCF算法进行目标跟踪。
若您想要在主线程中重启在其他线程中运行的KCF跟踪器,您可以使用Qt信号与槽机制来进行通信。在主线程中添加一个按钮或其他控件,在点击这个按钮时,主线程发送一个信号到跟踪线程,告诉它重启KCF跟踪器。在跟踪线程中,您需要定义一个槽函数来接收这个信号并执行相应的操作,例如重新调用KCF跟踪器的init()函数。
还有一种可能是,在跟踪线程中,对KCF跟踪器进行初始化之前需要设置标志位, 在主线程中,在需要重启跟踪器时将这个标志位设置为真,并在跟踪线程的update函数中判断这个标志位,如果为真就调用kcf跟踪器的init()函数,再将标志位设置为假。这样做的好处是可以在运行期间随时重启跟踪器,而不会影响到其他的操作。
需要注意,需要确保线程之间的安全性,避免在跟踪线程和主线程之间产生竞争条件。
你可以通过在主线程中发送信号,在其他类的线程中接收信号并调用 init() 和 update() 函数来重启跟踪器。
首先,你需要在其他类的线程中定义一个槽函数来接收信号。然后,你可以在主窗口的某个按钮的点击事件中发射信号,触发其他类的线程中的槽函数。其他类的线程中的槽函数就可以调用跟踪器的 init() 和 update() 函数来重启跟踪器了。
这里是一个简单的示例代码:
主窗口(MainWindow)中的代码:
// 发射信号
void MainWindow::on_btnsign_clicked()
{
emit RestartTracker();
}
其他类(OtherClass)中的代码:
// 接收信号并调用跟踪器的init()和update()函数
void OtherClass::onRestartTracker()
{
tracker->init(img,SignPoint);
tracker->update(img,SignPoint);
}
// 连接信号和槽
OtherClass::OtherClass(QObject *parent) : QObject(parent)
{
connect(mainWindow, SIGNAL(RestartTracker()), this, SLOT(onRestartTracker()));
}
在这种情况下,你需要在主窗口的构造函数中将其他类的对象传入,以便主窗口能够发射信号并触发其他类的槽函数。你也可以在其他类的构造函数中将主窗口的对象传入,以便其他类能够连接信号和槽。
这里是完整的示例代码:
主窗口(MainWindow)中的代码:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "otherclass.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
OtherClass *otherClass = new OtherClass(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
// 发射信号
void MainWindow::on_btnsign_clicked()
{
emit RestartTracker();
}
其他类(OtherClass)中的代码:
#include "otherclass.h"
#include "mainwindow.h"
OtherClass::OtherClass(QObject *parent) : QObject(parent)
{
// 获取主窗口的对象
mainWindow = qobject_cast<MainWindow*>(parent);
// 连接信号和槽
connect(mainWindow, SIGNAL(RestartTracker()), this, SLOT(onRestartTracker()));
}
OtherClass::~OtherClass()
{
}
// 接收信号并调用跟踪器的init()和update()函数
void OtherClass::onRestartTracker()
{
tracker->init(img,SignPoint);
tracker->update(img,SignPoint);
}