opencv仿射变换

#include <opencv2/opencv.hpp>

/*
功能:对一系列坐标点进行平移仿射变换
参数:
srcPoints:输入点坐标
dstPoints:变换后的点坐标
x:x方向平移的距离
y:y方向平移的距离
*/
void tranlatePoints(std::vector<cv::Point2f>& srcPoints, std::vector<cv::Point2f>& dstPoints,double x,double y)
{
    cv::Mat affineMatrix = (cv::Mat_<double>(2, 3) << 1, 0, x, 0, 1,y);
    cv::transform(srcPoints, dstPoints, affineMatrix);
}

/*
功能:对一系列点进行旋转仿射变换
参数:
srcPoints:输入点坐标
dstPoints:变换后的点坐标
basePoint:旋转基准点
zoomRate:缩放比例,默认为1表示不缩放
*/
void rotatePoints(std::vector<cv::Point2f>& srcPoints, std::vector<cv::Point2f>& dstPoints, cv::Point& basePoint,int degree, float zoomRate=1)
{
    cv::Mat affineMatrix = cv::getRotationMatrix2D(basePoint,degree,zoomRate);
    cv::transform(srcPoints, dstPoints, affineMatrix);
}

/*
功能:对一系列点进行缩放仿射变换
参数:
srcPoints:输入点坐标
dstPoints:变换后的点坐标
basePoint:缩放基准点
zoomRate:缩放比例
*/
void zoomPoints(std::vector<cv::Point2f>& srcPoints, std::vector<cv::Point2f>& dstPoints, cv::Point& basePoint,float zoomRate)
{
    cv::Mat affineMatrix = cv::getRotationMatrix2D(basePoint,0,zoomRate);
    cv::transform(srcPoints, dstPoints, affineMatrix);
}

/*
功能:对一张图片进行平移
参数:
src:要平移的图片
dst:平移的结果
x:x方向平移的距离
y:y方向平移的距离
*/
void translateImage(cv::Mat& src, cv::Mat& dst, double x, double y)
{
    cv::Mat M = (cv::Mat_<double>(2, 3) << 1, 0, x, 0, 1, y);
    cv::warpAffine(src, dst, M, src.size());
}

/*
功能:对一张图片进行旋转
参数:
image:输入图像
imgOut:旋转后的图像
angle:旋转角度
*/
void rotateImage(cv::Mat& image, cv::Mat& imgOut, int angle)
{
    /*
    对旋转的进行改进,由于图形是一个矩形,旋转后的新图像的形状是一个原图像的外接矩形
    因此需要重新计算出旋转后的图形的宽和高
    */
    int width = image.cols;
    int height = image.rows;

    double radian = angle * CV_PI / 180.;//角度转换为弧度
    double width_rotate = fabs(width*cos(radian)) + fabs(height*sin(radian));
    double height_rotate = fabs(width*sin(radian)) + fabs(height*cos(radian));

    //旋转中心 原图像中心点
    cv::Point2f center((float)width / 2.0, (float)height / 2.0);
    //旋转矩阵
    cv::Mat m1 = cv::getRotationMatrix2D(center, angle, 1.0);
    //m1为2行3列通道数为1的矩阵
    //变换矩阵的中心点相当于平移一样 原图像的中心点与新图像的中心点的相对位置
    m1.at<double>(0, 2) += (width_rotate - width) / 2.;
    m1.at<double>(1, 2) += (height_rotate - height) / 2.;
    if (image.channels() == 1)
    {
        cv::warpAffine(image, imgOut, m1, cv::Size(width_rotate, height_rotate), cv::INTER_LINEAR, 0, cv::Scalar(0));
    }
    else if (image.channels() == 3)
    {
        cv::warpAffine(image, imgOut, m1, cv::Size(width_rotate, height_rotate), cv::INTER_LINEAR, 0, cv::Scalar(0,0,0));
    }
}

/*
功能:对一张图片进行缩放
参数:
src:输入图像
dst:缩放后的图像
basePoint:缩放基准点
zoomRate:缩放比例
*/
void zoomImage(cv::Mat& src, cv::Mat& dst, cv::Point& rotaPoint, float zoomRate)
{
    cv::Mat M = cv::getRotationMatrix2D(rotaPoint, 0, zoomRate);
    cv::warpAffine(src, dst, M, src.size());
}

//#define TESTPOINTS
#define TESTIMAGE

int main() {
#ifdef TESTPOINTS
    // 创建原始点集
    std::vector<cv::Point2f> srcPoints = { cv::Point2f(100, 100), cv::Point2f(200, 200), cv::Point2f(300, 300) };
    //变换点集
    std::vector<cv::Point2f> dstPoints;
    //tranlatePoints(srcPoints, dstPoints, 10, 10);
    cv::Point point(0, 0);
    //rotatePoints(srcPoints, dstPoints, point,180);
    //zoomPoints(srcPoints, dstPoints, point, 0.5);

    // 输出结果
    std::cout << "原始点集: ";
    for (const auto& point : srcPoints) {
        std::cout << point << " ";
    }
    std::cout << std::endl;

    std::cout << "仿射变换后的点集: ";
    for (const auto& point : dstPoints) {
        std::cout << point << " ";
    }
    std::cout << std::endl;
#endif // TESTPOINTS

#ifdef TESTIMAGE
    cv::Mat img1 = cv::imread("D:/20240103141532.png");
    cv::Mat dst;
    //translateImage(img1, dst, -50, 50);
    //cv::imshow("src",img1);
    //cv::imshow("1", dst);
    //cv::waitKey(0);
    
    //for (int i = 0; i < 36; i++)
    //{
    //    rotateImage(img1, dst,i * 10);
    //    cv::imshow("1", dst);
    //    cv::waitKey(0);
    //}

    //int width = img1.cols;
    //int height = img1.rows;
    //cv::Point basePoint((float)width / 2.0, (float)height / 2.0);
    //zoomImage(img1, dst, basePoint, 0.5);
    //cv::imshow("src", img1);
    //cv::imshow("1", dst);
    //cv::waitKey(0);
#endif // TESTIMAGE
    return 0;
}

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

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

相关文章

低代码助力制造业数智转型,激发创新力迎接工业 4.0

随着科技的不断进步&#xff0c;我们迈入了一个崭新的工业时代——工业4.0。这场工业革命不仅颠覆了制造业的传统形象&#xff0c;还为全球生产方式带来了前所未有的变革。 在这一过程中&#xff0c;制造业数字化转型逐渐成为主旋律&#xff0c;而低代码技术在这其中发挥着重要…

近红外光谱分析技术与基于深度学习的化学计量学方法

郁磊【副教授】&#xff1a;主要从事AI人工智能与大数据分析等相关研究&#xff0c;长期致力于人工智能与近红外生物医学工程等领域融合&#xff0c;主持并完成多项科研课题。著有《神经网络43个案例分析》等书籍。 // 讲座内容 1、近红外光谱基本理论、近红外光谱仪基本原理…

openssl3.2 - 官方demo学习 - digest - EVP_MD_stdin.c

文章目录 openssl3.2 - 官方demo学习 - digest - EVP_MD_stdin.c概述笔记END openssl3.2 - 官方demo学习 - digest - EVP_MD_stdin.c 概述 使用 SHA3-512 对stdin输入做摘要, 并输出摘要值. 笔记 /*! \file EVP_MD_stdin.c \note openssl3.2 - 官方demo学习 - digest - EVP…

python爬虫-代理ip理解

目录 1、为什么使用代理IP 2、代理IP 3、IP池 4、代理分类&#xff1a; 5、python中使用代理IP 6、如何找可以使用的代理IP 7、拿到IP后&#xff0c;测试IP的有效性 8、扩展理解正向代理和反向代理 1、为什么使用代理IP 就是为了防止ip被封禁&#xff0c;提高爬虫的效…

【Proteus仿真】【Arduino单片机】智能窗户设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用蜂鸣器模块、LCD1602显示模块、雨滴传感器、风速传感器、人体红外模块、ADC模块、按键模块、28BYJ48步进电机 模块、DS18B20温度传感器等。 …

2023年北邮渣硕的暑期秋招总结

背景 实验室一般是在研究生二年级的时候会放实习&#xff0c;在以后的日子就是自己完成毕业工作要求&#xff0c;基本上不再涉及实验室的活了&#xff0c;目前是一月份也是开始准备暑期实习的好时间。实验室每年这个时候都会有学长学姐组织暑期实习经验分享&#xff0c;本着不…

外国入境的免签国家以及中外互免(普通护照*、普通公务护照)

2024.1.11起&#xff0c;外籍人员在北京首都、北京大兴、上海浦东、杭州萧山、厦门高崎、广州白云、深圳宝安、成都天府、西安咸阳9个国际机场&#xff0c;推行24小时直接过境旅客免办边检手续。对于持24小时内国际联程机票&#xff0c;经上述任一机场过境前往第三国或地区的出…

Python dataframe取单元值

取dataframe某行某列所指的单元值 代码准备&#xff1a; 环境平台&#xff1a;Python 3.7.1 -IDLE Shell >>> import pandas as pd >>> df pd.DataFrame({Name: [Tom, Jim, Lily], Age: [20, 18, 22], Gender: [Male, Male, Female]})注&#xff1a;部分参…

高防dns服务器租用有哪些应用场景?-速盾cdn

高防DNS服务器租用可以应用于以下场景&#xff1a; 网站安全防护&#xff1a;高防DNS服务器可以提供强大的防御能力&#xff0c;抵御DDoS攻击、DNS劫持、泛洪攻击等威胁&#xff0c;保证网站的稳定运行和安全性。 网络游戏&#xff1a;网络游戏通常面临大量用户同时访问和数据…

C#中对浮点数NaN,PositiveInfinity,NegativeInfinity的特殊处理

NAN NAN 整体意思为Not a Number 不是一个数&#xff0c; NaN&#xff08;Not a Number&#xff0c;非数&#xff09;是计算机科学中数值数据类型的一类值&#xff0c;表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。 EEE 75…

论文阅读 Self-Supervised Burst Super-Resolution

这是一篇 ICCV 2023 的文章&#xff0c;主要介绍的是用自监督的方式进行多帧超分的学习 Abstract 这篇文章介绍了一种基于自监督的学习方式来进行多帧超分的任务&#xff0c;这种方法只需要原始的带噪的低分辨率的图。它不需要利用模拟退化的方法来构造数据&#xff0c;而且模…

API设计:从基础到最佳实践

1*vWvkkgG6uvgmJT8GkId98A.png 在这次深入探讨中&#xff0c;我们将深入了解API设计&#xff0c;从基础知识开始&#xff0c;逐步进阶到定义出色API的最佳实践。 作为开发者&#xff0c;你可能对许多这些概念很熟悉&#xff0c;但我将提供详细的解释&#xff0c;以加深你的理解…

Python DataFrame取行

文章目录 index区间取行列值区间条件取行&#xff08;1&#xff09;列值区间基本表达方式&#xff08;2&#xff09;多条件组合表达方式&#xff08;3&#xff09;函数条件表达方式 datafame接受的几个过滤函数&#xff08;1&#xff09;isin函数&#xff1a;(2) query函数&…

2024--Django平台开发-Django知识点(七)

频率超高的问题 Redis的问题虚拟环境mysqlcient和pymysql短信服务&#xff0c;一期用的是腾讯云短信 虚拟环境 可以用来创建虚拟环境的&#xff1a; virtualenv这个模块&#xff0c;简单易上手&#xff0c;推荐 小白不建议&#xff0c;conda&#xff0c;如果大家用这个&…

React项目实战--------极客园项目PC端

项目介绍&#xff1a;主要将学习到的项目内容进行总结&#xff08;有需要项目源码的可以私信我&#xff09; 关于我的项目的配置如下&#xff0c;请注意下载的每个版本不一样&#xff0c;写的api也不一样 一、项目介绍 1.资料 1&#xff09;短信接收&M端演示&#xff1a…

微信小程序 - 视图与逻辑 介绍

文章目录 视图与逻辑一、页面导航1、页面导航 - 声明式导航1.1 导航到tabBar页面1.2 导航到非tabBar页面1.3 后退导航 2、页面导航 - 编程式导航2.1 导航到tabBar页面2.2 导航到非tabBar页面2.3 后退导航 3、页面导航 - 导航传参3.1 声明式导航传参3.2 编程式导航传参3.3 在 on…

ZZULIOJ 1125: 上三角矩阵的判断

题目描述 编写程序&#xff0c;输入一个正整数n&#xff08;1<n<10&#xff09;和n阶方阵a中的元素&#xff0c;如果a是上三角矩阵&#xff0c;输出“YES”&#xff0c;否则&#xff0c;输出“NO”。 上三角矩阵即主对角线以下&#xff08;不包括主对角线&#xff09;的…

Vue中v-if与v-show区别详解

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

目标导向理论 : 一种高效,改变人做事精神状态,决定成事概率的行为方式

百科对目标导向理论的解释 目标导向理论是激励理论的一种。它是由豪斯提出来的&#xff0c;目标导向理论的基本出发点是要求领导者排除走向目标的障碍&#xff0c;使其顺利达到目标&#xff0c;在此过程中&#xff0c;给予职工满足多种多样需要的机会。 [1]   目标导向理论认…

寻找最富裕的小家庭 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 在一棵树中,每个节点代表一个家庭成员,节点的数字表示其个人的财富值,一个节点及其直接相连的子节点被定义为一个小家庭现给你一棵树,请计算出最富裕的小家庭的财富和。 输入描述 第一行为一个数N,…