废话:

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

QT_BEGIN_NAMESPACE
namespaceUi {classMainWindow;
}
QT_END_NAMESPACE
class MainWindow : publicQMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget
*parent =nullptr);~MainWindow();voidupdateQLabelImage();

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, intval);publicslots:void horChange(intindex);void verChange(intindex);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(
newUi::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()
{
deleteui;
}
//更新QLabel里面的图像 voidMainWindow::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;caseQImage::Format_RGB888:
mat
= cv::Mat(img.height(), img.width(), CV_8UC3, (void*)img.constBits(), img.bytesPerLine());
cv::cvtColor(mat,mat,cv::COLOR_RGB2BGR);
break;caseQImage::Format_Indexed8:
mat
= cv::Mat(img.height(), img.width(), CV_8UC1, (void*)img.constBits(), img.bytesPerLine());break;
}
returnmat;
}

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);returnimage;
}
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, intval)
{
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(intindex)
{
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(intindex)
{
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

标签: none

添加新评论