使用Python和极坐标变换将椭圆环展开为矩形

最近的工作中遇到了一个问题,查了挺久发现没有相应的实现方式,于是自己摸索着写了一个椭圆环展开成为矩形长条的python算法,记录一下备忘。

0x00代码

废话不多说先上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import cv2
import numpy as np
import math

def get_word_by_circle(img,circle_center,radius,radius_width):
black_img = np.zeros((radius_width,int(radius[1]*(radius[0]+radius[1])/radius[0])+500,3),dtype='uint8')
for row in range(0,black_img.shape[0]):
for col in range(0,black_img.shape[1]):
theta = 0-(math.pi*2/black_img.shape[1]*(col+1)+1.57)

rho = int((radius[0]*radius[1])/(((radius[1]**2)*(math.cos(theta)**2)+(radius[0]**2)*(math.sin(theta)**2))**0.5))-row-1

p_x = int(circle_center[0] + rho*math.cos(theta))
p_y = int(circle_center[1] - rho*math.sin(theta))

black_img[row,col,:] = img[p_y,p_x,:]

return black_img

参数解释:

  • img是用cv2.imread读入的带有椭圆的图片;circle_center指的是椭圆圆心的坐标数据,是一个列表,相对于左上角[x,y];radius是一个列表,[长轴半径,短轴半径];radius_width指的是椭圆环的宽度

最终生成的矩形长条,以椭圆环的外周长为长(实际上由于展开的是椭圆的印章,便于查看,增加了长),以椭圆环的宽度为高。函数中,从椭圆环的最外圈开始遍历,最外圈即对应着矩形中的第一行,宽度为多少,则矩形中就有多少行。以圆心为中心构成极坐标系,则圆环上任意一点可以用rho和theta来表示,再根据公式计算出该点在图上的真实坐标,把像素值赋给矩形框中对应的位置,极坐标转换公式如下所示:

0x01效果

效果图如下:

由于椭圆的定位准确度不如圆,因此展开还有一些文字扭曲问题,效果还是没有很理想,后续还会继续优化。

0x02补充

由于某些椭圆是倾斜的,因此我们需要引入一个新的参数去定义椭圆的倾斜角度inclination,单位是rad,具体实现方案参考:https://jingyan.baidu.com/article/2c8c281dfbf3dd0009252a7b.html

代码如下,增加了坐标变换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import cv2
import numpy as np
import math

def get_word_by_circle(img,circle_center,radius,radius_width,inclination):
black_img = np.zeros((radius_width,int(radius[1]*(radius[0]+radius[1])/radius[0])+500,3),dtype='uint8')
for row in range(0,black_img.shape[0]):
for col in range(0,black_img.shape[1]):
theta = 0-(math.pi*2/black_img.shape[1]*(col+1)+1.57-inclination)

rho = int((radius[0]*radius[1])/(((radius[1]**2)*(math.cos(theta)**2)+(radius[0]**2)*(math.sin(theta)**2))**0.5))-row-1

p_x = circle_center[0] + rho*math.cos(theta)
p_y = circle_center[1] - rho*math.sin(theta)
#坐标变换
px = int((p_x-circle_center[0])*math.cos(inclination)-(p_y-circle_center[1])*math.sin(inclination)+circle_center[0])
py = int((p_x-circle_center[0])*math.sin(inclination)+(p_y-circle_center[1])*math.cos(inclination)+circle_center[1])

black_img[row,col,:] = img[p_y,p_x,:]

return black_img


使用Python和极坐标变换将椭圆环展开为矩形
https://chujian521.github.io/blog/2021/03/09/使用Python和极坐标变换将椭圆环展开为矩形/
作者
Encounter
发布于
2021年3月9日
许可协议