Problem with widgets in minimal integration of opencv
-
Hi, i'm a beginnner and i use visual studio 2022 and the project is a c++ from the qt template.
Opencv is correctly linked and all dll are present.I managed to get the video feed of a webcam in a qt window but the rest of the widgets are behaving weirdly.
They have no code for now.I have done no sizing or placing of stuff for now so my program start like this :
The widget at the top respond to the mouse when i click or hover them.
Those on the right do nothing.If i extend the window i get this :
The green part are responsive but the red part do nothing.
The widgets are just added in the designer, all the same way just drag and drop.
I have no idea what to do.
Before i can make some functions and add more stuff i need buttons that work.my main.cpp:
#include "QtWidgetsApplication1.h" #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) { QApplication a(argc, argv); QtWidgetsApplication1 w; w.show(); // Create a QLabel to display the webcam feed QLabel* webcamLabel = w.getWebcamLabel(); // Use 'webcamLabel->show()' instead of 'webcamLabel.show()' webcamLabel->show(); // Open the default camera (camera index 0) VideoCapture cap(0); if (!cap.isOpened()) { // Use 'webcamLabel->setText' instead of 'label.setText' webcamLabel->setText("Cannot open camera"); webcamLabel->repaint(); return -1; } Mat frame; while (true) { // Read a frame from the camera cap >> frame; cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); if (frame.empty()) { // Use 'webcamLabel->setText' instead of 'label.setText' webcamLabel->setText("End of video stream"); webcamLabel->repaint(); break; } // Convert the OpenCV Mat to a QImage QImage qImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888); // Display the QImage in the QLabel // Use 'webcamLabel->setPixmap' instead of 'webcamLabel.setPixmap' webcamLabel->setPixmap(QPixmap::fromImage(qImage)); webcamLabel->repaint(); // Pause for a short duration to control the frame rate QCoreApplication::processEvents(); } return a.exec(); }
My QtWidgetsApplication1.h :
#pragma once #include <QtWidgets/QMainWindow> #include "ui_QtWidgetsApplication1.h" #include <QLabel> #include <opencv2/opencv.hpp> class QtWidgetsApplication1 : public QMainWindow { Q_OBJECT public: QtWidgetsApplication1(QWidget* parent = nullptr); ~QtWidgetsApplication1(); QLabel* getWebcamLabel() const { return webcamLabel; } private: Ui::QtWidgetsApplication1Class ui; QLabel* webcamLabel; // QLabel to display the webcam feed cv::VideoCapture cap; // OpenCV VideoCapture for webcam QTimer* timer; // QTimer to update the feed cv::Mat frame; // OpenCV Mat for holding frames };
My QtWidgetsApplication1.cpp :
#include "QtWidgetsApplication1.h" #include <QTimer> #include <QVBoxLayout> #include <opencv2/opencv.hpp> using namespace std; QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent) : QMainWindow(parent) { ui.setupUi(this); // Load the UI from the .ui file, including the existing central widget // Access the existing central widget QWidget* existingCentralWidget = centralWidget(); // Create a layout for the existing central widget (e.g., QVBoxLayout) QVBoxLayout* layout = new QVBoxLayout(existingCentralWidget); webcamLabel = new QLabel(existingCentralWidget); // Create a QLabel for the webcam feed webcamLabel->setObjectName("webcamLabel"); // Set object name for later reference in Qt Designer // Add the webcamLabel to the layout layout->addWidget(webcamLabel); } QtWidgetsApplication1::~QtWidgetsApplication1() {}
Any help is appreciated, since there is no code yet it is layout or refresh related but i don't know what to do to solve this.
-
Hi and welcome to devnet,
You should rather use a QTimer to grab the images rather than using a blocking loop like you do. Calling processEvent like that is a last resort solution that should be avoided.
-
Hi and welcome to devnet,
You should rather use a QTimer to grab the images rather than using a blocking loop like you do. Calling processEvent like that is a last resort solution that should be avoided.
@SGaist Thank you for the advice
Cleaned up main :
#include "QtWidgetsApplication1.h" #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) { QApplication a(argc, argv); QtWidgetsApplication1 w; w.show(); QLabel* webcamLabel = w.getWebcamLabel(); webcamLabel->show(); return a.exec(); }
Timer added in QtWidgetsApplication1.cpp :
#include "QtWidgetsApplication1.h" #include <QTimer> #include <QVBoxLayout> #include <opencv2/opencv.hpp> using namespace std; QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent) : QMainWindow(parent) { ui.setupUi(this); // Load the UI from the .ui file, including the existing central widget // Access the existing central widget QWidget* existingCentralWidget = centralWidget(); // Create a layout for the existing central widget (e.g., QVBoxLayout) QVBoxLayout* layout = new QVBoxLayout(existingCentralWidget); webcamLabel = new QLabel(existingCentralWidget); // Create a QLabel for the webcam feed webcamLabel->setObjectName("webcamLabel"); // Set object name for later reference in Qt Designer // Add the webcamLabel to the layout layout->addWidget(webcamLabel); // Open the default camera (camera index 0) cap.open(0, cv::VideoCaptureAPIs::CAP_DSHOW); if (!cap.isOpened()) { webcamLabel->setText("Cannot open camera"); return; } cout << cap.get(cv::VideoCaptureProperties::CAP_PROP_FORMAT); // Create a QTimer to update the frame timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateFrame())); timer->start(30); // Adjust the interval as needed for your desired frame rate } QtWidgetsApplication1::~QtWidgetsApplication1() {} void QtWidgetsApplication1::updateFrame() { // Read a frame from the camera cap >> frame; // Convert the OpenCV Mat to a QImage (correcting color format from BGR to RGB) cv::Mat rgbFrame; cv::cvtColor(frame, rgbFrame, cv::COLOR_BGR2RGB); QImage qImage(rgbFrame.data, rgbFrame.cols, rgbFrame.rows, rgbFrame.step, QImage::Format_RGB888); // Display the QImage in the QLabel webcamLabel->setPixmap(QPixmap::fromImage(qImage)); // Update the QLabel webcamLabel->update(); }
Still same behavior.
-
@SGaist Thank you for the advice
Cleaned up main :
#include "QtWidgetsApplication1.h" #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) { QApplication a(argc, argv); QtWidgetsApplication1 w; w.show(); QLabel* webcamLabel = w.getWebcamLabel(); webcamLabel->show(); return a.exec(); }
Timer added in QtWidgetsApplication1.cpp :
#include "QtWidgetsApplication1.h" #include <QTimer> #include <QVBoxLayout> #include <opencv2/opencv.hpp> using namespace std; QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent) : QMainWindow(parent) { ui.setupUi(this); // Load the UI from the .ui file, including the existing central widget // Access the existing central widget QWidget* existingCentralWidget = centralWidget(); // Create a layout for the existing central widget (e.g., QVBoxLayout) QVBoxLayout* layout = new QVBoxLayout(existingCentralWidget); webcamLabel = new QLabel(existingCentralWidget); // Create a QLabel for the webcam feed webcamLabel->setObjectName("webcamLabel"); // Set object name for later reference in Qt Designer // Add the webcamLabel to the layout layout->addWidget(webcamLabel); // Open the default camera (camera index 0) cap.open(0, cv::VideoCaptureAPIs::CAP_DSHOW); if (!cap.isOpened()) { webcamLabel->setText("Cannot open camera"); return; } cout << cap.get(cv::VideoCaptureProperties::CAP_PROP_FORMAT); // Create a QTimer to update the frame timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateFrame())); timer->start(30); // Adjust the interval as needed for your desired frame rate } QtWidgetsApplication1::~QtWidgetsApplication1() {} void QtWidgetsApplication1::updateFrame() { // Read a frame from the camera cap >> frame; // Convert the OpenCV Mat to a QImage (correcting color format from BGR to RGB) cv::Mat rgbFrame; cv::cvtColor(frame, rgbFrame, cv::COLOR_BGR2RGB); QImage qImage(rgbFrame.data, rgbFrame.cols, rgbFrame.rows, rgbFrame.step, QImage::Format_RGB888); // Display the QImage in the QLabel webcamLabel->setPixmap(QPixmap::fromImage(qImage)); // Update the QLabel webcamLabel->update(); }
Still same behavior.
Did you benchmark your slot ?
Why are you calling show on webcamLabel ? It should be shown automatically since it's part of QtWidgetsApplication1.
By the way, there's no need to call update since you are changing the pixmap every time. -
Did you benchmark your slot ?
Why are you calling show on webcamLabel ? It should be shown automatically since it's part of QtWidgetsApplication1.
By the way, there's no need to call update since you are changing the pixmap every time.@SGaist
I'm not sure how to use slots and i don't know what benchmark mean in this context.
Indeed, webcamLabel.show and webcamLabel->update(); where unneeded, blame me who tried to use chatgpt to help.I found that removing completly all opencv code made the buttons work normally again.
Since i don't know the inner workings of Qt, i don't know exactly how the opencv addition on the central widget mess with the buttons events and/or display.I'm working on a solution where the camera code is in a separate thread and right from the start the buttons all worked normally.
-
@SGaist
I'm not sure how to use slots and i don't know what benchmark mean in this context.
Indeed, webcamLabel.show and webcamLabel->update(); where unneeded, blame me who tried to use chatgpt to help.I found that removing completly all opencv code made the buttons work normally again.
Since i don't know the inner workings of Qt, i don't know exactly how the opencv addition on the central widget mess with the buttons events and/or display.I'm working on a solution where the camera code is in a separate thread and right from the start the buttons all worked normally.
@ADAG said in Problem with widgets in minimal integration of opencv:
I'm not sure how to use slots
You're already using one:
connect(timer, SIGNAL(timeout()), this, SLOT(updateFrame()));
You should switch to newer Qt5 connect syntax, but this is another topic.
I guess what @SGaist suggested is that you benchmark your updateFrame() slot to see where it spends most time.
-
Hi, i'm a beginnner and i use visual studio 2022 and the project is a c++ from the qt template.
Opencv is correctly linked and all dll are present.I managed to get the video feed of a webcam in a qt window but the rest of the widgets are behaving weirdly.
They have no code for now.I have done no sizing or placing of stuff for now so my program start like this :
The widget at the top respond to the mouse when i click or hover them.
Those on the right do nothing.If i extend the window i get this :
The green part are responsive but the red part do nothing.
The widgets are just added in the designer, all the same way just drag and drop.
I have no idea what to do.
Before i can make some functions and add more stuff i need buttons that work.my main.cpp:
#include "QtWidgetsApplication1.h" #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) { QApplication a(argc, argv); QtWidgetsApplication1 w; w.show(); // Create a QLabel to display the webcam feed QLabel* webcamLabel = w.getWebcamLabel(); // Use 'webcamLabel->show()' instead of 'webcamLabel.show()' webcamLabel->show(); // Open the default camera (camera index 0) VideoCapture cap(0); if (!cap.isOpened()) { // Use 'webcamLabel->setText' instead of 'label.setText' webcamLabel->setText("Cannot open camera"); webcamLabel->repaint(); return -1; } Mat frame; while (true) { // Read a frame from the camera cap >> frame; cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); if (frame.empty()) { // Use 'webcamLabel->setText' instead of 'label.setText' webcamLabel->setText("End of video stream"); webcamLabel->repaint(); break; } // Convert the OpenCV Mat to a QImage QImage qImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888); // Display the QImage in the QLabel // Use 'webcamLabel->setPixmap' instead of 'webcamLabel.setPixmap' webcamLabel->setPixmap(QPixmap::fromImage(qImage)); webcamLabel->repaint(); // Pause for a short duration to control the frame rate QCoreApplication::processEvents(); } return a.exec(); }
My QtWidgetsApplication1.h :
#pragma once #include <QtWidgets/QMainWindow> #include "ui_QtWidgetsApplication1.h" #include <QLabel> #include <opencv2/opencv.hpp> class QtWidgetsApplication1 : public QMainWindow { Q_OBJECT public: QtWidgetsApplication1(QWidget* parent = nullptr); ~QtWidgetsApplication1(); QLabel* getWebcamLabel() const { return webcamLabel; } private: Ui::QtWidgetsApplication1Class ui; QLabel* webcamLabel; // QLabel to display the webcam feed cv::VideoCapture cap; // OpenCV VideoCapture for webcam QTimer* timer; // QTimer to update the feed cv::Mat frame; // OpenCV Mat for holding frames };
My QtWidgetsApplication1.cpp :
#include "QtWidgetsApplication1.h" #include <QTimer> #include <QVBoxLayout> #include <opencv2/opencv.hpp> using namespace std; QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent) : QMainWindow(parent) { ui.setupUi(this); // Load the UI from the .ui file, including the existing central widget // Access the existing central widget QWidget* existingCentralWidget = centralWidget(); // Create a layout for the existing central widget (e.g., QVBoxLayout) QVBoxLayout* layout = new QVBoxLayout(existingCentralWidget); webcamLabel = new QLabel(existingCentralWidget); // Create a QLabel for the webcam feed webcamLabel->setObjectName("webcamLabel"); // Set object name for later reference in Qt Designer // Add the webcamLabel to the layout layout->addWidget(webcamLabel); } QtWidgetsApplication1::~QtWidgetsApplication1() {}
Any help is appreciated, since there is no code yet it is layout or refresh related but i don't know what to do to solve this.
Oh, dear, the problem has nothing to do with opencv or video capture.
If you add a frame to your QLabel likewebcamLabel->setFrameShape(QFrame::Box);
You will see that's your QLabel above other widgets, so blocking their mouse events.
About the "responsive" top part, that's because QVBoxLayout has default 9px margins.
If you addlayout->setContentsMargins(0, 0, 0, 0);
Then they'll be not responsive at all.
So the problem can be easily solved after you learn how to properly use layouts to arrange the widgets and not let anyone block others.
I think you are just copying the code from somewhere else, right? The orignal example probably doesn't use ui file and only has an empty window.
In your case, I would suggest that don't create the layout and the label in the cpp file, but in the ui file with all the other widgets.