首页 > 其他分享 >Qt加Opencv实现 梯度矫正 功能

Qt加Opencv实现 梯度矫正 功能

时间:2024-04-09 14:55:18浏览次数:24  
标签:矫正 Qt img Point dst height Opencv val width

废话:

有时候我们是从物品的斜上方拍摄的图片,看起来不直观,需要把视角拉正,这样的一个操作就叫做 梯度矫正,需要用到的技术是 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 <QMainWindow>
#include <QImage>
#include <QDebug>
#include <QtMath>

#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

 

标签:矫正,Qt,img,Point,dst,height,Opencv,val,width
From: https://www.cnblogs.com/shiyixirui/p/18123967

相关文章

  • MQTT基础
    1、MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议2、MQTT历史:MQTT协议最初版本是在1999年建立的。他们当时正在开发一个利用卫星通讯监控输油管道的项目。为了实现这个项目要求,他们需要开发一种用于嵌入式设备的通讯协议,这种通讯协议必须满足以下条件:易于实现数......
  • MQTT用python写的收消息例子
    在MQTT官网给的sub_wss.py例子中修改改写自己的用户名和密码BROKER='*******.ala.cn-hangzhou.emqxsl.cn'//改成自己的连接地址USERNAME='**************'//用户名PASSWORD='*************'//密码注意这句是改使用v1回调API(与旧版本的库一起使用)。原......
  • 【QT教程】QT6 QML编程
    QT6QML编程使用AI技术辅助生成QT界面美化视频课程QT性能优化视频课程QT原理与源码分析视频课程QTQMLC++扩展开发视频课程免费QT视频课程您可以看免费1000+个QT技术视频免费QT视频课程QT统计图和QT数据可视化视频免费看免费QT视频课程QT性能优化视频免费看免......
  • qt实现实时抓取串口数据,并对数据做解密处理
    效果:       1.实时抓取串口数据,并对串口数据做解密,解密后显示在QTextEdit上。       2.对显示的内容做特殊关键字标记处理,比如对出现的Error关键字标红               高亮另一个版本       3.对显示的明文进行查询,类似编辑文件中......
  • Qt中显示hex数据的控件
    效果类似QTextEdit,但是显示十六进制的数据,比如用于显示抓取串口或者bin文件的数据等等chunks.h#ifndefCHUNKS_H#defineCHUNKS_H/**\conddocNever*//*!TheChunksclassisthestoragebackendforQHexEdit.**WhenQHexEditloadsdata,Chunksaccessthe......
  • C++与Qt中回调函数的两种实现方法
    一.回调函数介绍1.概念回调函数是一种在程序运行期间通过函数指针调用的函数,它通常用于实现事件驱动、异步通信、消息传递等功能。在回调函数中,被调用的函数通常称为回调函数(CallbackFunction),而调用回调函数的函数通常称为回调函数容器(CallbackContainer)。回调函数容器可......
  • YOLOv5+PyQT5 果蔬识别检测可视化界面
    一、功能介绍界面里面可以选择图片检测与视频检测,可以用官方yolov5s模型训练出来的权重检测,也可以用自己改进的模型权重检测。二、界面展示三、项目介绍images存放的是界面需要的背景图片,runs存放的是已训练的模型权重,windows.py是运行文件,直接运行该文件即可。四、项......
  • tensorflow.js 如何使用opencv.js通过面部特征点估算脸部姿态并绘制示意图
    文章目录前言一、实现步骤1.获取所需特征点的索引2.使用opencv.js计算俯仰角、水平角和翻滚角cv.solvePnP介绍cv.solvePnP原理运行代码查看效果3.绘制姿态示意直线添加canvas元素计算姿态直线坐标并绘制总结前言在计算机视觉领域,估算脸部姿态是一项具有挑战性......
  • qt之函数重定义
    错误信息:/usr/bin/ld:rknnthread.o:infunction`rknnThread::~rknnThread()':***/rknnthread.cpp:14:multipledefinitionof`rknnThread::~rknnThread()';rknnthread.o:/***/rknnthread.cpp:14:firstdefinedhere/usr/bin/ld:rknnthread.o:infunction`rk......
  • PySide2-QThread创建、终止、暂停、继续、延时功能实现
    程序实现了一个能够显示0-99数字循环进度的功能,并提供了进度查看、暂停、继续及终止操作。importsysimporttimefromPySide2.QtCoreimport(QObject,QThread,Qt,Signal,QTimer,QCoreApplication,QEventLoop,Slot,)fromPy......