当前位置: 首页 > news >正文

C++版OpenCV_02_几何变换

几何变换

      • 2.1 仿射变换
      • 2.2 投影变换
      • 2.3 极坐标变换
        • 2.3.1 笛卡尔坐标转极坐标
        • 2.3.2 极坐标转换为笛卡儿坐标
        • 2.3.3 图像极坐标变换
        • 2.3.4 线性极坐标函数
        • 2.3.5 对数极坐标函数 logPolar

几何变换:

  1. 仿射变换:平移、放大缩小、旋转、计算仿射矩阵(方程法、矩阵法)、插值(最近邻、双线性插值)、
  2. 投影变换
  3. 极坐标变换

2.1 仿射变换

平移

x_ = 1*x + 0*y+ tx
y_ = 0*x + 1*y+ ty

放大缩小

/*
x_ = sx*x + 0*y+ 0*tx
y_ = 0*x + sy*y+ 0*tyvoid resize(InputArray scr,outputArray dst,Size dsize,double fx=0,double fy=0,int interpolation=INTER_LINEAR)
scr: 输入图像
dst: 输出图像
dsize:(宽高)
fx: 水平方向上的缩放比例
fy: 垂直方向上的缩放比例
interpolation: 插值法 INTER_NEAREST、INTER_LINEAR*/
#include<opencv/core/core.hpp>
#include<opencv/highgui/highgui.hpp>
#include<opencv/imgproc/imgproc.hpp>
using namespace cv;
int main(int argv,char*argv[])
{Mat I = imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);if(!I.data)return -1;Mat s = (Mat_<float>(2,2)<<0.5,0,0,0,0.5,0);Mat dst;warpAffine(I,dst,s,Size(I.cols/2,I.rows/2));Mat dst1;resize(I,dst1,Size(I.cols/2,I.rows/2),0.5,0.5);
}

旋转

/*
x_ = cosa*x + sina*y+ 0*tx
y_ = -sina*x + cosa*y+ 0*ty
void rotate(InputArray scr,outputArray dst,int rotateCode)
rotateCode: ROTATE_90_CLOCKWISE,ROTATE_180,ROTATE_90_COUNTERCLOCKWISE,270度
*/#include<opencv/core/core.hpp>
#include<opencv/highgui/highgui.hpp>using namespace cv;
int main(int argv,char*argv[])
{Mat I = imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);if(!I.data)return -1;Mat dst;rotate(I,dst,ROTATE_90_CLOCKWISE);}

计算仿射矩阵
方程法求仿射矩阵

// 仿射矩阵有6个自由度,因此需要src,dst3对不共线的点求解
// 把对应点存在数组中
Point2f src[]={Point2f(0,0),Point2f(10,24),Point2f(60,120)};
Point2f dst[]={Point2f(0,0),Point2f(30,64),Point2f(50,98)};
Mat A = getAffineTransform(src,dst)// 把对应点存在矩阵中
Mat src = (Mat_<float>(3,2)<<0,0,10,24,60,120);
Mat dst = (Mat_<float>(3,2)<<0,0,30,64,50,98);
Mat A = getAffineTransform(src,dst)

计算仿射矩阵
矩阵法:

// 获取旋转矩阵
Mat A = getRotationMatrixD(Point2f(x,y),angle,scale);

2.2 投影变换

/*
Point2f src[]={Point2f(0,0),Point2f(100,0),Point2f(0,100),Point2f(100,100)};
Point2f dst[]={Point2f(100,30),Point2f(200,30),Point2f(70,80),Point2f(230,90)};
Mat P=getPerspectiveTransform(src,dst);Point2f src=(Mat_<float>(4,2)<<0,0,20,10,40,89,100,100);
Point2f dst=(Mat_<float>(4,2)<<10,20,30,80,80,90,200,150);
Mat P=getPerspectiveTransform(src,dst);
*/

2.3 极坐标变换

2.3.1 笛卡尔坐标转极坐标
/*
笛卡尔坐标转极坐标
已知任意一点(x,y),中心(x',y'),(a,r)
r = ((x-x')**2+(y-y')**2)**0.5
a = 2pi+arctan2(y-y',x-x') 当y-y' <=0  or  arctan2(y-y',x-x')  当y-y' >0cartToPolar(x,y magnitude,angle,angleInDegrees)
angleInDegrees: ture 返回角度,反之,返回弧度。*/
// 笛卡儿坐标转换为极坐标
Mat x = (Mat_<float>(1,8)<<0,1,2,0,2,0,1,2)-1;
Mat y = (Mat_<float>(1,8)<<0,0,0,1,1,2,2,2)-1;
Mat r,theta;
cartToPolar(x,y,r,theta,True);
/* 结果
1.41   3.93
1.0    4.71
1.41   5.5
1.0    3.14
1.0    0.0
1.41   2.36
1.0    1.57
1.41   0.79
*/
2.3.2 极坐标转换为笛卡儿坐标
/*
x = x'+r*cosa
y = y'+r*sina
polarTocart(magnitude,angle,x,y,angleInDegrees));
返回的是以(0,0)为中心的笛卡尔坐标,已知(r,theta)和(x',y')得到(x-x',y-y')
*/
Mat angle = (Mat_<float>(2,2)<<30,31,30,31);
Mat r = (Mat_<float>(2,2)<<10,10,11,11);
Mat x,y;
polarTocart(r,angle,x,y,true);
2.3.3 图像极坐标变换
/*
O(i,j) = I(x'+(r_min+r_step*i)*cos(a_min+a_step*j),  y'+(r_min+r_step*i)*sin(a_min+a_step*j))
*/
import cv2
import numpy as np
import matplotlib.pyplot as pltdef polar(img, center, r, theta=(0, 360), rstep=1.0, thetastep=360.0 / (180 * 8)):cx, cy = centerr_min, r_max = rtheta_min, theta_max = thetaH = int((r_max - r_min) / rstep) + 1W = int((theta_max - theta_min) / thetastep) + 1out = np.ones((H, W), img.dtype) * 125r = np.linspace(r_min, r_max, H)r = np.tile(r, (W, 1)).T  # (H,W)theta = np.linspace(theta_min, theta_max, W)theta = np.tile(theta, (H, 1))  # (H,W)x, y = cv2.polarToCart(r, theta, True)for i in range(H):for j in range(W):px = int(round(x[i, j]) + cx)py = int(round(y[i, j]) + cy)if (px >= 0 and px <= W - 1) and (py >= 0 and px <= H - 1):out[i, j] = img[px, py]return outif __name__ == "__main__":img = np.zeros([300, 300, ], np.uint8)img = cv2.circle(img, (150, 150), 80, (255), -1)plt.imshow(img, 'gray')o = polar(img, center=(150, 150), r=(0, 100), theta=(0, 360), rstep=0.25)plt.imshow(o, 'gray')
/*
根据中心(cx,cy)、最小半径、最小角度、半径步长、角度步长获取最大半径和最大步长,把r、theta转换成x,y。把(x,y)对应的像素值赋值给对应坐标(r、theta)。
*/
Mat polar(Mat I,Point2f center,Size size,float minr = 0,float mintheta=0,float thetaStep = 1.0/4,float rStep;=1.0)
{// 构建 r[size.height,size.width]Mat ri = Mat::zeroes(Size(1,size.height),CV_32FC1);for (int i = 0;i <size.height;++i){ri.at<float>(i,0) = minr+i*rStep;}Mat r = repeat(ri,1,size.width);// 构建 theta[size.height,size.width]Mat  thetaj = Mat::zeroes(Size(size.width,1),CV_32FC1);for (int j = 0;j <size.width;++j){thetaj.at<float>(0,j) = mintheta+j*thetaStep;}Mat theta = repeat(thetaj,size.height,1// 把极坐标转换为笛卡尔坐标Mat x,y;polarToCart(r,theta,x,y,true);x += center.x;y += center.y;// 最近邻插值Mat dst = 125*Mat::ones(size,CV_8UC1);for (int i=0;i<size.height,++i){for (int j=0;j<size.width,++j){float xij = x.at<float>(i,j);float yij = y.at<float>(i,j);int x_near = int(round(xij));int y_near = int(round(yij));}if((x_near>=0&&x_near<=I.cols)&&(y_near>=0&&y_near<=I.rows)){dst.at<uchar>(i,j)=I.at<uchar>(y_near,x_near)}}return dst;
}int main(int argc,char*argv[])
{Mat I = imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);if(!I.data)return -1;float thetaStep=1.0/4;float minr = 270;Size size(int(360/thetaStep),80);Mat dst = polar(I,Point2f(500,508),size,minr);flip(dst,dst,0);
}
2.3.4 线性极坐标函数
/*
void linearPolar( InputArray src, OutputArray dst,Point2f center, double
maxRadius, int flags );
src :输入图像矩阵(单、多通道矩阵都可以)
dst :输出图像矩阵,其尺寸和 src 是相同的
center :极坐标变换中心
maxRadius :极坐标变换的最大距离
flags :插值算法,同函数 resize、warpAffine 的插值算法
角度 𝜃 的变换步长大约为 36/0𝐻
,𝑟 的变换步长大约为 maxRadius/𝑊
;
*/
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
int main(int argc, char*argv[])
{//输入图像Mat src = imread(argv[1], IMREAD_ANYCOLOR);if (!src.data)return -1;//极坐标变换Mat dst;linearPolar(src, dst, Point2f(508, 503), 550, CV_INTER_LINEAR);//显示原图和极坐标变换图imshow("原图", src);imshow("极坐标变换图", dst);waitKey(0);return 0;
}
2.3.5 对数极坐标函数 logPolar
/*
void logPolar(InputArray src,OutputArray dst,Point2f center, double M, int
flags )
src: 输入图像矩阵(单、多通道矩阵都可以)
dst: 输出图像矩阵,其尺寸和 src 是相同的
center: 极坐标变换中心
M: 系数,该值大一点效果会好一些
flags:
WARP_FILL_OUTLIERS:笛卡儿坐标向对数极坐标变换
WARP_INVERSE_MAP:对数极坐标向笛卡儿坐标变换笛卡儿坐标转换为对数极坐
标:
r = M*log(((x-cx)**2+(y-cy)**2)**0.5)
theta = actan2(y-cy,x-cx); if y>cy,theta=theta else theta+=2*pi
将对数极坐标转换为笛卡儿坐标:
x = cx+exp(r/M)cosa;y = cy+exp(r/M)sina
*/
int main(int argc, char*argv[])
{//读入图像Mat src = imread(argv[1], IMREAD_ANYCOLOR);//对数极坐标变换Mat dst;Point2f center(508, 503);float M = 100;logPolar(src, dst, center, M, WARP_FILL_OUTLIERS);//显示对数极坐标变换的结果imshow("对数极坐标变换", dst);imshow("原图", src);waitKey(0);return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spring Boot应用的配置文件(application.properties或application.yml)指定应用连接MySQL数据库
  • 什么是dom驱动?
  • Docker核心技术:应用架构演进
  • 服务攻防-应用协议cve
  • Thinkphp开发文档二次整理版
  • 子查询
  • Langchain 对pdf,word,txt等不同文件的加载解析
  • C语言-栈和队列
  • springboot 配置 spring data redis
  • spring-boot 整合 redisson 实现延时队列(文末有彩蛋)
  • TiDB实践—索引加速+分布式执行框架创建索引提升70+倍
  • SpringBoot RestHighLevelClient 按版本更新
  • 自动驾驶AVM环视算法–全景和标定全功能算法实现和exe测试demo
  • vscode配置latex环境制作【文档、简历、resume】
  • Chapter16 渲染优化技术——Shader入门精要学习笔记
  • CentOS从零开始部署Nodejs项目
  • HTTP中GET与POST的区别 99%的错误认识
  • JDK 6和JDK 7中的substring()方法
  • maven工程打包jar以及java jar命令的classpath使用
  • Mybatis初体验
  • MySQL的数据类型
  • Octave 入门
  • Otto开发初探——微服务依赖管理新利器
  • vue的全局变量和全局拦截请求器
  • 测试开发系类之接口自动化测试
  • 聊聊sentinel的DegradeSlot
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 前端自动化解决方案
  • 悄悄地说一个bug
  • 删除表内多余的重复数据
  • 时间复杂度与空间复杂度分析
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 原生Ajax
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • #C++ 智能指针 std::unique_ptr 、std::shared_ptr 和 std::weak_ptr
  • #在 README.md 中生成项目目录结构
  • (C语言)fread与fwrite详解
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (算法)N皇后问题
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (转)可以带来幸福的一本书
  • (转)用.Net的File控件上传文件的解决方案
  • ***利用Ms05002溢出找“肉鸡
  • .gitignore文件_Git:.gitignore
  • .net core + vue 搭建前后端分离的框架
  • .net core使用ef 6
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • @ResponseBody
  • @SuppressWarnings(unchecked)代码的作用