qt+opencv 使用 QOpencvWidget 便于快速测试的一个图片浏览器

  最近总感觉,日常开发时候,使用c++/opencv处理图片调试时候比较麻烦。跟Halcon或者matlab完全没法比,想实时调试效果太麻烦了。虽然windos下vs有个ImageWatch插件,勉强还能接受,但是ubuntu下,或者不用vs,就跟砍一只手一样。
  QOpencvWidget是我平时用来测试opencv效果的窗口,便于快速测试自己想法。

#ifndef QOPENCVWIDGET_H
#define QOPENCVWIDGET_H

/**
 * qt opencv widget
 * 试过各种图片浏览方式,感觉还是用现成的GraphicsView好一些
 * QOpencvPixmapItem、QOpencvScene、QOpencvView 便于快速实现自己交互
 */

// 01 Frame includes
#include "stable.h"

class QOpencvPixmapItem;
class QOpencvScene;
class QOpencvView;


class QOpencvWidget : public QWidget {
    Q_OBJECT
  public:
    explicit QOpencvWidget(QWidget *parent = nullptr);
    ~QOpencvWidget();
    void SetSurface(const QImage value);
    QImage GetSurface();
  private:
    void Initial();
  private:
    QGridLayout *gridLayout;
    QOpencvView *graphicsView;
    QOpencvPixmapItem  *opencv_pixmap_;
    QOpencvScene *opencv_scene_;
    QImage img_;
};


class QOpencvPixmapItem : public QGraphicsPixmapItem {
  public:
    explicit QOpencvPixmapItem(QGraphicsPixmapItem *parent = nullptr);
    ~QOpencvPixmapItem();
};

class QOpencvScene : public QGraphicsScene {
    Q_OBJECT
  public:
    explicit QOpencvScene(QGraphicsScene *parent = nullptr);
    ~QOpencvScene();
};

class QOpencvView : public QGraphicsView {
  public:
    explicit QOpencvView(QWidget *parent = nullptr);
    ~QOpencvView();
  protected:
    void wheelEvent(QWheelEvent *event);
};
#endif // QOPENCVWIDGET_H
// 01 Frame includes
#include "qopencvwidget.h"

QOpencvWidget::QOpencvWidget(QWidget *parent) :
    QWidget(parent) {
    this->Initial();
}

QOpencvWidget::~QOpencvWidget() {

}

void QOpencvWidget::SetSurface(const QImage value) {
    int tmp_height = img_.height() - value.height() ;
    int tmp_width = img_.width() - value.width();
    img_ = value;
    if (tmp_height > 0 || tmp_width > 0) {
        opencv_pixmap_->setOffset(tmp_width / 2, tmp_height / 2);
    } else if (tmp_height < 0 || tmp_width < 0) {
        opencv_pixmap_->setOffset(0, 0);
    }
    opencv_pixmap_->setPixmap(QPixmap::fromImage(img_));
}

QImage QOpencvWidget::GetSurface() {
    return img_;
}

void QOpencvWidget::Initial() {
    this->setObjectName(QStringLiteral("QOpencvWidget"));
    gridLayout = new QGridLayout(this);
    gridLayout->setContentsMargins(0, 0, 0, 0);
    graphicsView = new QOpencvView(this);
    gridLayout->addWidget(graphicsView);
    opencv_scene_ = new QOpencvScene;
    opencv_pixmap_ = new QOpencvPixmapItem;
    graphicsView->setScene(opencv_scene_);
    opencv_scene_->addItem(opencv_pixmap_);
    graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
    graphicsView->show();
}

QOpencvPixmapItem::QOpencvPixmapItem(QGraphicsPixmapItem *parent):
    QGraphicsPixmapItem(parent) {
}

QOpencvPixmapItem::~QOpencvPixmapItem() {

}
QOpencvScene::QOpencvScene(QGraphicsScene *parent):
    QGraphicsScene(parent) {
}

QOpencvScene::~QOpencvScene() {
}

QOpencvView::QOpencvView(QWidget *parent):
    QGraphicsView(parent) {
}

QOpencvView::~QOpencvView() {
}

void QOpencvView::wheelEvent(QWheelEvent *event) {
    if (event->delta() > 0) {
        this->scale(1.1, 1.1);
    } else {
        this->scale(0.9, 0.9);
    }
}

  使用方法如下,ImageBrowserManager::SlotImgProcess 改为自己的测试程序

#ifndef IMAGEBROWSERMANAGER_H
#define IMAGEBROWSERMANAGER_H
// 01 Frame includes
#include "stable.h"

// 03 OPENCV includes
#include "qopencvprocessing.h"
#include "qopencvwidget.h"

class ImageBrowserManager: public QObject {
    Q_OBJECT
  public:
    explicit ImageBrowserManager(QOpencvWidget &widget,
                                 QObject *parent = nullptr);
    virtual ~ImageBrowserManager() override;
    void OpenStlFile(const QString &file_path = "");
  public Q_SLOTS:
    void SlotImgProcess(const int &operation, const QString &text);
  Q_SIGNALS:
    void SignalPromptInformationOut(const QString &text);
  private:
    void Initial();
    void UnDo();
    void ReDo();
    void UpDataImage(const QImage);
  private:
    QOpencvWidget &widget_;
    QVector<QImage> img_vector_;	            // 存储图像的Vector容器
    QVector<QImage>::iterator imt_iter_;		// Vector迭代器
};
#endif // IMAGEBROWSERMANAGER_H
// 01 Frame includes
#include "imagebrowsermanager.h"
#include "quihelper.h"

// 06 Test includes
#include "readivus.h"
#include "mainwindow.h"
#include "formedgeadjustment.h"

ImageBrowserManager::ImageBrowserManager(QOpencvWidget &widget,
        QObject *parent) :
    QObject(parent), widget_(widget) {
    this->Initial();
}

ImageBrowserManager::~ImageBrowserManager() {

}

void ImageBrowserManager::Initial() {

}

void ImageBrowserManager::UnDo() {// 撤销
    if (imt_iter_ != img_vector_.begin()) {// 前面还有对象
        imt_iter_--;
        this->widget_.SetSurface(*imt_iter_);
        if (imt_iter_ == img_vector_.begin()) {// 自减为初始图像
            if (imt_iter_ != (img_vector_.end() - 1)) {
                img_vector_.erase(++imt_iter_, img_vector_.end());
            }
        }
    }
}

void ImageBrowserManager::ReDo() {// 重做
    if (imt_iter_ != img_vector_.end() && imt_iter_ != img_vector_.end() - 1) {
        // 后面还有对象
        imt_iter_++;
        this->widget_.SetSurface(*imt_iter_);
        if (imt_iter_ == (img_vector_.end())) {// 自加后是否为最后一个
        }
    }
}

void ImageBrowserManager::UpDataImage(const QImage tmp) {
    img_vector_.append(tmp);
    imt_iter_ = img_vector_.end() - 1;
    this->widget_.SetSurface(*imt_iter_);
}

void ImageBrowserManager::OpenStlFile(const QString &file_path) {
    QString tmp = file_path;
    QImage *img = new QImage();

    if (tmp.isEmpty()) {
        tmp = QUIHelper::GetFileName(
                  "*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm ");
    }
    if (!(img->load(tmp))) {
        QUIHelper::ShowMessageBoxError("打开图像失败!", 3, true);
        delete img;
        return;
    }
    this->widget_.SetSurface(*img);
    img_vector_.clear();
    img_vector_.append(*img);
    imt_iter_ = img_vector_.end() - 1;
    this->widget_.SetSurface(*imt_iter_);
}

void ImageBrowserManager::SlotImgProcess(const int &operation, const QString &text) {
    if (this->img_vector_.size() == 0) {
        emit SignalPromptInformationOut(("Image 数据错误"));
        return;
    }
    QString tmp_information = text;
    QStringList imformation = tmp_information.split("|");
    switch (operation) {
        case 1: {// 载入
                OpenStlFile();
                break;
            }
        case 2: {// 保存
                QImage img = QOpencvProcessing::Instance()->splitColor(
                                 widget_.GetSurface(),
                                 imformation.at(0).toLocal8Bit().data(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                break;
            }
        case 3: {// 撤销
                UnDo();
                break;
            }
        case 4: {// 重做
                ReDo();
                break;
            }
        case 101: {// 图像自适应大小
                emit SignalPromptInformationOut(("图像自适应大小"));
                break;
            }
        case 102: {// 改变大小
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Resize(
                    img, imformation.at(0).toInt(), imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("改变大小"));
                break;
            }
        case 103: {// 确认缩放
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Enlarge_Reduce(
                    img, imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认缩放"));
                break;
            }
        case 104: {// 确认旋转
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Rotate(img, imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认旋转"));
                break;
            }
        case 105: {// 确认线性变换
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Lean(
                    img, imformation.at(0).toInt(), imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认线性变换"));
                break;
            }
        case 106: {// 水平镜像
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Flip(img, 1);
                UpDataImage(img);
                emit SignalPromptInformationOut(("水平镜像"));
                break;
            }
        case 107: {// 垂直镜像
                QImage img = widget_.GetSurface();
                QOpencvProcessing::Instance()->Flip(img, 0);
                UpDataImage(img);
                emit SignalPromptInformationOut(("垂直镜像"));
                break;
            }
        case 201: {// 二值图像
                QImage img = QOpencvProcessing::Instance()->Bin(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("二值图像"));
                break;
            }
        case 202: {// 灰度图像
                QImage img = QOpencvProcessing::Instance()->Graylevel(
                                 widget_.GetSurface());
                UpDataImage(img);
                emit SignalPromptInformationOut(("灰度图像"));
                break;
            }
        case 203: {// 图像反转
                QImage img = QOpencvProcessing::Instance()->Reverse(
                                 widget_.GetSurface());
                UpDataImage(img);
                emit SignalPromptInformationOut(("图像反转"));
                break;
            }
        case 204: {// 确认线性变换
                QImage img = QOpencvProcessing::Instance()->Linear(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认线性变换"));
                break;
            }
        case 205: {// 确认对数变换
                QImage img = QOpencvProcessing::Instance()->Log(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认对数变换"));
                break;
            }
        case 206: {// 确认伽马变换
                QImage img = QOpencvProcessing::Instance()->Gamma(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("确认伽马变换"));
                break;
            }
        case 207: {// 直方图均衡化
                QImage img = QOpencvProcessing::Instance()->Histeq(
                                 widget_.GetSurface());
                UpDataImage(img);
                emit SignalPromptInformationOut(("直方图均衡化"));
                break;
            }
        case 301: {// 简单滤波
                QImage img = QOpencvProcessing::Instance()->Normalized(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("简单滤波"));
                break;
            }
        case 302: {// 高斯滤波
                QImage img = QOpencvProcessing::Instance()->Gaussian(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("高斯滤波"));
                break;
            }
        case 303: {// 中值滤波
                QImage img = QOpencvProcessing::Instance()->Median(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("中值滤波"));
                break;
            }
        case 304: {// sobel边缘检测
                QImage img = QOpencvProcessing::Instance()->Sobel(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("sobel边缘检测"));
                break;
            }
        case 305: {// laplacian边缘检测
                QImage img = QOpencvProcessing::Instance()->Laplacian(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("laplacian边缘检测"));
                break;
            }
        case 306: {// canny边缘检测
                QImage img = QOpencvProcessing::Instance()->Canny(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("canny边缘检测"));
                break;
            }
        case 307: {// line检测
                QImage img = QOpencvProcessing::Instance()->HoughLine(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt(),
                                 imformation.at(2).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut("line检测");
                break;
            }
        case 308: {// circle检测
                QImage img = QOpencvProcessing::Instance()->HoughCircle(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("circle检测"));
                break;
            }
        case 401: {// 腐蚀
                QImage img = QOpencvProcessing::Instance()->Erode(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt(),
                                 imformation.at(2).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("腐蚀"));
                break;
            }
        case 402: {// 膨胀
                QImage img = QOpencvProcessing::Instance()->Dilate(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt(),
                                 imformation.at(2).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("膨胀"));
                break;
            }
        case 403: {// 开运算
                QImage img = QOpencvProcessing::Instance()->Open(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt(),
                                 imformation.at(2).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("开运算"));
                break;
            }
        case 404: {// 闭运算
                QImage img = QOpencvProcessing::Instance()->Close(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt(),
                                 imformation.at(2).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("闭运算"));
                break;
            }
        case 405: {// 形态学梯度
                QImage img = QOpencvProcessing::Instance()->Grad(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("形态学梯度"));
                break;
            }
        case 406: {// 顶帽操作
                QImage img = QOpencvProcessing::Instance()->Tophat(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("顶帽操作"));
                break;
            }
        case 407: {// 黑帽操作
                QImage img = QOpencvProcessing::Instance()->Blackhat(
                                 widget_.GetSurface(),
                                 imformation.at(0).toInt(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("黑帽操作"));
                break;
            }

        case 501: {// 颜色模型
                QImage img = QOpencvProcessing::Instance()->splitColor(
                                 widget_.GetSurface(),
                                 imformation.at(0).toLocal8Bit().data(),
                                 imformation.at(1).toInt());
                UpDataImage(img);
                emit SignalPromptInformationOut(("颜色模型"));
                break;
            }
        case 601: {// 最短路径提取测试
                MainWindow *tmp = new MainWindow;
                tmp->OpenMinPathWidgetIn(widget_.GetSurface());
                break;
            }
        case 602: {// 边缘调整控件测试
                FormEdgeAdjustment *tmp = new FormEdgeAdjustment();
                tmp->showMaximized();
                break;
            }
        case 603: {// IVUS浏览控件
                ReadIVUS *tmp = new ReadIVUS();
                tmp->show();
                break;
            }
        default: {
                break;
            }
    }
}


发布了135 篇原创文章 · 获赞 68 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/a15005784320/article/details/103544756