• Qt加Opencv实现 梯度矫正 功能


    废话:

    有时候我们是从物品的斜上方拍摄的图片,看起来不直观,需要把视角拉正,这样的一个操作就叫做 梯度矫正,需要用到的技术是 Opencv 的 透视变换。

    这个只是一个简单的演示demo,如果完善一下,比如物品检测,可以应用更多的场景,比如常见的:文件、资料上传,软管摄像头的应用等,怎么说也是一个技术点吧

     

    重要代码:

    复制代码
    /**
    * @brief hDLL_gradientAuto 梯度矫正
    * @param src  输入图像
    * @param dst  输出图像
    * @param flag 方向,[0(左),1(上),2(右),3(下)]
    * @param val  矫正度数,像素,[10 ~ 100]
    * @return 0(成功),-1(失败)
    */ 
    int MainWindow::hDLL_gradientAuto(Mat &src, Mat &dst, int flag, int val)
    {
        if(flag != 0 && flag != 1 && flag != 2 && flag != 3) return -1;
        if(val < 10 || val > 100) return -1;
    
        int width = src.cols;
        int height = src.rows;
        Mat M;
        // flag 方向,[0(左),1(上),2(右),3(下)]
        switch (flag) {
        case 0:
        {
            Point2f pts_src[] = { Point(val,val), Point(width, 0), Point(width, height), Point(val, height-val)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 1:
        {
            Point2f pts_src[] = { Point(val,val), Point(width-val, val), Point(width, height), Point(0, height)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 2:
        {
            Point2f pts_src[] = { Point(0,0), Point(width-val, val), Point(width-val, height-val), Point(0, height)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 3:
        {
            Point2f pts_src[] = { Point(0,0), Point(width, 0), Point(width-val, height-val), Point(val, height-val)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        }
    
        cv::warpPerspective(src, dst, M, dst.size(), cv::INTER_LINEAR , cv::BORDER_REPLICATE);
        return 0;
    }
    复制代码

     

     

    Demo演示:

     

    完整代码:

    .h

    复制代码
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include 
    #include 
    #include 
    
    #include "opencv2/opencv.hpp"
    using namespace cv;
    
    QT_BEGIN_NAMESPACE
    namespace Ui {
    class MainWindow;
    }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
        void updateQLabelImage();
    
        Mat QImage2Mat(QImage &img);
        QImage Mat2QImage(Mat &img);
    
        /**
         * @brief hDLL_gradientAuto 梯度矫正
         * @param src  输入图像
         * @param dst  输出图像
         * @param flag 方向,[0(左),1(上),2(右),3(下)]
         * @param val  矫正度数,像素,[10 ~ 100]
         * @return 0(成功),-1(失败)
         */
        int hDLL_gradientAuto(Mat &src, Mat &dst, int flag, int val);
    
    public slots:
        void horChange(int index);
        void verChange(int index);
    
    private:
        Ui::MainWindow *ui;
    
        QImage m_img;       // 原图
        QImage m_img_dst;   // 处理过的图像
    };
    #endif // MAINWINDOW_H
    复制代码

     

    .cpp

    复制代码
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(horChange(int)));
        connect(ui->verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(verChange(int)));
    
        m_img = QImage("F:1.jpg");
        m_img_dst = m_img;
        updateQLabelImage();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    // 更新QLabel里面的图像
    void MainWindow::updateQLabelImage()
    {
        // m_img = m_img.scaled(ui->label->width(), ui->label->height());
        QImage img_show = m_img_dst.scaled(ui->label->width(), ui->label->height());
        ui->label->setPixmap(QPixmap::fromImage(img_show));
    }
    
    Mat MainWindow::QImage2Mat(QImage &img)
    {
        cv::Mat mat;
        switch (img.format())
        {
        case QImage::Format_RGB32:  //一般Qt读入彩色图后为此格式
            mat = cv::Mat(img.height(), img.width(), CV_8UC4, (void*)img.constBits(), img.bytesPerLine());
            cv::cvtColor(mat,mat,cv::COLOR_BGRA2BGR);   //转3通道
            break;
        case QImage::Format_RGB888:
            mat = cv::Mat(img.height(), img.width(), CV_8UC3, (void*)img.constBits(), img.bytesPerLine());
            cv::cvtColor(mat,mat,cv::COLOR_RGB2BGR);
            break;
        case QImage::Format_Indexed8:
            mat = cv::Mat(img.height(), img.width(), CV_8UC1, (void*)img.constBits(), img.bytesPerLine());
            break;
        }
        return mat;
    }
    
    QImage MainWindow::Mat2QImage(Mat &img)
    {
        if(img.type()==CV_8UC1 || img.type()==CV_8U)
        {
            QImage image((const uchar *)img.data, img.cols, img.rows, img.step, QImage::Format_Grayscale8);
            return image;
        }
        else if(img.type()==CV_8UC3)
        {
            QImage image((const uchar *)img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
            return image.rgbSwapped();  //r与b调换
        }
    }
    
    int MainWindow::hDLL_gradientAuto(Mat &src, Mat &dst, int flag, int val)
    {
        if(flag != 0 && flag != 1 && flag != 2 && flag != 3) return -1;
        if(val < 10 || val > 100) return -1;
    
        int width = src.cols;
        int height = src.rows;
        Mat M;
        // flag 方向,[0(左),1(上),2(右),3(下)]
        switch (flag) {
        case 0:
        {
            Point2f pts_src[] = { Point(val,val), Point(width, 0), Point(width, height), Point(val, height-val)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 1:
        {
            Point2f pts_src[] = { Point(val,val), Point(width-val, val), Point(width, height), Point(0, height)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 2:
        {
            Point2f pts_src[] = { Point(0,0), Point(width-val, val), Point(width-val, height-val), Point(0, height)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        case 3:
        {
            Point2f pts_src[] = { Point(0,0), Point(width, 0), Point(width-val, height-val), Point(val, height-val)};
            Point2f pts_dst[] = { Point(0, 0), Point(width, 0), Point(width, height) ,Point(0, height) };
            M = cv::getPerspectiveTransform(pts_src, pts_dst);
        }break;
        }
    
        cv::warpPerspective(src, dst, M, dst.size(), cv::INTER_LINEAR , cv::BORDER_REPLICATE);
        return 0;
    }
    
    // 横向改变
    void MainWindow::horChange(int index)
    {
        qDebug() << "hor:" << index;
    
        if(index == 0)
        {
            m_img_dst = m_img;
        }
        else if(index < 0)
        {
            int val = abs(index) * 10;
            Mat src = QImage2Mat(m_img);
            Mat dst;
            hDLL_gradientAuto(src, dst, 0, val);
            m_img_dst = Mat2QImage(dst);
        }
        else if (index > 0)
        {
            int val = abs(index) * 10;
            Mat src = QImage2Mat(m_img);
            Mat dst;
            hDLL_gradientAuto(src, dst, 2, val);
            m_img_dst = Mat2QImage(dst);
        }
        updateQLabelImage();
    }
    
    // 竖向改变
    void MainWindow::verChange(int index)
    {
        qDebug() << "ver:" << index;
    
        if(index == 0)
        {
            m_img_dst = m_img;
        }
        else if(index < 0)
        {
            int val = abs(index) * 10;
            Mat src = QImage2Mat(m_img);
            Mat dst;
            hDLL_gradientAuto(src, dst, 3, val);
            m_img_dst = Mat2QImage(dst);
        }
        else if (index > 0)
        {
            int val = abs(index) * 10;
            Mat src = QImage2Mat(m_img);
            Mat dst;
            hDLL_gradientAuto(src, dst, 1, val);
            m_img_dst = Mat2QImage(dst);
        }
    
        updateQLabelImage();
    }
    复制代码

     

     

     

    代码下载:

    我的环境是:Qt 5.15.2 + Opencv V4.8.0,如果需要下载代码,自己调试,自己配置环境即可

    代码仓库:https://gitee.com/vvvj/qt-test-gradient-auto

     

  • 相关阅读:
    Rust基本数据类型-字符串
    《VS2013+ Qt5.6 创建Qt对话框(*.ui 文件, *.h, *.cpp )》
    详解JS——垃圾回收的原理
    【算法】单调队列
    嵌入式 新建基于固件库的MDK5工程模板
    含文档+PPT+源码等]精品微信小程序在线考试系统+后台管理系统|前后分离VUE[包运行成功]微信小程序毕业设计项目源码计算机毕设
    050_阵列天线方向图乘积原理
    brew安装特定版本flow,解决问题!
    postgresql数据库备份
    Software caused connection abort: recv failed
  • 原文地址:https://www.cnblogs.com/shiyixirui/p/18123967