若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105691534
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
OpenCV开发专栏(点击传送门)
上一篇:《OpenCV开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(四十七):红胖子8分钟带你深入了解直方图(图文并茂+浅显易懂+程序源码)》
前言
红胖子来也!!!
图像处理中的仿射,仿射其实原理与重映射类似,其可以理解为更高级的重映射变换。
相关博客
《OpenCV开发笔记(八):OpenCV常用操作之计时、缩放、旋转、镜像》
该文章中,也同样实现了部分简单重映射效果,使用的四个函数:
- 旋转函数1:cv::transpose,直接对矩阵进行顺时钟旋转90°
- 旋转函数2:cv::rotate,三个枚举可以旋转90°,180°,270°
- 翻转函数:cv::flip,xy轴翻转
- 缩放函数:cv::resize,缩放
《OpenCV开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》
Demo
仿射变换
概述
仿射变换(仿射映射)是指在几何中,一个响亮空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。
一个任意的仿射都能表示为乘以一个矩阵再加上一个向量(平移)的形式(注:重映射可以理解为是一种简单的仿射变换)。
- 旋转:rotation,线性变换;
- 平移:translation,向量加;
- 缩放,scale,线性变换;
原理
仿射是用矩阵表示变换的关系,通常使用的是2 x 3的矩阵来表示仿射变换。
整个映射关系为:
dst = src * A + B
其中:
A为线性变换矩阵,B为向量加矩阵;
对应的每个像素的变换关系,则是:
dst(x,y) = src(x,y) * A + B
下面上图解释仿射(三个点就是函数提供计算仿射矩阵需要我们输入的点):
与重映射原理区别
仿射变换的原理与重映射不同,重映射是直接对像素点的序号进行映射,可以做些拉长,特点像素着重等等(如哈哈镜),而仿射变换是对原矩阵的标准变换,有适合各自的场景。
-
void warpAffine( InputArray src,
-
OutputArray dst,
-
InputArray M,
-
Size dsize,
-
int flags = INTER_LINEAR,
-
int borderMode = BORDER_CONSTANT,
-
const Scalar& borderValue = Scalar());
- 参数一:InputArray类型的src,一般为cv::Mat;
- 参数二:OutputArray类型的dst,目标图像。它的大小、类型与src相同。
- 参数三:InputArray类型的M,即变换矩阵,大小为2 x 3。
- 参数四:Size类型的size,表示输出图像的尺寸;
- 参数五:int类型的interpolation,使用的插值方法;
- 参数六:int类型的borderMode,边界处理方式;
- 参数七:Scalar类型的borderValue,重映射后,离群点的背景,需要broderMode设置为BORDER_CONSTRANT时才有效。
计算二维三角变换矩阵函数原型
-
Mat getAffineTransform( InputArray src,
-
InputArray dst );
- 参数一:InputArray类型的src,原来三个点的坐标;
- 参数二:OutputArray类型的dst,映射后三个点的坐标;
计算二维旋转变换矩阵函数原型
-
Mat getRotationMatrix2D( Point2f center,
-
double angle,
-
double scale );
- 参数一:Point2f类型的center,输入的旋转中心点;
- 参数二:double类型的angle,旋转的角度(逆时针旋转角度,非弧度);
- 参数三:double类型的scale,缩放系数;
Demo源码
-
void OpenCVManager::testAffineMap()
-
{
-
QString fileName1 =
-
"E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
-
cv::Mat srcMat = cv::imread(fileName1.toStdString());
-
cv::Mat dstMat;
-
int width =
400;
-
int height =
300;
-
-
cv::resize(srcMat, srcMat, cv::Size(width, height));
-
-
cv::String windowName = _windowTitle.toStdString();
-
cvui::init(windowName);
-
-
cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols *
2,
-
srcMat.rows *
4),
-
srcMat.type());
-
-
while(
true)
-
{
-
windowMat = cv::Scalar(
0,
0,
0);
-
-
cv::Mat mat = windowMat(cv::Range(srcMat.rows *
0, srcMat.rows *
1),
-
cv::Range(srcMat.cols *
0, srcMat.cols *
1));
-
cv::addWeighted(mat,
0.0f, srcMat,
1.0f,
0.0f, mat);
-
-
// 第一种旋转180度
-
{
-
cv::Mat M = cv::getRotationMatrix2D(cv::Point(srcMat.cols /
2,
-
srcMat.rows /
2),
-
180.0f,
-
1.0f);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
0, srcMat.rows *
1),
-
cv::Range(srcMat.cols *
1, srcMat.cols *
2));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
-
// 第二种旋转45度,缩小1/2
-
{
-
cv::Mat M = cv::getRotationMatrix2D(cv::Point(srcMat.cols /
2,
-
srcMat.rows /
2),
-
45.0f,
-
0.5f);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
1, srcMat.rows *
2),
-
cv::Range(srcMat.cols *
0, srcMat.cols *
1));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 第三种旋转315度,缩小1/2
-
{
-
cv::Mat M = cv::getRotationMatrix2D(cv::Point(srcMat.cols /
2,
-
srcMat.rows /
2),
-
315.0f,
-
0.5f);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
1, srcMat.rows *
2),
-
cv::Range(srcMat.cols *
1, srcMat.cols *
2));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 第四种旋转135度,缩小1/2
-
{
-
cv::Mat M = cv::getRotationMatrix2D(cv::Point(srcMat.cols /
2,
-
srcMat.rows /
2),
-
135.0f,
-
0.5f);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
2, srcMat.rows *
3),
-
cv::Range(srcMat.cols *
0, srcMat.cols *
1));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 第五种旋转225度,缩小1/2
-
{
-
cv::Mat M = cv::getRotationMatrix2D(cv::Point(srcMat.cols /
2,
-
srcMat.rows /
2),
-
225.0f,
-
0.5f);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
2, srcMat.rows *
3),
-
cv::Range(srcMat.cols *
1, srcMat.cols *
2));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 第六种使用三角点进行仿射变换,沿着对角线翻转
-
{
-
cv::Point2f srcTraingle[
3];
-
cv::Point2f dstTraingle[
3];
-
srcTraingle[
0] = cv::Point2f(
0,
0);
-
srcTraingle[
1] = cv::Point2f(srcMat.cols -
1,
0);
-
srcTraingle[
2] = cv::Point2f(
0, srcMat.rows -
1);
-
dstTraingle[
0] = cv::Point2f(
0,
0);
-
dstTraingle[
1] = cv::Point2f(
0, srcMat.rows -
1);
-
dstTraingle[
2] = cv::Point2f(srcMat.cols -
1,
0);
-
-
cv::Mat M = cv::getAffineTransform(srcTraingle, dstTraingle);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
3, srcMat.rows *
4),
-
cv::Range(srcMat.cols *
0, srcMat.cols *
1));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 第七种使用三角点进行仿射变换
-
{
-
cv::Point2f srcTraingle[
3];
-
cv::Point2f dstTraingle[
3];
-
srcTraingle[
0] = cv::Point2f(
0,
0);
-
srcTraingle[
1] = cv::Point2f(srcMat.cols -
1,
0);
-
srcTraingle[
2] = cv::Point2f(
0, srcMat.rows -
1);
-
dstTraingle[
0] = cv::Point2f(srcMat.cols /
4, srcMat.rows /
4);
-
dstTraingle[
1] = cv::Point2f(srcMat.cols /
4 *
3, srcMat.rows /
4 );
-
dstTraingle[
2] = cv::Point2f(srcMat.cols /
2, srcMat.rows -
1);
-
-
cv::Mat M = cv::getAffineTransform(srcTraingle, dstTraingle);
-
dstMat = srcMat.clone();
-
dstMat = cv::Scalar(
0,
0,
0);
-
cv::warpAffine(srcMat, dstMat, M, cv::Size(srcMat.cols, srcMat.rows));
-
mat = windowMat(cv::Range(srcMat.rows *
3, srcMat.rows *
4),
-
cv::Range(srcMat.cols *
1, srcMat.cols *
2));
-
cv::addWeighted(mat,
0.0f, dstMat,
1.0f,
0.0f, mat);
-
}
-
// 更新
-
cvui::update();
-
// 显示
-
cv::imshow(windowName, windowMat);
-
// esc键退出
-
if(cv::waitKey(
25) ==
27)
-
{
-
break;
-
}
-
}
-
}
工程模板:对应版本号v1.41.0
对应版本号v1.41.0
上一篇:《OpenCV开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(四十七):红胖子8分钟带你深入了解直方图(图文并茂+浅显易懂+程序源码)》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105691534
转载:https://blog.csdn.net/qq21497936/article/details/105691534