用OpenCV库可实现将图片旋转任意角度,以及放大、缩小功能。本例应用OpenCV库来实现对图片的任意旋转、缩放功能。
1.程序界面
创建一个Qt桌面应用程序项目,项目名称为“OpencvScaleRotate”,设计程序界面如图所示。
2.全局变量及方法
为了提高程序代码的使用效率,通常建议将程序中公用的图片对象的句柄声明为全局变量,通用的方法声明为公有(public)方法,定义在项目.h头文件中。
“mainwindow.h”头文件,代码如下:
#include <QMainWindow>
#include "opencv2/opencv.hpp" //OpenCV包含文件
using namespace cv; //OpenCV 命名空间
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initMainWindow();//界面初始化
void imgProc(float angle, float scale); //处理图片
void imgShow(); //显示图片
private slots:
void on_sliderScale_sliderMoved(int position);//缩放滑条拖曳槽
void on_sliderScale_valueChanged(int value);//缩放滑条值改变槽
void on_sliderRotate_sliderMoved(int position);//旋转滑条拖曳槽
void on_sliderRotate_valueChanged(int value);//旋转滑条值改变槽
private:
Ui::MainWindow *ui;
Mat myImg;//缓存图片(供程序代码引用和处理)
QImage myQImg; //保存图片(可转为文件存盘或显示)
};
3.初始化显示
首先在Qt界面上显示待处理的图片,在构造方法中添加如下代码:
初始化方法initMainWindow()的代码为:
void MainWindow::initMainWindow()
{
QString imgPath = "lake.jpg"; //本地路径(将图片直接存放在项目目录下)
Mat imgData = imread (imgPath.toLatin1().data()); //读取图片数据
cvtColor(imgData, imgData, COLOR_BGR2RGB); //图片格式转换
myImg = imgData;
myQImg = QImage((const unsigned char*)(imgData.data), imgData.cols, imgData.rows, QImage::Format_RGB888);
imgShow(); //显示图片
}
显示图片的imgShow()方法中只有一句:
void MainWindow::imgShow()
{
ui->labView->setPixmap(QPixmap::fromImage(
myQImg.scaled(ui->labView->size(), Qt::KeepAspectRatio))); //在 Qt 界面上显示图片
}
4.功能实现
图片旋转和缩放处理功能写在imgProc()方法中,该方法接收2个参数,皆为单精度实型,ang表示旋转角度(正为顺时针、负为逆时针),sea表示缩放率(大于1为放大、小于1为缩小),实现代码为:
void MainWindow::imgProc(float ang, float sea)
{
Point2f srcMatrix[3];
Point2f dstMatrix[3];
Mat imgRot(2, 3, CV_32FC1);
Mat imgSrc = myImg;
Mat imgDst;
Point centerPoint = Point(imgSrc.cols / 2, imgSrc.rows / 2);
//计算原图片的中心点
imgRot = getRotationMatrix2D(centerPoint, ang, sea); //(a)
//根据角度和缩放参数求得旋转矩阵
warpAffine(imgSrc, imgDst, imgRot, imgSrc.size()); //执行旋转操作
myQImg=QImage((const unsigned char*)(imgDst.data),
imgDst.cols, imgDst.rows, QImage::Format_RGB888);
imgShow();
}
其中,
- (a) imgRot = getRotationMatrix2D(centerPoint, ang, sea): OpenCV内部用仿射变换算法来实现图片的旋转缩放。它需要3个参数:①旋转图片所要围绕的中心;②旋转的角度,在OpenCV中逆时针角度为正值,反之为负值;③缩放因子(可选),在本例中分别对应centerPoint、ang和sea参数值。任何一个仿射变换都能表示为向量乘以一个矩阵(线性变换)再加上另一个向量(平移),研究表明,不论是对图片的旋转还是缩放操作,本质上都是对其每个像素施加了某种线性变换,如果不考虑平移,实际上也就是一个仿射变换。因此,变换的关键在于求出变换矩阵,这个矩阵实际上代表了变换前后两张图片之间的关系。这里用OpenCV的getRotationMatrix2D()方法来获得旋转矩阵,然后通过warpAffine()方法将所获得的矩阵用到对图片的旋转缩放操作中。
5.界面事件响应
最后,为使界面上的滑条响应用户操作,还要编写事件过程代码如下:
void MainWindow::on_sliderScale_sliderMoved(int position)
{
imgProc(float(ui->sliderRotate->value()-360), position/100.0);
}
void MainWindow::on_sliderScale_valueChanged(int value)
{
imgProc(float(ui->sliderRotate->value()-360), value/100.0);
}
void MainWindow::on_sliderRotate_sliderMoved(int position)
{
imgProc(float(position-360), ui->sliderScale->value()/100.0);
}
void MainWindow::on_sliderRotate_valueChanged(int value)
{
imgProc(float(value-360), ui->sliderScale->value()/100.0);
}
这样,当用户拖动或单击滑条就能实时地根据滑条当前所指的参数来变换图片。
6.运行效果
运行程序,界面上显示出初始图片,如下图所示。
用鼠标拖曳右侧滑条,可将图片放大或缩小,如下图所示。
接着,用鼠标拖曳下方滑条,可对图片做任意方向和角度的旋转,如下图所示。
————————————————
觉得有用的话请关注点赞,谢谢您的支持!
对于本系列文章相关示例完整代码有需要的朋友,可关注并在评论区留言!