【发布时间】:2021-05-01 11:38:47
【问题描述】:
我正在使用 Basler 相机同时传输图像和分析图像。 该程序在子项目静态库中有摄像头类、图像检测类、图像采集类。用于在另一个 GUI 子项目中显示流的 GUI。但是,当程序运行时,GUI 在摄像机流式传输时一直“无响应”。我做错了什么,我需要在这种情况下实现 QThread 吗?如果我必须使用 QThread,我应该在主 GUI 线程中使用它还是在 Acquisition 中使用它? 从 Basler 相机中获取图像流的相机类:
class ICam: public QObject
,public Pylon::CImageEventHandler {
Q_OBJECT
public:
ICam(QObject *parent = nullptr);
Mat GetOpencvImage();
void StartContinuousGrabbing();
signals:
void OneImageFinishSignal();
protected:
virtual void OnImageGrabbed(Pylon::CInstantCamera& camera, const Pylon::CGrabResultPtr& grabResult);
private:
CBaslerUniversalInstantCamera m_camera;
};
void ICam::OnImageGrabbed(Pylon::CInstantCamera& camera, const Pylon::CGrabResultPtr& grabResult)
{
clock.Lock();
m_ptr_grab_result = grabResult;//Pass the captured image out
m_bitmap_image.CopyImage(grabResult);
clock.Unlock();
emit OneImageFinishSignal();
}
Mat ICam::GetOpencvImage(){
return cv::Mat(m_bitmap_image.GetHeight(), m_bitmap_image.GetWidth(), CV_8UC3, (uint8_t *)m_bitmap_image.GetBuffer());
}
void ICam::StartContinuousGrabbing(){
m_camera.StartGrabbing( Pylon::GrabStrategy_OneByOne, Pylon::GrabLoop_ProvidedByInstantCamera);
}
Detect 类进行图像处理以检测虹膜眼:
class Detect : public QObject
{
Q_OBJECT
public:
explicit Detect(QObject *parent = nullptr);
cv::Point CalculateIrisOffset(cv::Mat img_input);
};
cv::Point Detect::CalculateIrisOffset(cv::Mat img_input, bool show) {
//Some Code to detect the iris
return center_offset;
}
Acquisition 类包含一个ICam 类的icam 对象和一个Detect 类的detect 对象作为成员属性,它在抓取图像时从icam 对象接收信号,同时向GUI 发送信号以显示图像,调用Detect类的detect函数对图像进行处理:
class Acquisition: public QObject
{
Q_OBJECT
public:
Acquisition (QObject *parent = nullptr);
void StartContinuousGrabbing();
Mat GetOpenCVImageFromICam();
signals:
void OneImageFinishSignal();
private slots:
void OneImageFinishSlot();
private:
ICam *icam;
Detect *detect;
};
Acquisition:: Acquisition(QObject *parent) : QObject(parent)
,icam(new ICam())
,detect(new Detect())
{
//connect(this->icam, SIGNAL(OneImageFinishSignal()), this, SIGNAL(OneImageFinishSignal()));
connect(this->icam, SIGNAL(OneImageFinishSignal()), this, SLOT(OneImageFinishSlot()));
}
void Acquisition::OneImageFinishSlot(){
cv::Mat img_input= icam-> GetOpencvImage ();
cv::Point center_iris_offset;
center_offset = detect->CalculateOffset(img_input, 0);
emit(OneImageFinishSignal());
}
void Acquisition::StartContinuousGrabbing(){
this->icam->StartContinuousGrabbing();
}
Mat CDLImageAcquisition::GetOpenCVImageFromICam(){
return this->icam_->GetOpencvImage();
}
主 GUI 类:
class MainWizard : public QWizard
{
Q_OBJECT
public:
explicit MainWizard(QWidget *parent = nullptr);
private slots:
void OneImageFinishSlot();
void ShowImage(QWidget *object, Mat image);
private:
virtual bool eventFilter(QObject *watched, QEvent *event);
Acquisition *acquisition;
};
MainWizard::MainWizard(QWidget *parent) :
QWizard(parent),
ui(new Ui::MainWizard),
acquisition(new Acquisition())
{
ui->setupUi(this);
ui->dock_cnt_continuous_grab->installEventFilter(this);//Install Qt's event filter
acquisition ->StartContinuousGrabbing();
connect(acquisition, SIGNAL(OneImageFinishSignal()), this, SLOT(OneImageFinishSlot()));
}
void MainWizard::OneImageFinishSlot(){
ui->dock_cnt_continuous_grab->update();
}
bool MainWizard::eventFilter(QObject *watched, QEvent *event)
{
if (watched == ui->dock_cnt_continuous_grab && event->type() == QEvent::Paint)
{
cv::Mat opencv_image = acquisition->GetOpenCVImageFromICam();
this->ShowImage(ui->dock_cnt_continuous_grab, opencv_image);
}
return false;
}
void MainWizard::ShowImage(QWidget *widget, Mat image)
{
m_mutex_lock.lock();
QPainter painter(widget);
QImage img((const unsigned char *)(image.data), image.cols, image.rows, QImage::Format_RGB888);
QRectF target;
target.setLeft(0);
target.setTop(0);
target.setSize(this->size());
QRectF source;
source.setLeft(0);
source.setTop(0);
source.setSize(img.size());
QPixmap pixmap = QPixmap::fromImage(img);
painter.drawImage(target,img, source);
painter.drawPixmap(target, pixmap, source);
m_mutex_lock.unlock();
}
【问题讨论】:
-
你能附加
MainWizard::ShowImage函数吗? -
是的,我只是将它附加到 MainWizard 类的末尾。
-
您不必在仅在 GUI 线程中调用的私有插槽中使用
mutex。捕获事件时,您的事件过滤器未返回true。你的画家画了image和pixmap,图像就足够了。 -
你为什么不直接update
dock_cnt_continuous_grab并在paintEvent 中绘制图像。 -
谢谢,我按照你说的编辑了代码,但是 GUI 仍然没有响应
标签: c++ qt camera streaming qthread