I'm writing a simple Qt application to test multi-threading (something I am also completely new to).I made a QApplication to manage the GUI,then I write a class VisionApp that contains the class MainWindow which is a subclass of QMainWindow.
In the MainWindow class,I write a function void MainWindow::getfromfilevd() which is connected to the button using this:
QObject::connect(ui->FileVdButton,SIGNAL(clicked()),this,SLOT(getfromfilevd()));
Then I want to read a image from file by using QFileDialog::getOpenFileName,my code is here:
void MainWindow::getfromfilevd()
{
//mutex.lock();
from_imgorvd = true;
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"),"", tr("Image Files (*.png *.jpg *.bmp *.xpm)"));
if(fileName.isEmpty()) {
cv::Mat image;
image = cv::imread(fileName.toUtf8().constData(), CV_LOAD_IMAGE_COLOR);
mutex.lock();
Mat_Img = image.clone();
mutex.unlock();
}
}
however,every time I click the button ,the window of QFileDialog opened but it is blank,then my program finished unexpected.
when I use this code:
void MainWindow::getfromfilevd()
{
from_imgorvd = true;
cv::Mat image;
image = cv::imread("/home/somnus/Picture/mouse.jpg", CV_LOAD_IMAGE_COLOR);
if(! image.data) {
std::cout << "Could not open or find the image" << std::endl ;
}
else {
mutex.lock();
Mat_Img = image.clone();
mutex.unlock();
}
}
It works well.
I am really wonder which mistake I take...
Hope for your help
It should be like this, !fileName.isEmpty() in stead of fileName.isEmpty() because you need to load image when the file name is not empty not the opposite.
Related
I am trying to display a video in QLabet in QT Creator. I am reading video using openCV. Here is my code:
mainwindow.cpp
#include "includes.h"
#include "vidreadthread.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
VidReadThread *thread1 = new VidReadThread("Video read thread");
thread1->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
vidreadthread.cpp
#include "vidreadthread.h"
#include "includes.h"
using namespace cv;
extern MainWindow *mainPtr;
VidReadThread::VidReadThread(QString s) : name(s)
{
}
void VidReadThread::run()
{
QThread::msleep(100);
VideoCapture cap;
cap.open("helicopter_with_stickers.mp4");
while(1)
{
Mat image1;
// Capture frame-by-frame
cap >> image1;
// If the frame is empty, break immediately
if (image1.empty())
break;
QImage image2 = QImage((uchar*) image1.data, image1.cols, image1.rows, image1.step, QImage::Format_RGB888);
mainPtr->ui->label1->setPixmap(QPixmap::fromImage(image2));
}
}
I am able to display the video but I can't set frame rate. Whole 60sec of video gets over in 4-5 frames. With only OpenCV I have command on frame rate with cvWaitkey(), but here msleep() doesn't seem to be working for a similar application. Please suggest a way to do so without frame skipping. I made a vidreadthread so that GUI doesn't get hanged while video is being read.
If there is any other way by which I can display OpenCV window inside my QT UI, then please recommend that as well.
try moveto thread may works better
.cpp
for (int i = 0; i<Camera::getCameraCount();)
ui->comboBox->addItem(QString::number(i++)); //name camera
camera = new Camera();
camera->moveToThread(&thread);
connect(this, SIGNAL(cameraOperate(int)), camera, SLOT(Operate(int)));
connect(camera, SIGNAL(updateImage(QImage)), this, SLOT(updateImage(QImage)));
void app0::updateImage(QImage image)
{
ui->videoviewer->setPixmap(QPixmap::fromImage(image));
}
camera thread:
void Camera::Operate(int _index)
{
if (open(_index)) { qDebug() << "Camera open success!";}
else { qDebug() << "Camera open failed!"; return; }
if (capture.get(28) == -1) { cout << "get 28 -1" << "\n";emit }
while (1)
{
qApp->processEvents();
Mat matin = read(); //read mat
matnow = matin;
QImage image = Mat2QImage(matin);
emit updateImage(image);
}
}
link:https://blog.csdn.net/Sun_tian/article/details/104236327
Is there a easy way to load sf::Image using for example QDialog or other library? I mean I want to load image for using it in sfml by "Choose image..." window.
You can use QFileDialog to get the path of the given image:
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
QDir::currentDirPath() ,
tr("Images (*.png *.xpm *.jpg)"));
if (!fileName.isEmpty()) {
// Now you can init your sf::image
}
According to the official documentation of SFML, you can use the loadFromFile function
sf::Image image;
if (image.loadFromFile(filename.toStdString())) {
std::cout << "image loaded with success";
}
I'm struggling to print an image to the PNG format using Qt4.
The code below has default settings of either PDF or PS, but no way to choose PNG:
void DetectorView::printToFile()
{
// A basic printing function
QPrinter printer;
QPrintDialog dialog(&printer, this);
if (dialog.exec()==QDialog::Accepted) {
QPainter painter(&printer);
this->render(&painter);
std::cout << "INFO [DetectorView::printToFile] Wrote file " << std::endl;
}
else {
std::cout << "INFO [DetectorView::printToFile] Cancelling printer " << std::endl;
}
}
Any help would be appreciated!
Using this link: Rendering QWidget to QImage loses alpha-channel, you can render your widget to a QImage.
Then, using QImageWriter, you can save it to a png:
// render QWidget to QImage:
QImage bitmap(this->size(), QImage::Format_ARGB32);
bitmap.fill(Qt::transparent);
QPainter painter(&bitmap);
this->render(&painter, QPoint(), QRegion(), QWidget::DrawChildren);
// save QImage to png file:
QImageWriter writer("file.png", "png");
writer.write(bitmap);
Note: links provided are for Qt5, but this should work with Qt4.
Using jpo38's answer, I expanded to get the behaviour I wanted:
void DetectorView::printToFile()
{
QString default_name = "myImage.png";
QImage bitmap(this->size(), QImage::Format_ARGB32);
QPainter painter(&bitmap);
this->render(&painter,QPoint(),QRegion(),QWidget::DrawChildren);
QString filename = QFileDialog::getSaveFileName(this, tr("Save File"),QDir::homePath()+"/"+default_name,tr("Image Files (*.png *.jpg *.bmp)"));
QImageWriter writer(filename, "png");
writer.write(bitmap);
std::cout << "INFO [DetectorView::printToFile] Wrote image to file" << std::endl;
}
Note the QFileDialog which is needed to create the interactive window.
I am making a Qt GUI application that uses a custom QLabel class (name as ImageInteraction) to show images from a streaming camera while also allowing mouse interaction on the image. As the GUI has other functionalities, the customized QLabel class does the job of extracting the image from the camera and updating its shown image through a while loop in a function which is run in another thread. The code for that is as below:
void ImageInteraction::startVideo()
{
if (!capture.open(streamUrl))
{
QMessageBox::warning(this, "Error", "No input device availabe!");
}
else
{
QFuture<void> multiprocess = QtConcurrent::run(this, &ImageInteraction::loadVideo);
}
}
void ImageInteraction::loadVideo()
{
while(loopContinue){
cv::Mat frame;
capture.read(frame);
if(!frame.empty())
{
cv::cvtColor(frame, frame, CV_BGR2RGBA);
cv::resize(frame, frame, cv::Size(this->width(), this->height()), 0, 0);
QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGBA8888);
this->setPixmap(QPixmap::fromImage(image));
}
}
capture.release();
}
Here capture is of type cv::VideoCapture and loopContinue is a boolean type which is initially set to be true. There is a closeEvent() function that invokes the method for stopping the capture of the image from the camera.
void MainWindow::closeEvent(QCloseEvent *event)
{
liveVideo->stopVideoThread();//liveVideo is a pointer to an object of ImageInteraction
event->accept();
}
where stopVideoThread simply sets the boolean flag loopContinue to false and has the following simple code:
void ImageInteraction::stopVideoThread()
{
mutex.lock();//QMutex mutex;
loopContinue = false;
mutex.unlock();
}
In my understanding the while loop in loadVideo method should be stopped once stopVideoThread method is invoked and loopContinue is set to false. But in reality, when the close button is pressed, apparently it doesn't stop while loop and the application crashes with a message:
The inferior stopped because it received a signal from the operating system.
Signal name : SIGSEGV
Signal meaning : Segmentation fault
Am I using QtConcurrent::run method and the QMutex object erroneously? Could you identify what the problem is? FYI, the OS is ubuntu 14.04 and IDE is QtCreator.
Thanks!
The following is just an idea of the improvements mentioned in the above comments.
class ImageInteraction
{
public:
~ImageInteraction()
{
multiprocess_.waitForFinished();
}
void startVideo()
{
if (!capture.open(streamUrl))
{
QMessageBox::warning(this, "Error", "No input device availabe!");
}
else
{
multiprocess_ = QtConcurrent::run(this, &ImageInteraction::loadVideo);
}
}
void loadVideo()
{
while(loopContinue_)
{
cv::Mat frame;
capture.read(frame);
if(!frame.empty())
{
cv::cvtColor(frame, frame, CV_BGR2RGBA);
cv::resize(frame, frame, cv::Size(this->width(), this->height()), 0, 0);
QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGBA8888);
this->setPixmap(QPixmap::fromImage(image));
}
}
capture.release();
}
void stopVideoThread()
{
loopContinue_ = false;
//multiprocess_.waitForFinished(); // you can call this here if you want to make sure that the thread has finished before returning
}
private:
QFuture<void> multiprocess_;
std::atomic<bool> loopContinue_;
};
I saw an other thread talking about this, but I'm not succeeding in the display of my image.
Currently, I'm downloading my image like this :
void MyClass::imgHandle() {
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
QUrl url(_code.c_str());
QNetworkReply* reply = nam->get(QNetworkRequest(url));
QEventLoop eventLoop;
connect(reply,SIGNAL(finished()),&eventLoop,SLOT(quit()));
eventLoop.exec();
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
imageReader.setAutoDetectImageFormat (false);
_img = imageReader.read();
}
}
_code is built from a code got from a Json parsing, and the url looks like this : http://l.yimg.com/a/i/us/we/52/33.gif
_img is a QImage in my class.
And in my other class I do this :
int OtherClass::displayWeather()
{
MyClass mC = new MyClass;
mC->exec() // Where I get the code from the Json
QLabel *imgWeather = new QLabel(this);
imgWeather->setPixmap(QPixmap::fromImage(mC->getImg()));
// getImg() return a QImage.
//The QImage created in MyClass.
imgWeather->setGeometry(1700, 0, 120, 120);
}
And at the end .. Nothing is displayed !
You should check the QImageReader::read result:
QImageReader imageReader(reply);
imageReader.setAutoDetectImageFormat(false);
QImage _img = imageReader.read();
if (_img.isNull())
{
qDebug() << imageReader.errorString();
}
In your case the error is "Unsupported image format".
By default QImageReader tries to autodetect the image format and you've just disabled it by calling setAutoDetectImageFormat(false). Remove it and QImageReader will do the job.