-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathconvert.py
146 lines (137 loc) · 5.25 KB
/
convert.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys
from PIL import Image
from math import pi,sin,cos,tan,atan2,asin,acos,hypot,floor,fabs,sqrt,radians
from numpy import clip,array,matrix
# convertCoordinate from coordinate A to B
# x 是沿所求坐标系转换为原坐标系X轴旋转的角度
# y 是沿所求坐标系转换为原坐标系y轴旋转的角度
# z 是沿所求坐标系转换为原坐标系z轴旋转的角度
# sequence 是矩阵旋转的次序,0是x->y->z,1是x->z->y,2是y->x->z,3是y->z->x,4是z->x->y,5是z->y->x
def convertCoordinate(x, y, z, sequence):
mx = matrix([
[1, 0, 0],
[0, cos(x), -sin(x)],
[0, sin(x), cos(x)]
])
my = matrix([
[cos(y), 0, sin(y)],
[0, 1, 0],
[-sin(y), 0, cos(y)]
])
mz = matrix([
[cos(z), -sin(z), 0],
[sin(z), cos(z), 0],
[0, 0, 1]
])
if sequence == 0:
A = (mz.dot(my)).dot(mx)
elif sequence == 1:
A = (my.dot(mz)).dot(mx)
elif sequence == 2:
A = (mz.dot(mx)).dot(my)
elif sequence == 3:
A = (mx.dot(mz)).dot(my)
elif sequence == 4:
A = (my.dot(mx)).dot(mz)
elif sequence == 5:
A = (mx.dot(my)).dot(mz)
return A
A1 = convertCoordinate(radians(0), radians(90), radians(-45), 5)
B1 = convertCoordinate(radians(45), -asin(1.0/sqrt(3))-pi/2.0, radians(0), 2)
A2 = convertCoordinate(radians(0), radians(0), radians(45), 2)
B2 = convertCoordinate(radians(-45), asin(1.0/sqrt(3))-pi, radians(0), 2)
A3 = convertCoordinate(radians(180), radians(90), radians(-45), 1)
B3 = convertCoordinate(radians(135), asin(1.0/sqrt(3))-pi/2.0, radians(0), 2)
A4 = convertCoordinate(radians(45), radians(-90), radians(0), 3)
B4 = convertCoordinate(radians(45), asin(1.0/sqrt(3))-pi/2.0, radians(0), 2)
# get x,y,z coords from out image pixels coords
# i,j 是输出图像的xy坐标
# face 是面的号码
# halfOutSize 输出图像宽度的一半
# 将输出图像的xy值转换为三维空间中的xyz坐标,对应成一个坐标值由-1到1的立方体
def outImgToXYZ(i,j,face,halfOutSize,toward):
if (toward == 0): # front face
a = i * 4.0 / (halfOutSize * 2)
b = j * 4.0 / (halfOutSize * 2)
if face==0: # down
a = a - 2.0
b = 2.0 - b
(x,y,z) = (sqrt(3) - 1, a, b)
elif face==1: # left top
# first coordinate conversion
c = A1.dot(matrix([b-1, a-1, 0]).T)
c[2] = c[2] * sqrt(3) # stretch
# second coordinate conversion
c[0] = c[0] - (1 - sqrt(3))
c[1] = c[1] - 0
c[2] = c[2] - sqrt(2)
d = B1.dot(c)
(x,y,z) = (d[0], d[1], d[2])
elif face==2: # left bottom
# first coordinate conversion
c = A2.dot(matrix([b-3, a-1, 0]).T)
c[0] = c[0] * sqrt(3) # stretch
# second coordinate conversion
c[0] = c[0] - sqrt(2)
c[1] = c[1] - 0
c[2] = c[2] - (1 - sqrt(3))
d = B2.dot(c)
(x,y,z) = (d[0], d[1], d[2])
elif face==3: # right top
# first coordinate conversion
c = A3.dot(matrix([b-1, a-3, 0]).T)
c[2] = c[2] * sqrt(3) # stretch
# second coordinate conversion
c[0] = c[0] - (sqrt(3) - 1)
c[1] = c[1] - 0
c[2] = c[2] - sqrt(2)
d = B3.dot(c)
(x,y,z) = (d[0], d[1], d[2])
elif face==4: # right bottom
# first coordinate conversion
c = A4.dot(matrix([b-3, a-3, 0]).T)
c[2] = c[2] * sqrt(3) # stretch
# second coordinate conversion
c[0] = c[0] - (sqrt(3) - 1)
c[1] = c[1] - 0
c[2] = c[2] - sqrt(2)
d = B4.dot(c)
(x,y,z) = (d[0], d[1], d[2])
return (x,y,z)
# convert using an inverse transformation
def convertBack(imgIn,imgOut):
inSize = imgIn.size
outSize = imgOut.size
inPix = imgIn.load()
outPix = imgOut.load()
edge = inSize[0]/4 # 视角宽度
halfOutSize = outSize[0] / 2;
for i in xrange(outSize[0]):
for j in xrange(outSize[1]):
face = 0
if fabs(halfOutSize - i) + fabs(halfOutSize - j) <= halfOutSize:
face = 0
elif (i < halfOutSize) and (j < halfOutSize):
face = 1 # 左上角
elif (i < halfOutSize) and (j > halfOutSize):
face = 2 # 左下角
elif (i > halfOutSize) and (j < halfOutSize):
face = 3 # 右上角
elif (i > halfOutSize) and (j > halfOutSize):
face = 4 # 右下角
(x,y,z) = outImgToXYZ(i,j,face,halfOutSize, 0)
theta = atan2(y,x) # 水平方向夹角
r = hypot(x,y)
phi = atan2(z,r) # 垂直方向夹角
# 对应原图像的坐标值
uf = ( 2.0*edge*(theta + pi) / pi )
vf = ( 2.0*edge * (pi/2 - phi)/pi)
outPix[i,j] = inPix[int(uf) % inSize[0], clip(vf,0,inSize[1]-1)]
imgIn = Image.open("2.jpg")
inSize = imgIn.size
imgOut = Image.new("RGB",((int)(inSize[0] / 4 * sqrt(2)) , (int)(inSize[0] / 4 * sqrt(2))),"black")
convertBack(imgIn,imgOut)
imgOut.save("out.jpg")
imgOut.show()