在 QGraphicsView/QGraphicsScene 上显示一系列图像
Display a sequence of images on a QGraphicsView/QGraphicsScene
我正在开发一个应用程序,我必须在其中显示一系列图像并在其上绘制一些矩形。这就是为什么我必须选择以 QGraphicsScene/QGraphicsView.
显示我的图像
在向您展示我的代码之前,我将详细介绍我开发的一些功能:
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
and void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
=> 对图像(img),对所有图像,或图像的指定部分(x1->x2,y1->y2)进行线性变换,上(Tolmax)和下(Tolmin) 公差
void equalizeHist_16U(Mat &img); and void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
=> 对16位灰度图像进行均等化处理,对图像的指定部分(x1->x2,y1->y2)或对所有图像进行均等化。
ZonePoints getZonePoints();
=> 函数用于获取要进行变换的图像区域(点来自鼠标位置),returns ZonePoints 对象(int xmin、xma、ymin、ymax)
QPixmap convert16uc1(const cv::Mat& source);
=> 将 OpenCV 16 位灰度图像 (Mat) 转换为 RGB32 QPixmap imgage
我有一个文件夹,其中包含许多标记为 "ImageRaw_00000.png" 到 "ImageRaw_02999.png" 的图像。我的图像是 16 位灰度,我使用 OpenCV 打开它们(因为 Qt 无法读取 16 位图像),我想对其进行一些处理(使用 OpenCV),将它们转换为 QPixmap,在其上添加一个矩形(代表区域)并显示它们。
我还需要同时显示 2 个图像(第一个我对 "getZonePoints" 给定的区域进行转换,第二个我显示一个对应于区域点的矩形)。我的应用程序如下所示:PrintScreen of the application
这是我目前所拥有的:
Class 声明:
class FenetrePrinc : public QMainWindow
{
Q_OBJECT
public:
explicit FenetrePrinc(QWidget *parent = 0);
~FenetrePrinc();
void compute_hist_16U(Mat &img, long* hist, bool cumul);
void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
void equalizeHist_16U(Mat &img);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
QPixmap convert16uc1(const cv::Mat& source);
public slots:
virtual void openFile();
virtual void start();
private:
QString filename;
QGraphicsScene *scene_src, *scene_dst;
QGraphicsItem *item_rect;
QGraphicsItem *img_src, *img_dst;
VideoCapture sequence;
Mat src, dst;
bool transfo_lineaire;
bool coupling;
int Tolmin, Tolmax;
int impsec;
ZonePoints zpoints;
};
Class定义:
FenetrePrinc::FenetrePrinc(QWidget *parent) : QMainWindow(parent), ui(new Ui::FenetrePrinc)
{
scene_src = new QGraphicsScene();
img_src = scene_src->addPixmap(QPixmap("vide.jpg"));
img_src->setZValue(1);
ui->view_src->setScene(scene_src);
scene_dst = new QGraphicsScene();
img_dst = scene_dst->addPixmap(QPixmap("vide.jpg"));
img_dst->setZValue(1);
ui->view_dst->setScene(scene_dst);
}
void FenetrePrinc::openFile()
{
filename = QFileDialog::getOpenFileName(this, tr("Open Video file"), "C:/", tr("Image Files (*.png)"));
sequence.open(filename.toStdString());
if(!sequence.isOpened())
ui->buttonStart->setEnabled(false);
else
ui->buttonStart->setEnabled(true);
}
void FenetrePrinc::start()
{
char key;
for(;;)
{
sequence >> src;
sequence >> dst;
if(src.empty() || dst.empty())
{
cout << "End of sequence" << endl;
break;
} zpoints = getZonePoints();
key = (char)waitKey(1000);
if(transfo_lineaire)
{
equalizeHist_16U_linear(src, Tolmin, Tolmax, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U_linear(dst, Tolmin, Tolmax);
}
else
{
equalizeHist_16U(src, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U(dst);
}
scene_src->removeItem(img_src);
img_src = scene_src->addPixmap( convert16uc1(src));
img_src->setZValue(1);
scene_dst->removeItem(img_dst);
img_dst = scene_dst->addPixmap( convert16uc1(dst));
img_dst->setZValue(1);
scene_dst->removeItem(item_rect);
item_rect = scene_dst->addRect(zpoints.xmin, zpoints.ymin, zpoints.xmax-zpoints.xmin+1, zpoints.ymax-zpoints.ymin+1, QPen(Qt::red, 2, Qt::SolidLine));
item_rect->setZValue(2);
if(key == 'q' || key == 'Q' || key == 27)
break;
}
}
我已经完成了一个具有相同行为的工作应用程序,其中我没有使用 Qt,我使用 OpenCV 进行图像处理和显示。我尝试使用相同的技术:
Mat img;
VideoCapture sequence;
sequence.open(filename.toStdString());
for(;;)
{
sequence >> img;
... //Process images
... //Display images
}
但是不行。仅显示最后一个图像和矩形。我想该技术与 Qt 类似,但我找不到代码示例
提前致谢
我找到了一种方法来做我想做的事,最后真的很简单。
我使用了计时器和 signal/slot 机制。
我的新 class 声明如下:
class FenetrePrinc : public QMainWindow
{
Q_OBJECT
public:
explicit FenetrePrinc(QWidget *parent = 0);
~FenetrePrinc();
void compute_hist_16U(Mat &img, long* hist, bool cumul);
void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
void equalizeHist_16U(Mat &img);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
QPixmap convert16uc1(const cv::Mat& source);
public slots:
virtual void openFile();
virtual void start();
virtual void tick(); //Added a 'tick()' slot
private:
QString filename;
QGraphicsScene *scene_src, *scene_dst;
QGraphicsItem *item_rect;
QGraphicsItem *img_src, *img_dst;
VideoCapture sequence, sequence2; //Declared a 2nd sequence
//If there's only 1 sequence, both images will be the same
Mat src, dst;
QTimer *timer //Added a QTimer
bool transfo_lineaire;
bool coupling;
int Tolmin, Tolmax;
int impsec;
ZonePoints zpoints;
};
Class 定义:
FenetrePrinc::FenetrePrinc(QWidget *parent) : QMainWindow(parent), ui(new Ui::FenetrePrinc)
{
scene_src = new QGraphicsScene();
img_src = scene_src->addPixmap(QPixmap("vide.jpg"));
img_src->setZValue(1);
ui->view_src->setScene(scene_src);
scene_dst = new QGraphicsScene();
img_dst = scene_dst->addPixmap(QPixmap("vide.jpg"));
img_dst->setZValue(1);
ui->view_dst->setScene(scene_dst);
timer = new QTimer(this); //timer instantiation
}
void FenetrePrinc::openFile()
{
filename = QFileDialog::getOpenFileName(this, tr("Open Video file"), "C:/", tr("Image Files (*.png)"));
sequence.open(filename.toStdString());
sequence2.open(filename.toStdString());
if(!sequence.isOpened())
ui->buttonStart->setEnabled(false);
else
ui->buttonStart->setEnabled(true);
}
void FenetrePrinc::start()
{
connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
timer->start(1000/impsec);
}
void FenetrePrinc::tick()
{
char key;
int i=0;
sequence >> src;
sequence2 >> dst;
if(src.empty() || dst.empty())
{
stop_timer();
}
zpoints = mgaze->getZonePoints();
zpoints = mgaze->applyOFFSET(zpoints);
zpoints = mgaze->fixZonePoints(zpoints);
if(transfo_lineaire)
{
equalizeHist_16U_linear(src, Tolmin, Tolmax, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U_linear(dst, Tolmin, Tolmax);
}
else
{
equalizeHist_16U(src, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U(dst);
}
scene_src->removeItem(img_src);
img_src = scene_src->addPixmap(convert16uc1(src));
img_src->setZValue(1);
scene_dst->removeItem(img_dst);
img_dst = scene_dst->addPixmap(convert16uc1(dst));
img_dst->setZValue(1);
scene_dst->removeItem(item_rect);
item_rect = scene_dst->addRect(zpoints.xmin, zpoints.ymin, zpoints.xmax-zpoints.xmin+1, zpoints.ymax-zpoints.ymin+1, QPen(Qt::red, 2, Qt::SolidLine));
item_rect->setZValue(2);
}
效果很好,我只需要创建一个 'stop' 插槽,以防我想停止播放视频,这很好
我正在开发一个应用程序,我必须在其中显示一系列图像并在其上绘制一些矩形。这就是为什么我必须选择以 QGraphicsScene/QGraphicsView.
显示我的图像在向您展示我的代码之前,我将详细介绍我开发的一些功能:
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
and void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
=> 对图像(img),对所有图像,或图像的指定部分(x1->x2,y1->y2)进行线性变换,上(Tolmax)和下(Tolmin) 公差
void equalizeHist_16U(Mat &img); and void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
=> 对16位灰度图像进行均等化处理,对图像的指定部分(x1->x2,y1->y2)或对所有图像进行均等化。
ZonePoints getZonePoints();
=> 函数用于获取要进行变换的图像区域(点来自鼠标位置),returns ZonePoints 对象(int xmin、xma、ymin、ymax)
QPixmap convert16uc1(const cv::Mat& source);
=> 将 OpenCV 16 位灰度图像 (Mat) 转换为 RGB32 QPixmap imgage
我有一个文件夹,其中包含许多标记为 "ImageRaw_00000.png" 到 "ImageRaw_02999.png" 的图像。我的图像是 16 位灰度,我使用 OpenCV 打开它们(因为 Qt 无法读取 16 位图像),我想对其进行一些处理(使用 OpenCV),将它们转换为 QPixmap,在其上添加一个矩形(代表区域)并显示它们。
我还需要同时显示 2 个图像(第一个我对 "getZonePoints" 给定的区域进行转换,第二个我显示一个对应于区域点的矩形)。我的应用程序如下所示:PrintScreen of the application
这是我目前所拥有的:
Class 声明:
class FenetrePrinc : public QMainWindow
{
Q_OBJECT
public:
explicit FenetrePrinc(QWidget *parent = 0);
~FenetrePrinc();
void compute_hist_16U(Mat &img, long* hist, bool cumul);
void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
void equalizeHist_16U(Mat &img);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
QPixmap convert16uc1(const cv::Mat& source);
public slots:
virtual void openFile();
virtual void start();
private:
QString filename;
QGraphicsScene *scene_src, *scene_dst;
QGraphicsItem *item_rect;
QGraphicsItem *img_src, *img_dst;
VideoCapture sequence;
Mat src, dst;
bool transfo_lineaire;
bool coupling;
int Tolmin, Tolmax;
int impsec;
ZonePoints zpoints;
};
Class定义:
FenetrePrinc::FenetrePrinc(QWidget *parent) : QMainWindow(parent), ui(new Ui::FenetrePrinc)
{
scene_src = new QGraphicsScene();
img_src = scene_src->addPixmap(QPixmap("vide.jpg"));
img_src->setZValue(1);
ui->view_src->setScene(scene_src);
scene_dst = new QGraphicsScene();
img_dst = scene_dst->addPixmap(QPixmap("vide.jpg"));
img_dst->setZValue(1);
ui->view_dst->setScene(scene_dst);
}
void FenetrePrinc::openFile()
{
filename = QFileDialog::getOpenFileName(this, tr("Open Video file"), "C:/", tr("Image Files (*.png)"));
sequence.open(filename.toStdString());
if(!sequence.isOpened())
ui->buttonStart->setEnabled(false);
else
ui->buttonStart->setEnabled(true);
}
void FenetrePrinc::start()
{
char key;
for(;;)
{
sequence >> src;
sequence >> dst;
if(src.empty() || dst.empty())
{
cout << "End of sequence" << endl;
break;
} zpoints = getZonePoints();
key = (char)waitKey(1000);
if(transfo_lineaire)
{
equalizeHist_16U_linear(src, Tolmin, Tolmax, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U_linear(dst, Tolmin, Tolmax);
}
else
{
equalizeHist_16U(src, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U(dst);
}
scene_src->removeItem(img_src);
img_src = scene_src->addPixmap( convert16uc1(src));
img_src->setZValue(1);
scene_dst->removeItem(img_dst);
img_dst = scene_dst->addPixmap( convert16uc1(dst));
img_dst->setZValue(1);
scene_dst->removeItem(item_rect);
item_rect = scene_dst->addRect(zpoints.xmin, zpoints.ymin, zpoints.xmax-zpoints.xmin+1, zpoints.ymax-zpoints.ymin+1, QPen(Qt::red, 2, Qt::SolidLine));
item_rect->setZValue(2);
if(key == 'q' || key == 'Q' || key == 27)
break;
}
}
我已经完成了一个具有相同行为的工作应用程序,其中我没有使用 Qt,我使用 OpenCV 进行图像处理和显示。我尝试使用相同的技术:
Mat img;
VideoCapture sequence;
sequence.open(filename.toStdString());
for(;;)
{
sequence >> img;
... //Process images
... //Display images
}
但是不行。仅显示最后一个图像和矩形。我想该技术与 Qt 类似,但我找不到代码示例
提前致谢
我找到了一种方法来做我想做的事,最后真的很简单。 我使用了计时器和 signal/slot 机制。
我的新 class 声明如下:
class FenetrePrinc : public QMainWindow
{
Q_OBJECT
public:
explicit FenetrePrinc(QWidget *parent = 0);
~FenetrePrinc();
void compute_hist_16U(Mat &img, long* hist, bool cumul);
void equalizeHist_16U(Mat &img, int x1, int x2, int y1, int y2);
void equalizeHist_16U(Mat &img);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax, int x1, int x2, int y1, int y2);
void equalizeHist_16U_linear(Mat &img, int Tolmin, int Tolmax);
QPixmap convert16uc1(const cv::Mat& source);
public slots:
virtual void openFile();
virtual void start();
virtual void tick(); //Added a 'tick()' slot
private:
QString filename;
QGraphicsScene *scene_src, *scene_dst;
QGraphicsItem *item_rect;
QGraphicsItem *img_src, *img_dst;
VideoCapture sequence, sequence2; //Declared a 2nd sequence
//If there's only 1 sequence, both images will be the same
Mat src, dst;
QTimer *timer //Added a QTimer
bool transfo_lineaire;
bool coupling;
int Tolmin, Tolmax;
int impsec;
ZonePoints zpoints;
};
Class 定义:
FenetrePrinc::FenetrePrinc(QWidget *parent) : QMainWindow(parent), ui(new Ui::FenetrePrinc)
{
scene_src = new QGraphicsScene();
img_src = scene_src->addPixmap(QPixmap("vide.jpg"));
img_src->setZValue(1);
ui->view_src->setScene(scene_src);
scene_dst = new QGraphicsScene();
img_dst = scene_dst->addPixmap(QPixmap("vide.jpg"));
img_dst->setZValue(1);
ui->view_dst->setScene(scene_dst);
timer = new QTimer(this); //timer instantiation
}
void FenetrePrinc::openFile()
{
filename = QFileDialog::getOpenFileName(this, tr("Open Video file"), "C:/", tr("Image Files (*.png)"));
sequence.open(filename.toStdString());
sequence2.open(filename.toStdString());
if(!sequence.isOpened())
ui->buttonStart->setEnabled(false);
else
ui->buttonStart->setEnabled(true);
}
void FenetrePrinc::start()
{
connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
timer->start(1000/impsec);
}
void FenetrePrinc::tick()
{
char key;
int i=0;
sequence >> src;
sequence2 >> dst;
if(src.empty() || dst.empty())
{
stop_timer();
}
zpoints = mgaze->getZonePoints();
zpoints = mgaze->applyOFFSET(zpoints);
zpoints = mgaze->fixZonePoints(zpoints);
if(transfo_lineaire)
{
equalizeHist_16U_linear(src, Tolmin, Tolmax, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U_linear(dst, Tolmin, Tolmax);
}
else
{
equalizeHist_16U(src, zpoints.xmin, zpoints.xmax, zpoints.ymin, zpoints.ymax);
equalizeHist_16U(dst);
}
scene_src->removeItem(img_src);
img_src = scene_src->addPixmap(convert16uc1(src));
img_src->setZValue(1);
scene_dst->removeItem(img_dst);
img_dst = scene_dst->addPixmap(convert16uc1(dst));
img_dst->setZValue(1);
scene_dst->removeItem(item_rect);
item_rect = scene_dst->addRect(zpoints.xmin, zpoints.ymin, zpoints.xmax-zpoints.xmin+1, zpoints.ymax-zpoints.ymin+1, QPen(Qt::red, 2, Qt::SolidLine));
item_rect->setZValue(2);
}
效果很好,我只需要创建一个 'stop' 插槽,以防我想停止播放视频,这很好