c++视觉处理---仿射变换和二维旋转变换矩阵的函数

2023-10-12 05:12

本文主要是介绍c++视觉处理---仿射变换和二维旋转变换矩阵的函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

仿射变换cv::warpAffine

cv::warpAffine 是OpenCV中用于执行仿射变换的函数。仿射变换是一种线性变换,可用于执行平移、旋转、缩放和剪切等操作。下面是 cv::warpAffine 函数的基本用法:

cv::warpAffine(src, dst, M, dsize, flags, borderMode, borderValue);
  • src: 输入图像。
  • dst: 输出图像,用于存储仿射变换后的结果。
  • M: 2x3仿射变换矩阵,包含变换的参数。
  • dsize: 输出图像的尺寸。
  • flags: 插值方法,通常使用
    • cv::INTER_LINEAR 进行双线性插值。
    • cv::INTER_NEAREST 最近邻插值
    • cv::INTER_AREA 区域插值
    • cv::INTER_CUBIC 三次样条插值
    • cv::INTER_LANCZOS4 Lanczos插值
    • cv::CV_WARP_FILL_OUTLIERS 填充所有输出图像的象素。如果部分象素落在输入图像的边界 外,那么它们的值设定为 fillval
    • cv::CV_WARP_INVERSE_MAP 表示 M为输出图像到输入图像的反变换。因此可以直接用来做 象素插值。否则,warpAffine函数从M矩阵得到反变换
  • borderMode: 边界模式,可选参数,定义当像素越出图像边界时的处理方式,通常使用 cv::BORDER_CONSTANTcv::BORDER_REPLICATE
  • borderValue: 当 borderModecv::BORDER_CONSTANT 时使用,用于指定图像边界外的像素值。

通过提供仿射变换矩阵 M,您可以指定图像的变换方式,包括平移、旋转、缩放和剪切等。然后,cv::warpAffine 函数会根据给定的变换参数将输入图像进行变换,输出结果保存在 dst 中。

以下是一个简单的示例,演示如何使用 cv::warpAffine 进行图像的平移操作:

#include <opencv2/opencv.hpp>int main() {cv::Mat image = cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "无法加载图像" << std::endl;return -1;}// 定义仿射变换矩阵(平移操作)cv::Mat warpMatrix = (cv::Mat_<double>(2, 3) << 1, 0, 50, 0, 1, 30);cv::Mat result;// 应用仿射变换cv::warpAffine(image, result, warpMatrix, image.size());cv::imshow("原始图像", image);cv::imshow("仿射变换后的图像", result);cv::waitKey(0);return 0;
}

在这个示例中,我们定义了一个仿射变换矩阵 warpMatrix,该矩阵包含平移操作的参数。然后,我们使用 cv::warpAffine 函数将变换应用于原始图像,生成了变换后的结果。您可以根据需要修改 warpMatrix 中的值以实现不同的仿射变换效果。
在这里插入图片描述

二维旋转变换矩阵的函数:cv::getRotationMatrix2D

cv::getRotationMatrix2D 是OpenCV中用于获取二维旋转变换矩阵的函数。这个函数用于构造一个仿射变换矩阵,该矩阵用于执行二维图像的旋转操作。下面是 cv::getRotationMatrix2D 函数的基本用法:

cv::Mat cv::getRotationMatrix2D(cv::Point2f center, double angle, double scale);
  • center: 旋转中心的坐标,通常是旋转图像的中心点。
  • angle: 旋转的角度(以度为单位)。
  • scale: 缩放因子,通常设置为1.0。

函数返回一个2x3的仿射变换矩阵,该矩阵包含了旋转和缩放的参数。

以下是一个示例,演示如何使用 cv::getRotationMatrix2D 函数构造旋转变换矩阵,然后应用该变换矩阵来旋转图像:

#include <opencv2/opencv.hpp>int main() {cv::Mat image = cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "无法加载图像" << std::endl;return -1;}// 旋转中心坐标cv::Point2f center(image.cols / 2.0, image.rows / 2.0);// 旋转角度(以度为单位)double angle = 30;// 缩放因子double scale = 1.0;// 获取旋转变换矩阵cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, scale);cv::Mat result;// 应用仿射变换cv::warpAffine(image, result, rotationMatrix, image.size());cv::imshow("原始图像", image);cv::imshow("旋转后的图像", result);cv::waitKey(0);return 0;
}

在这个示例中,我们使用 cv::getRotationMatrix2D 函数获取旋转变换矩阵,然后将该变换矩阵应用于原始图像,以实现旋转效果。您可以根据需要调整 centeranglescale 参数来执行不同的旋转和缩放操作。

在这里插入图片描述

综合案例

#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace std;
using namespace cv;
#include <iostream>
#include <fstream>
using namespace cv; //包含cv命名空间
#include <opencv2/core/core.hpp>
#define WINDOW_NAME1 " 【原始图窗口】 " //为窗口标题定义的宏
#define WINDOW_NAME2 " 【经过 Warp后的图像】 " //为窗口标题定义的宏
#define WINDOW_NAME3 " 【经过 Warp和 Rotate后的图像】 " //为窗口标题定
static void ShowHelpText();
/// 【main()函数】-------------------------- -
// 描述: 控制台应用程序的入口函数, 我们的程序从这里开始执行
int main()
{//【0】改变 console字体颜色system("color 1A");//【0】显示欢迎和帮助文字ShowHelpText();//【1】参数准备//定义两组点, 代表两个三角形Point2f srcTriangle[3];Point2f dstTriangle[3];//定义一些 Mat变量Mat rotMat(2, 3, CV_32FC1);Mat warpMat(2, 3, CV_32FC1);Mat srcImage, dstImage_warp, dstImage_warp_rotate;//【2】加载源图像并作一些初始化srcImage = imread("1.jpg", 1);if (!srcImage.data) { printf("读取图片错误, 请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }// 设置目标图像的大小和类型与源图像一致dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());//【3】设置源图像和目标图像上的三组点以计算仿射变换srcTriangle[0] = Point2f(0, 0);srcTriangle[1] = Point2f(static_cast<float>(srcImage.cols - 1), 0);srcTriangle[2] = Point2f(0, static_cast<float>(srcImage.rows - 1));dstTriangle[0] = Point2f(static_cast<float>(srcImage.cols * 0.0), static_cast<float>(srcImage.rows * 0.33));dstTriangle[1] = Point2f(static_cast<float>(srcImage.cols * 0.65), static_cast<float>(srcImage.rows * 0.35));dstTriangle[2] = Point2f(static_cast<float>(srcImage.cols * 0.15), static_cast<float>(srcImage.rows * 0.6));//【4】求得仿射变换warpMat = getAffineTransform(srcTriangle, dstTriangle);//【5】对源图像应用刚刚求得的仿射变换warpAffine(srcImage, dstImage_warp, warpMat, dstImage_warp.size());//【6】对图像进行缩放后再旋转// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);double angle = -30.0;double scale = 0.8;// 通过上面的旋转细节信息求得旋转矩阵rotMat = getRotationMatrix2D(center, angle, scale);// 旋转已缩放后的图像warpAffine(dstImage_warp, dstImage_warp_rotate, rotMat, dstImage_warp.size());//【7】显示结果imshow(WINDOW_NAME1, srcImage);imshow(WINDOW_NAME2, dstImage_warp);imshow(WINDOW_NAME3, dstImage_warp_rotate);// 等待用户按任意按键退出程序waitKey(0);return 0;
}
//一 【ShowHelpText()函数】---------------------- -
// 描述: 输出一些帮助信息
static void ShowHelpText()
{//输出一些帮助信息printf("\n\n\n\t欢迎来到【仿射变换】示例程序~ \n\n");//printf("\t当前使用的OpenCV版本为 OpenCV "CV_VERSION); 
}

在这里插入图片描述

这篇关于c++视觉处理---仿射变换和二维旋转变换矩阵的函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/193503

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言