昊虹AI笔记网

 找回密码
 立即注册
搜索
查看: 1935|回复: 0
收起左侧

详解OpenCV实现图像直角坐标系转极坐标系的函数warpPolar(),并附自己写的实现直角坐标系转极坐标系的MATLAB代码

[复制链接]

238

主题

241

帖子

931

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
931
昊虹君 发表于 2022-12-27 12:52 | 显示全部楼层 |阅读模式
详解OpenCV实现图像直角坐标系转极坐标系的函数warpPolar(),并附自己写的实现直角坐标系转极坐标系的MATLAB代码

有些时候我们需要把图像或矩阵从直角坐标系(笛卡尔坐标系)转换到极坐标,这个过程通常称为图像的极坐标变换。

图像的极坐标变换一个常见的作用是可以将将一圆形图像变换成一个矩形图像,类似于把圆剪开铺平。这样可以方便我们处理钟表、圆盘等图像。图形上的圆形排列文字经过及坐标变换后可以垂直的排列在新图像上,便于对文字的识别和检测。
示意图如下:


OpenCV4中新增加了函数warpPolar()用于将图像或矩阵从直角坐标系(笛卡尔坐标系)转换到极坐标。

其C++原型如下:
  1. void cv::warpPolar(InputArray         src,
  2.                    OutputArray dst,
  3.                    Size         dsize,
  4.                    Point2f  center,
  5.                    double         maxRadius,
  6.                    int         flags )
复制代码

其Python原型如下:
  1. dst = cv.warpPolar(src, dsize, center, maxRadius, flags[, dst])
复制代码

参数意义如下:
src---原图像,对通道数无要求,可以是灰度图像或者彩色图像。
dst---输出图像,它和原图像具有相同的数据类型和通道数,注意没有说尺寸相同哈。
dsize---目标图像大小,如图不填这个值或dsize两个值中的某个值,那么按下面的规则计算:

center---极坐标变换时原点坐标。
maxRadius---极坐标系的极半径最大值,如果想更明确的理解这个参数的意义,请看我在参数意义介绍完毕后补充的示意图。
flags--- 插值方法与极坐标映射方法标志。两个方法之间通过“+”或者“|”号进行连接。
插值方式如下表所示:

这里说下为什么要涉及到插值?
因为我们的变换本质上是在离散序列中进行的,而不是在连续域中进行的,这就导致两个坐标系的点与点之间并不能一一对应。
为了尽可能保证目标矩阵中的每个点的值的准确性,我们就要进行插值处理。如果想对这个问题作更深入的理解,那么看本文最后附的利用MATLAB实现的直角坐标系转极坐标系的代码。

映射方法如下表所示:

从上面这个映射方法表可以看出,函数warpPolar()不仅可以实现从直角坐标系向极坐标系的转换,也能实现从极坐标系向直角坐标系的转换。

为了大家能更好的理解上面各参数的意义,特别是参数dsize和参数maxRadius的意义,补充两张示意图(建议大家放大观看)。
下边这张图上半部分是变换前的原图,下半部分是变换后的图像。左下部分是线性极坐标变换,右下部分是半对数极坐标变换。


图中相关量的计算式如下:

注意:上面计算式中是二维直角坐标系中的一个向量,它是某点距离极坐标原点的位置向量。
也许您会觉得上面的示意图和计算公式看着挺难,但实际上一点也不复杂,只要你静下心来仔细看一看,就能很快理解明白的。
另外,如果已知一个点的极坐标(magnitude, angleRad),可以用下面的代码进行计算得到其直角系的坐标(x, y):
[Python] 纯文本查看 复制代码
double angleRad, magnitude;
double Kangle = dst.rows / CV_2PI;
angleRad = phi / Kangle;
if (flags & WARP_POLAR_LOG)
{
    double Klog = dst.cols / std::log(maxRadius);
    magnitude = std::exp(rho / Klog);
}
else
{
    double Klin = dst.cols / maxRadius;
    magnitude = rho / Klin;
}
int x = cvRound(center.x + magnitude * cos(angleRad));
int y = cvRound(center.y + magnitude * sin(angleRad));


接下来,上两个函数warpPolar()使用的示例代码。

第一个示例代码:
在第一个示例代码中,我们绘制一个半径为100的圆,并且把它映射到极坐标中。
[Python] 纯文本查看 复制代码
# -*- 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
[Python] 纯文本查看 复制代码
# -*- 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个函数的原型和说明如下:
  1. function [Rmax,polarv]=topolar(v,x0,y0,np)
  2. % 本函数实现将单通道的图像或矩阵v从直角坐标系转化为极坐标
  3. % (x0,y0)为要指定的极坐标原点
  4. % np为一周等间距相位数
  5. % Rmax为函数自动计算出的极坐标系的最大极半径
复制代码

第2个函数的原型和说明如下:
  1. function [x,y] = polartorect(angle,magnitude,x0,y0)
  2. % 该函数实现将极坐标转换到直角坐标
  3. % angle是某点极坐标的角度值(以度为单位)
  4. % magnitude是某点极坐标的
  5. % x0是极坐系的原点在直角坐标系中的横坐标值
  6. % y0是极坐系的原点在直角坐标系中的纵坐标值
复制代码


上面两个函数的Matlab代码所在文件夹详情如下:

代码的百度网盘下载链接请各位朋友移步淘宝花费5元购买(自动发货):
淘宝购买链接:https://item.taobao.com/item.htm?ft=t&id=695628192081

第1个函数【矩阵(图像)从直角坐标系转换到极坐系的函数】的测试代码如下:
[Python] 纯文本查看 复制代码
% 出处:昊虹AI笔记网(hhai.cc)
% 用心记录计算机视觉和AI技术

% 博主微信/QQ 2487872782
% QQ群 271891601
% 欢迎技术交流与咨询

clc
close all
clear all

%读取图像
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代码所在文件夹详情如下:

代码的百度网盘下载链接请各位朋友移步淘宝花费5元购买(自动发货):
淘宝购买链接:https://item.taobao.com/item.htm?ft=t&id=695628192081
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|昊虹AI笔记网 ( 蜀ICP备2024076726 )

GMT+8, 2024-5-19 09:31 , Processed in 0.024594 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表