【草稿】详解OpenCV实现图像直角坐标系转极坐标系的函数warpPolar(),并附自己写的实现直角坐标系转极坐标系的MATLAB代码
有些时候我们需要把图像或矩阵从直角坐标系(笛卡尔坐标系)转换到极坐标,这个过程通常称为图像的极坐标变换。
图像的极坐标变换一个常见的作用是可以将将一圆形图像变换成一个矩形图像,类似于把圆剪开铺平。这样可以方便我们处理钟表、圆盘等图像。图形上的圆形排列文字经过及坐标变换后可以垂直的排列在新图像上,便于对文字的识别和检测。示意图如下:
OpenCV4中新增加了函数warpPolar()用于将图像或矩阵从直角坐标系(笛卡尔坐标系)转换到极坐标。
其C++原型如下:
void cv::warpPolar(InputArray src,
OutputArray dst,
Size dsize,
Point2f center,
double maxRadius,
int flags )
其Python原型如下:
dst = cv.warpPolar(src, dsize, center, maxRadius, flags[, dst])
参数意义如下:
src—原图像,对通道数无要求,可以是灰度图像或者彩色图像。
dst—输出图像,它和原图像具有相同的数据类型和通道数,注意没有说尺寸相同哈。
dsize—目标图像大小,如图不填这个值或dsize两个值中的某个值,那么按下面的规则计算:
center—极坐标变换时原点坐标。
maxRadius—极坐标系的极半径最大值,如果想更明确的理解这个参数的意义,请看我在参数意义介绍完毕后补充的示意图。
flags— 插值方法与极坐标映射方法标志。两个方法之间通过“+”或者“|”号进行连接。
插值方式如下表所示:
有同学要问为什么这里要涉及到插值?
答案请访问本博文的原文获取。
本博文原文链接如下:
https://www.hhai.cc/thread-194-1-1.html
映射方法如下表所示:
从上面这个映射方法表可以看出,函数warpPolar()不仅可以实现从直角坐标系向极坐标系的转换,也能实现从极坐标系向直角坐标系的转换。
为了大家能更好的理解上面各参数的意义,特别是参数dsize和参数maxRadius的意义,补充两张示意图(建议大家放大观看)。
下边这张图上半部分是变换前的原图,下半部分是变换后的图像。左下部分是线性极坐标变换,右下部分是半对数极坐标变换。
上图中相关量的计算式和说明请访问本博文的原文查看,
本博文的原文链接如下:
https://www.hhai.cc/thread-194-1-1.html
注意:上面计算式中的
是二维直角坐标系中的一个向量,它是某点距离极坐标原点的位置向量。
也许您会觉得上面的示意图和计算公式看着挺难,但实际上一点也不复杂,只要你静下心来仔细看一看,就能很快理解明白的。
另外,如果已知一个点的极坐标(magnitude, angleRad),
还可以用一段简单的代码计算得到其在直角坐标系中的坐标,
具体的代码请访问本博文的原文获取,
本博文原文链接如下:
https://www.hhai.cc/thread-194-1-1.html
接下来,上两个函数warpPolar()使用的示例代码。
第一个示例代码:
在第一个示例代码中,我们绘制一个半径为100的圆,并且把它映射到极坐标中。
# -*- coding: utf-8 -*-
# 出处:昊虹AI笔记网(hhai.cc)
# 用心记录计算机视觉和AI技术
# 博主微信/QQ 2487872782
# QQ群 271891601
# 欢迎技术交流与咨询
# OpenCV的版本为4.4.0
import numpy as np
import cv2 as cv
Src_size = 101
Dst_size = Src_size
A = np.zeros((Src_size, Src_size), dtype='uint8')
cv.circle(A, (Src_size//2, Src_size//2), Src_size//2, 255, 1)
cv.imshow('A', A)
C = cv.warpPolar(A, (Dst_size, 360), (Src_size//2, Src_size//2), Src_size//2, cv.INTER_LINEAR + cv.WARP_POLAR_LINEAR)
cv.waitKey()
运行结果如下:
下面这张图是代码中的图像A:
图像A的部分数据如下:
图像C为图像A的极坐标变换图像,图像C的部分数据如下:
从图像C的数据来看,图A中半径为100的圆被映射到了极坐标中极半径为98,99,100的列中,并且角的度数为从0度到359度。
第二个示例代码:
在第二个示例代码中我们对钟表图进行极坐标变换,大家可以看下变换前后的效果,从而对图像极坐标变换有更形象的认识。
代码中用到的图片下载链接:
https://pan.baidu.com/s/1F-zZoKr-A3JETk5BLaNTFA?pwd=a6r0
# -*- coding: utf-8 -*-
# 出处:昊虹AI笔记网(hhai.cc)
# 用心记录计算机视觉和AI技术
# 博主微信/QQ 2487872782
# QQ群 271891601
# 欢迎技术交流与咨询
# OpenCV的版本为4.4.0
import numpy as np
import cv2 as cv
import sys
img_src = cv.imread('F:/material/images/P0048-clock_dial.jpg')
if img_src is None:
print('Error:Failed to read img')
sys.exit()
cv.imshow('img_src', img_src)
# 源图像的尺寸是338×338,所以就懒得去调属性了
img_polar = cv.warpPolar(img_src, (338, 360), (338//2, 338//2), 338//2, cv.INTER_LINEAR + cv.WARP_POLAR_LINEAR)
cv.imshow('img_polar', img_polar)
cv.waitKey()
运行结果如下图所示:
从上面的运行结果可以看出,通过直角坐标到极坐标的变换,实现了把直角坐标系中的圆“剪开并展平”的效果。
有很多同学由于老师或学校的要求,
需要直角坐标到极坐标变换的MATLAB代码,
所以博主昊虹君还用MATLAB写了下面两个函数 :
1、矩阵(图像)从直角坐标系转换到极坐系的函数;
2、将极坐标转换到直角坐标的函数;
第1个函数的原型和说明如下:
function [Rmax,polarv]=topolar(v,x0,y0,np)
% 本函数实现将单通道的图像或矩阵v从直角坐标系转化为极坐标
% (x0,y0)为要指定的极坐标原点
% np为一周等间距相位数
% Rmax为函数自动计算出的极坐标系的最大极半径
第2个函数的原型和说明如下:
function [x,y] = polartorect(angle,magnitude,x0,y0)
% 该函数实现将极坐标转换到直角坐标
% angle是某点极坐标的角度值(以度为单位)
% magnitude是某点极坐标的
% x0是极坐系的原点在直角坐标系中的横坐标值
% y0是极坐系的原点在直角坐标系中的纵坐标值
上面两个函数【函数topolar()和函数polartorect()】的Matlab代码所在文件夹详情如下:
具体的代码请大家访问本博文的原文获取,
本博文的原文链接如下:
https://www.hhai.cc/thread-194-1-1.html
第1个函数【矩阵(图像)从直角坐标系转换到极坐系的函数】的测试代码如下:
clc
close all
clear all
% 博主微信/QQ 2487872782
% 欢迎技术交流与咨询
%读取图像
ImageData=imread('F:/material/images/P0049-A_101_circle.bmp');
f1=figure(1);
set(f1,'name','原图','Numbertitle','off')
imshow(ImageData);
[rows,columns]=size(ImageData);
x0 = floor(rows/2);
y0 = floor(columns/2);
np = 360;
% Rmax中存储的是变换过程中自动计算出的最大极半值
% Rpolar_img就是经极坐标变换后的图像
[Rmax, Rpolar_img] = topolar(ImageData,x0,y0,np);
f2=figure(2);
set(f2,'name','原图的极坐标图','Numbertitle','off')
imshow(Rpolar_img);
运行结果如下图所示:
从上面的运行结果可以看出,原图中的圆形经极坐标变换后是一条垂直的直线。
函数topolar()和函数polartorect()的Matlab代码所在文件夹详情如下:
具体的代码请大家访问本博文的原文获取,
本博文的原文链接如下:
https://www.hhai.cc/thread-194-1-1.html