若该文为原创文章,未经允许不得转载
原博主博客地址: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开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》
下一篇:《OpenCV开发笔记(四十七):红胖子8分钟带你深入了解直方图(图文并茂+浅显易懂+程序源码)》
红胖子来也!!!
图像处理中的仿射,仿射其实原理与重映射类似,其可以理解为更高级的重映射变换。
《OpenCV开发笔记(八):OpenCV常用操作之计时、缩放、旋转、镜像》
该文章中,也同样实现了部分简单重映射效果,使用的四个函数:
《OpenCV开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》
仿射变换(仿射映射)是指在几何中,一个响亮空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。
一个任意的仿射都能表示为乘以一个矩阵再加上一个向量(平移)的形式(注:重映射可以理解为是一种简单的仿射变换)。
仿射是用矩阵表示变换的关系,通常使用的是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());
Mat getAffineTransform( InputArray src,
InputArray dst );
Mat getRotationMatrix2D( Point2f center,
double angle,
double scale );
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
上一篇:《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