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

news2024/11/17 2:39:49

仿射变换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); 
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1082731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式Linux裸机开发(七)UART串口、IIC、SPI通信

系列文章目录 文章目录 系列文章目录前言UART串口通信介绍UART配置 IIC介绍I.MX6U 的 I2C SPI介绍I.MX6U ECSPI 结语 前言 大概学完这三种通信后&#xff0c;之后就先去学系统移植&#xff0c;其他的先暂时放下 UART串口通信 介绍 串口全称叫做串行接口&#xff0c;通常也叫…

Maven创建父子工程详解

引言 在微服务盛行的当下&#xff0c;我们创建的工程基本都是父子工程&#xff0c;我们通过父工程来引入jar&#xff0c;定义统一的版本号等&#xff0c;这样我们在子工程中就可以直接引用后使用了&#xff0c;而不需要去重复的声明版本号等&#xff0c;这样会更方便对整个项目…

Linux中Locate命令查找不全

Locate locate(locate) 命令用来查找文件或目录。 locate命令要比find -name快得多&#xff0c;原因在于它不搜索具体目录&#xff0c;而是搜索一个数据库/var/lib/mlocate/mlocate.db 。这个数据库中含有本地所有文件信息。Linux系统会自动创建这个数据库&#xff0c;并且每天…

【ElasticSearch】深入探索 DSL 查询语法,实现对文档不同程度的检索,以及对搜索结果的排序、分页和高亮操作

文章目录 前言一、Elasticsearch DSL Query 的分类二、全文检索查询2.1 match 查询2.2 multi_match 查询 三、精确查询3.1 term 查询3.2 range 查询 四、地理坐标查询4.1 geo_bounding_box 查询4.2 geo_distance 查询 五、复合查询5.1 function score 查询5.2 boolean 查询 六、…

2023年中国溶瘤病毒药物上市产品、研发现状及行业市场规模前景[图]

溶瘤病毒&#xff08;Oncolyticvirus&#xff09;&#xff0c;是一类具有复制能力的肿瘤杀伤型病毒&#xff0c;溶瘤病毒根据所采用的毒株类型可以被分为天然病毒株&#xff08;野生型病毒株&#xff09;和基因改造病毒株两类&#xff0c;溶瘤病毒的种类也从最初的疱疹病毒发展…

使用c++视觉处理----canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测

使用c视觉处理canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测 #include <opencv2/opencv.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_GRAYSCALE); // 转为灰度图像if (image.empty()) {std::cerr << "无法加…

网络-网络状态网络速度

文章目录 前言一、网络状态二、网络速度 前言 本文主要记录如何监听网络状态和网络速度。 一、网络状态 获取当前网络状态: navigator.onLine // true:在线 false:离线监听事件&#xff1a;online&#xff08;联网&#xff09; 和 offline&#xff08;断网&#xff09; windo…

全国A级旅游景区清单数据(2023年更新)

全国A级旅游景区清单数据&#xff08;2023年更新&#xff09; 1.样本量&#xff1a;14847条 2.来源&#xff1a;政府公布资料 3.指标&#xff1a;景区名称、等级、所属省份、所属城市、所属区县、地址、当前等级评定时间、相关文件发布时间、坐标(GCJ02)Lng、坐标(GCJ02)Lat…

【Redis实战】分布式锁

分布式锁 synchronized只能保证单个JVM内部的线程互斥&#xff0c;不能保证集群模式下的多个JVM的线程互斥。 分布式锁原理 每个JVM内部都有自己的锁监视器&#xff0c;但是跨JVM&#xff0c;就会有多个锁监视器&#xff0c;就会有多个线程获取到锁&#xff0c;不能实现多JV…

分享一份关于 Rust 编程的学习指南

Rust是一种现代的系统级编程语言&#xff0c;以其注重内存安全、性能和并发性而闻名。学习Rust可以是一段有回报的旅程&#xff0c;为您打开构建强大高效应用的机会。无论您是经验丰富的开发者还是完全的初学者&#xff0c;本指南将通过精选的资源和技巧帮助您踏上Rust编程之旅…

【angular】实现简单的angular国际化(i18n)

文章目录 目标过程运行参考 目标 实现简单的angular国际化。本博客实现中文版和法语版。 将Hello i18n!变为中文版&#xff1a;你好 i18n!或法语版:Bonjour l’i18n !。 过程 创建一个项目&#xff1a; ng new i18nDemo在集成终端中打开。 添加本地化包&#xff1a; ng a…

景联文科技:3D点云标注应用场景和专业平台

3D点云技术之所以得到广泛发展和应用&#xff0c;主要是因为它能够以一种直观、真实和全面的方式来表示和获取现实世界中的三维信息。 3D点云的优势&#xff1a; 真实感和立体感&#xff1a;3D点云数据能够呈现物体的真实感和立体感&#xff0c;使观察者能够更直观地理解物体的…

Springboot整合阿里云OSS进行上传单个图片,多个图片,删除图片功能

1. 导入OSS依赖 <!-- 阿里云oss依赖 --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency> 2. 进行OSS配置 package com.example.sushe…

[GAMES101]透视投影变换矩阵中为什么需要改变z值

透视投影需要保证&#xff0c;1.变换矩阵内的元素是常数&#xff0c;2.相对深度值不变&#xff08;绝对值不重要&#xff09;&#xff1b;若再加上变换后zNear和zFar平面上的点依旧在zNear和zFar平面上这两个条件&#xff08;实际上并不一定需要满足这两个条件&#xff09;&…

机器人制作开源方案 | 扫地机器人

1. 功能描述 扫地机器人是现代家庭清洁的得力助手&#xff0c;能够自主规划清扫路径&#xff0c;避开障碍物&#xff0c;有效覆盖整个清洁区域。扫地机器人的出现极大地减轻了家庭清洁的负担&#xff0c;节省了时间和精力&#xff0c;它可以定期清理地面&#xff0c;确保家居环…

043:mapboxGL鼠标点击提示source属性信息

第043个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标点击提示source属性信息。这里用到了popup弹窗,用到了click事件,用到了鼠标样式的变化等功能。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

正点原子嵌入式linux驱动开发——Busybox根文件系统构建

前面已经移植了TF-A、Uboot和Linux kernel&#xff0c;就剩最后一个 rootfs(根文件系统)了&#xff0c;本章就来学习一下根文件系统的组成以及如何构建根文件系统。这是Linux系统移植的最后一步&#xff0c;根文件系统构建好以后就意味着拥有了一个完整的、可以运行的最小系统 …

【C语言】求解数独 求数独的解的个数 多解数独算法

目录 什么是数独&#xff1f; 数独的解法&#xff1f; 数独DFS算法详解 1. 初始化条件 2. 填入已初始化的数独表 3. 填数独 4. 拓展问题 请问删掉数独中的哪两个数可以使得数独的解最大&#xff1f; 删除的是哪两个数&#xff1f; 最终代码 main函数&#xff08;如何执行…

前端-uniapp-开发指南

美团外卖微信小程序开发 uniapp-美团外卖微信小程序开发P1 成果展示P2外卖小程序后端&#xff0c;学习给小程序写http接口P3 主界面配置P4 首页组件拆分P13 外卖列表布局筛选组件商家 布局测试数据创建样式 请求商家外卖数据封装请求并发请求 uni-app框架调用https接口 开发小程…

UE4和C++ 开发-C++绑定widget的方式和初始化UI

C绑定widget的方式有两种&#xff0c;一种是使用meta (BindWidget)&#xff0c;一种是使用GetWidgetFromName(TEXT("")),两种方式都可以。一、meta BindWidget方式 注意这种绑定的方式UMG里面的空间名称需要与C里面声明的变量名称相同 Btn_StartU 二、GetWidge…