我正在制作一个Qt GUI应用程序,该应用程序使用自定义QLabel
类(名称为ImageInteraction
)来显示来自流式摄像机的图像,同时还允许在图像上进行鼠标交互。由于GUI具有其他功能,因此定制的QLabel类可以从摄像机中提取图像,并通过在另一个线程中运行的函数中的while
循环更新其显示的图像。代码如下:
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();
}
此处capture
的类型为cv::VideoCapture
,loopContinue
是布尔类型,最初设置为true
。有一个closeEvent()
函数可以调用停止从相机捕获图像的方法。
void MainWindow::closeEvent(QCloseEvent *event)
{
liveVideo->stopVideoThread();//liveVideo is a pointer to an object of ImageInteraction
event->accept();
}
其中stopVideoThread
只是将布尔标记loopContinue
设置为false
,并具有以下简单代码:
void ImageInteraction::stopVideoThread()
{
mutex.lock();//QMutex mutex;
loopContinue = false;
mutex.unlock();
}
据我了解,调用while
方法并将loadVideo
设置为false后,应停止stopVideoThread
方法中的loopContinue
循环。但实际上,当按下关闭按钮时,显然它不会停止while
循环,应用程序崩溃并显示一条消息:
The inferior stopped because it received a signal from the operating system.
Signal name : SIGSEGV
Signal meaning : Segmentation fault
我是否错误地使用QtConcurrent::run
方法和QMutex
对象?你能确定问题是什么吗?仅供参考,操作系统是ubuntu 14.04,IDE是QtCreator。
谢谢!
答案 0 :(得分:1)
以下只是对上述评论中提到的改进的概念。
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_;
};