如何在 QTableView 上存储图像(Qt 和 openCV)

Posted

技术标签:

【中文标题】如何在 QTableView 上存储图像(Qt 和 openCV)【英文标题】:How to store images on QTableView (Qt and openCV) 【发布时间】:2018-07-18 08:28:51 【问题描述】:

我有一个由 18 列的 QTableView 和一个 QGraphicsView 组成的 GUI,我在其中使用按钮上传图像。我可以在感兴趣的区域 (ROI) 上绘制一个框,只要我用鼠标右键单击它,我就会打开一个小对话框。此对话框由具有两个页面的 TabWidget 组成。第一页有一个小的 QGraphicsView,它带有前一个框绘制的裁剪图像(比如图像 A)。 TabWidget 的第二页还有另一个 QGraphicsView,我用它来上传我桌面上以前保存的 .jpg 图像(比如图像 B)。一旦我点击确定,此对话框上的信息将被传输到 QTableView 的第一行。图像 A 将被放在一列中(准确地说是第 17 列),而图像 B 也将放在另一列中(准确地说是第 18 列)。

我能够将裁剪后的图像 A(这是最困难的部分,因为我必须努力理解 Qt 和 openCV 之间的转换格式,反之亦然)存储在 QTableView 但不是图像 B(我处理得很简单我保存在桌面上的图像)。

我尝试了不同的选项:选项 1:我创建了一个函数,用于处理我在 TabWidget(图像 B)的第二页上上传的图像,选项 2: 我尝试调试以缩小问题范围,但编译器似乎没有看到我要存储的图像。

我附上了带有此错误的代码中最重要的部分:

clipscene.h 中是我声明我使用的最重要的变量和函数的方式:

class clipScene : public QDialog

    Q_OBJECT
public:
    explicit clipScene(QWidget *parent = 0);
    ~clipScene();
    void setImage(QImage img);
    void setClassifiedImage(QImage img);
    SelectionData getData();
    void setData(SelectionData newdata);

private:
    SelectionData returnData;
    Ui::clipScene *ui;
    QImage simg;
    QImage featureClassified;
;

clipscene.cpp中这是我用来处理图像B的函数setClassifiedImage

 void clipScene::setClassifiedImage(QImage img)
    
        featureClassified = img;
        QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(featureClassified));
        workingImageScene->addItem(item);
    

clipscene.cpp中使用setImage我成功处理了裁剪图像的Qt和openCV转换

void clipScene::setImage(QImage img)

    simg = img;
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(simg));
    scene->addItem(item);
    ui->graphicsViewClipped->show();
    cv::Mat input = cv::Mat(simg.height(), simg.width(), CV_16UC3, simg.bits(), simg.bytesPerLine());
    // .....operations...
    // .....operations...

clipscene.cpp 中,以下img1 代表裁剪后的图像 A,img2 代表图像 B(当前也未存储,也未通过)

void clipScene::on_acceptBtn_clicked()

    // .....operations...
    // This will save the cropped Image A successfully
    QPixmap img1;
    img1.convertFromImage(simg);
    QByteArray img1Array;
    QBuffer buffer1(&img1Array);
    buffer1.open(QIODevice::WriteOnly);
    img1.save(&buffer1, "PNG");
    returnData.mSave = img1Array;

    // This will save a different Image B
    // But here the compiler says that no arguments are being passed
    QPixmap img2;
    QByteArray img2Array;
    QBuffer buffer2(&img2Array);
    buffer2.open(QIODevice::WriteOnly);
    img2.save(&buffer2, "PNG");
    returnData.mClassImg = img2Array;

最后,当所有信息都传递并存储在 QTableView 上时,我可以双击 QTableView 的一行,我之前用于手动存储数据的相同对话框将弹出,其中记录了所有信息和两个图像(图 A和图 B)。 在 MainWindow (以及连接错误的位置)上执行此操作的代码部分如下:

void MainWindow::onTableClick(const QModelIndex &index)

    int row = index.row();

    SelectionData currentData;
    currentData.mName = index.sibling(row, 1).data().toString();
    // ....additional data....
    // ....additional data...

    currentData.mSave = index.sibling(row, 17).data().toByteArray();
    currentData.mClassImg = index.sibling(row, 18).data().toByteArray();

    QPixmap iconPix;
    if(!iconPix.loadFromData(index.sibling(row, 17).data().toByteArray())) 
    
    QPixmap iconPix2;
    if(!iconPix2.loadFromData(index.sibling(row, 18).data().toByteArray())) 
    

    clipScene d(this);
    d.setData(currentData);
    d.setImage(iconPix.toImage());
    d.setClassifiedImage(iconPix2.toImage());

    // ....additional operations....

我已经为这个问题苦苦挣扎了几天,任何能对此有所了解或提供解决方案的人都会很棒。

【问题讨论】:

【参考方案1】:

我不确定这对您是否仍然有用,但由于我遇到了同样的问题,这可能会有所帮助。我认为您永远不会将图像传递给目标表。你有没有加载图像?你有没有做过这样的事情:

clipscene.h

private:
    QList<QGraphicsPixmapItem*> leftClipPix;

clipscene.cpp

void clipScene::load_classifiedImageFromDb(QImage image)

    clasImg = image;
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
    leftClipPix.append(item);
    workingImageScene->addItem(item);
    ui->yourgraphicsView->show();
    ui->yourgraphicsView->setSceneRect(QRectF(0, 0, image.width(), image.height()));

此外,如您所说,如果您尝试从桌面或数据库上传图像,那么执行以下操作可能会很有用:

void clipScene::load_classifiedImage()

    QString dir = QFileDialog::getOpenFileName(this, tr("Open image directory"), "", tr("Images (*.tif *.jpg *.png *.jpeg *.bmp *.gif *.tiff)"));
    QImage image;
    if(QString::compare(dir, QString()) != 0) 
        image = QImage(dir);
        QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
        leftClipPix.append(item);
        workingImageScene->addItem(item);
    
    ui->yourgraphicsView->show();
    ui->yourgraphicsView->setSceneRect(QRectF(0, 0, image.width(), image.height()));
    clasImg = image;


并将load_classifiedImage() 函数传递给QPushButton

【讨论】:

感谢您的回答,但我已经解决了这个问题。我会将您的答案标记为正确,因为我是按照您建议的方式进行的。

以上是关于如何在 QTableView 上存储图像(Qt 和 openCV)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Qt 的 QTableview 中找到我的按钮的行号

pyqt qt4 QTableView 如何禁用某些列的排序?

如何强制调整 indexWidgets 的大小以适合 Qt5 QTableView 的单元格

如何在 Qt 中使用 QFileSystemModel 设置文本颜色 QTableView?

QT中QTableView是怎么实现数字的排序

Qt:QTableView如何添加一行?