mercredi 27 janvier 2021

Qt GUI thread is not responding when camera is streaming

I am using Basler camera to stream images and analyze the image at the same time. The program has camera class, an image detection class, an image acquisition class in a subproject static library. A GUI to show the stream in another GUI subproject. However, when the program is running, the GUI keeps "not responding" while the camera is streaming. What did I do wrong, do I need to implement QThread in this scenario? If I have to use QThread, should I use it in the main GUI thread or in the Acquisition? Camera class to grab image stream from Basler camera:

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 to do image processing to detect the iris eye:

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 class contains an icam object of ICam class and a detect object of Detect class as member attributes, it receives signal from the icam object when an image is grabbed and send signal to the GUI to display the image, at the same time, it calls the detect function of the Detect class to process the image:

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();
}

Main GUI class:

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;
}

Aucun commentaire:

Enregistrer un commentaire