读书笔记-opencv-极坐标变换
读书笔记-opencv-极坐标变换
原理解析
极坐标变换用来矫正图像中的圆形物体,或者包含在圆形物体中。
笛卡尔坐标系xoy平面上任意一点(x,y),以(x1,y1)为中心通过以下计算公式对应到极坐标系上的极坐标(θ,r)
极坐标变换后的角度范围[0, 360]
举例:(11, 13)以(3, 5)为中心进行极坐标变换
import math
r = math.sqrt(math.pow(11-3, 2) + math.pow(13-5, 2))
theta = math.atan2(13-5, 11-3)/math.pi*180 #转换为角度
print(r, theta)
opencv提供的函数:
x = np.array([[0,1,2],[0,1,2],[0,1,2]], dtype = "float64")-1
y = np.array([[0,0,0],[1,1,1],[2,2,2]], np.float64)-1
r, theta = cv2.cartToPolar(x,y, angleInDegrees = True)
print(r, theta)
angleInDegrees = True代表返回的是角度,反之返回的是弧度。array数据类型为浮点型,float32或者float64,x,y具有相同尺寸和数据类型的数组。
将极坐标转换为笛卡尔坐标系
已知极坐标(θ,r)的条件下,以笛卡尔坐标(x1,y1)为中心,
原坐标(x,y)可表示为:
x=x1+rcosθ,y=y1+rsinθx = x_{1} + rcosθ, y = y_{1} + rsinθ x=x1+rcosθ,y=y1+rsinθ
opencv提供函数:
angle = np.array([[30,31], [30,31]], np.float32)
radiu = np.array([[10,10], [11, 11]], np.float32)
x, y = cv2.polarToCart(radiu, angle, angleInDegrees = True )
C++实现:
Mat angle = (Mat_<float>(2,2) << 30, 31, 30, 31);
Mat radiu = (Mat_<float>(2,2) << 10, 10, 11, 11);
Mat x, y;
polarToCart(radiu, angle, x, y, true);
函数参数和前面Python类似。
利用极坐标变换对图像进行变换
假设输入矩阵位I,(x1, y1)代表极坐标变换的中心,输出图像矩阵位O, 极坐标与笛卡尔坐标系一一对应的关系,即:
O(I,θ)=fI(x1+rcosθ,y1+rsinθ)O(I, θ) = f_{I}(x_{1} + rcosθ, y_{1} + rsinθ) O(I,θ)=fI(x1+rcosθ,y1+rsinθ)
这里的I, θ都是以1为步长,输出矩阵可能失真严重。进行改进,假设(x1, y1)的距离范围[rmin, rmax],角度范围是[θmin, θmax]进行坐标和变换,进行离散化;假设r的变换步长为rstep,0<rstep<=1,θ的变换步长为θstep,一般取360/(180*N), N>=2,输出矩阵的宽为w ~ (rmax - rmin)/rstep + 1,高h~(θmax - θmin)/θstep + 1。图像矩阵O的第i行第j列的值为:
O(i,j)=fI(x1+(rmin+rstep∗i)∗cos(θmin+θstep∗j),y1+(rmin+rstep∗i)∗sin(θmin+θstep∗j))O(i,j) = f_{I}(x_{1} + (r_{min} + r_{step} * i)*cos(θ_{min} + θ_{step} *j), y_{1} + (r_{min} + r_{step} * i)*sin(θ_{min} + θ_{step} *j)) O(i,j)=fI(x1+(rmin+rstep∗i)∗cos(θmin+θstep∗j),y1+(rmin+rstep∗i)∗sin(θmin+θstep∗j))
代码实现:
import cv2
import numpy as np
import sys
import math def polar(I, center, r, theta= (0,360), rstep = 1.0, thetastep = 360.0/(180*8)):#得到距离最小最大的范围minr, maxr = r#得到角度最小最大范围mintheta, maxtheta = theta#H = int((maxr - minr) / rstep) +1W = int((maxtheta - mintheta) / thetastep) +1O = 125 * np.ones((H, W), I.dtype)#tile(a,(2,3))在垂直方向和水平方向上复制2,3次#numpy.linspace(start, stop[, num=50[, endpoint=True[, retstep=False[, dtype=None]]]]])#返回在指定范围内的均匀间隔的数字(组成的数组),也即返回一个等差数列#start - 起始点,stop - 结束点,num - 元素个数,默认为50,#endpoint - 是否包含stop数值,默认为True,包含stop值;若为False,则不包含stop值#retstep - 返回值形式,默认为False,返回等差数列组,若为True,则返回结果(array([`samples`, `step`])),#dtype - 返回结果的数据类型,默认无,若无,则参考输入数据类型。#transpose用法详见https://blog.csdn.net/xiongchengluo1129/article/details/79017142#极坐标变换r = np.linspace(minr,maxr,H) r = np.tile(r,(W,1))r = np.transpose(r)theta = np.linspace(mintheta,maxtheta,W)theta = np.tile(theta,(H,1))x,y=cv2.polarToCart(r,theta,angleInDegrees=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 py <= h-1)):O[i][j] = I[py][px]else:O[i][j] = 125#灰色return O#主函数
if __name__ == "__main__":imagePath = "G:\\blog\\OpenCV_picture\\chapter3\\img2.jpg" #"G:\\blog\\OpenCV算法精解-测试图片\\第3章\\image2.jpg"image = cv2.imread(imagePath, cv2.IMREAD_GRAYSCALE)#图像的宽高h,w = image.shape[:2]print (w,h)#极左标变换的中心cx,cy = 508,503print (cx,cy)cv2.circle(image,(int(cx),int(cy)),10,(255.0,0,0),3)#距离的最小最大半径 #200 550 270,340O = polar(image,(cx,cy),(0,550))#旋转O = cv2.flip(O,0)#显示原图和输出图像cv2.imshow("image",image)cv2.imshow("O",O)cv2.imwrite("O.jpg",O)cv2.waitKey(0)cv2.destroyAllWindows()
注意:xrange()在opencv3里面合并到range()
C++实现
先介绍repeat()函数,重复函数与前面的tile()函数类似。
void repeat(const Mat& sr, int ny, int nx)
src输入矩阵,ny将src在垂直方向上重复ny次, nx将src在水平方向上面重复nx次。
通过polar()函数实现及坐标变换,参数I是输入图像,center十几座标变换中心,minr是与变换中心的最小距离,mintheta是最小角度,thetaStep是角度变换步长,rStep是距离变换步长,插值使用最邻近插值算法。
Mat polar(Mat I, Point2f center, Size size, float minr = 0, float mintheta = 0.0, float thetaStep = 1.0 / 4, float rStep = 1.0)
{//构建半径矩阵Mat r_i = Mat::zeros(Size(1, size.height), CV_32FC1);for (int i = 0; i < size.height; i++){r_i.at<float>(i, 0) = minr + i * rStep;}Mat r = repeat(r_i, 1, size.width);//构建角度矩阵Mat theta_j = Mat::zeros(Size(size.width, 1), CV_32FC1);for (int j = 0; j < size.height; j++){theta_j.at<float>(0, j) = mintheta + j * thetaStep;}Mat theta = repeat(theta_j, 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 nearestx = int(round(xij));int nearesty = int(round(yij));if ((0 <= nearestx && nearestx < I.cols) && (0 <= nearesty && nearesty < I.rows)){dst.at<uchar>(i, j) = I.at<uchar>(nearestx, nearesty);}}}return dst;}int main()
{std::string iamge_path = "G:\\blog\\OpenCV_picture\\chapter3\\img2.jpg";Mat image = imread(iamge_path, 0);if (!image.data){return -1;}//图像极坐标变化float thetaStep = 1.0 / 4;float minr = 270;Size size(int(360 / thetaStep), 70);Mat dst = polar(image, Point2f(508, 503), size, minr);//水平方向镜像处理flip(dst, dst, 0);//显示imshow("I", image);imshow("polar: ", dst);waitKey(0);return 0;
}
结果:
void filp(InputArray src, OutputArray dst, int flipCode)
flipCode : >0:src绕y轴镜像处理
:=0:src绕x轴镜像处理
: <0:src逆时针旋转180°,先绕x轴,再绕y轴镜像
flip()函数进行的几何变换,不是通过仿射变换,而是行列互换,声明在core.hpp中。
线性极坐标函数linearPolar
void linearPolar(InutArray src, OutputArray dst, Point2f center, double maxRadius, int flags)
center:极坐标变换中心; maxRadius:极坐标变换的最大距离, flags:插值算法,与前文的resize() 和warpAffine()类似。
代码实现:
int main()
{std::string iamge_path = "G:\\blog\\OpenCV_picture\\chapter3\\img2.jpg";Mat image = imread(iamge_path, 0);if (!image.data){return -1;}Mat dst;linearPolar(image, dst, Point2f(508, 503), 550, CV_INTER_CUBIC);//这里采用的不是最邻近插值算法imshow("InitImage", image);imshow("PolarImage", dst);waitKey(0);return 0;}
该函数存在两个缺点:极坐标变换的步长不可控,该函数只能对整个圆内区域进行变换,不可以对圆环进行操作。
void logPolar (InutArray src, OutputArray dst, Point2f center, double maxRadius, int flags)
该函数和linearPolar()函数类似。
读书笔记-opencv-极坐标变换相关推荐
- 读书笔记-opencv-投影变换
读书笔记-opencv-投影变换 原理解析 透视变换是将图片投影到一个新的视平面,也称作投影映射.它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x′,y′)空间的映射.相对于仿射变换,它 ...
- 【OpenCV 4开发详解】图像极坐标变换
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- Practical Python and OpenCV 3rd Edition读书笔记_Chapter8_Smoothing and Blurring平滑与模糊_思维导图
<Practical Python and OpenCV 3rd Edition>真的是一本非常棒的入门书籍. 它也很薄,只有166页,虽然是纯英文的,如果静下心来认真看一两天就可以读完. ...
- python直角坐标转极坐标_Python在OpenCV里实现极坐标变换功能
在中学里学习过直角坐标系,也叫做笛卡尔坐标系,它是正交坐标系,不过也学习过极坐标系,这种坐标系比较适合大炮发射的场合.极坐标系的定义如下: 在 平面内取一个定点O, 叫极点,引一条射线Ox,叫做极轴, ...
- 【算法+OpenCV】图像极坐标变换及基于OpenCV的实现
在医学图像处理,尤其是在处理血管断层扫描类(如OCT.IVUS等)图像的过程中,不可避免的会使用到极坐标变换,也即是我们通常所说的"方转圆".同样,我们可以使用极坐标变换的反变换实 ...
- 《Master Opencv...读书笔记》非刚性人脸跟踪 II
上一篇博文中,我们了解了系统的功能和模块,明确了需要采集哪些类型的样本点及利用类的序列化的保存方式.这次将介绍几何约束模块,通过统计形态分析法(Statistical Shape Analysis, ...
- 机器视觉算法与应用读书笔记(算法)
机器视觉算法与应用读书笔记(算法) 1.数据结构 2.图像增强 1. 灰度值变换 2. 辐射标定 3. 图像平滑 1. 时域去噪法 2. 空间域去噪法 均值滤波器 递归线性滤波器:将上次计算得到的值带 ...
- 吐血整理!万字原创读书笔记,数据分析的知识点全在这里了
作者:JaneK 来源:大数据DT 导读:今天这篇文章是「大数据」内容合伙人JaneK关于<Python数据分析与数据化运营>的一篇读书笔记. 本文目录: Python数据分析与挖掘 01 ...
- Matplotlib 数据可视化(读书笔记)
Python 数据科学手册第四章读书笔记,仅供学习交流使用 4. Matplotlib 数据可视化 4.1 Matplotlib 常用技巧 4.1.1 导入 Matplotlib plt 是最常用的接 ...
- 《代码整洁之道 clean code》 读书笔记(上篇)
<代码整洁之道 clean code> 读书笔记(上篇) 这本书我准备用较快的时间来读一下,简单记录一下自己的一些读完的感悟,因为更多地编码技巧还是需要在实际编程和读源码的过程中进行锤炼. ...
最新文章
- 地图区域划分转换成数学模型解决问题
- Admin注册和路由分发详解
- 【LeetCode从零单排】No14.LongestCommonPrefix
- android版记账本
- 交叉驰豫的影响因素_交叉滚子轴承系列吉林薄壁交叉滚子轴承用途博盈
- 统计字符串中某个字出现的次数
- Atitit. Api 设计 原则 ---归一化
- 通讯录 C语言分类,C语言 通讯录
- 融云android系统消息,如何解决 嵌入融云SDK后, Android 手机收不到消息推送?
- 【C++】类和对象(中) —— 构造函数 | 析构函数 | 拷贝构造 | 赋值运算符重载
- APP测试与WEB测试
- Delphi 制作股票分时图
- 云计算激荡十五年:亚马逊云科技的探路者精神
- 解决罗技K580键盘win和alt键互换问题
- oracle dul 扫描磁盘,案例:Oracle dul数据挖掘 磁盘损坏dul提取数据文件中表的数据及l...
- 你知道我国一共赠送了多少只熊猫给外国吗?来看看这个数据可视化项目
- 微信小程序意见反馈的实现
- nginx-2-讲解与使用
- Windows Update禁用后自动开启的解决办法
- bzoj 5248: [2018多省省队联测]一双木棋 博弈论+状压dp