Jika Anda ingin melakukannya di sisi server ada banyak pilihan. http://www.imagemagick.org/ memiliki banyak alat baris perintah yang dapat mengiris gambar Anda menjadi beberapa bagian . Anda dapat memasukkan perintah untuk melakukan ini ke dalam skrip dan menjalankannya setiap kali Anda memiliki gambar baru.
Sulit untuk mengetahui algoritma apa yang digunakan dalam program ini. Kita dapat mencoba dan merekayasa balik apa yang terjadi dengan memasukkan kotak persegi ke dalam program. Saya telah menggunakan grid dari wikipedia
Yang memberi Ini memberi kita petunjuk tentang bagaimana kotak itu dibuat.
Pencitraan bola dengan garis lintang dan bujur di salah satunya, dan kubus yang mengelilinginya. Sekarang proyek dari titik di tengah bola menghasilkan grid terdistorsi pada kubus.
Secara matematis ambil koordinat kutub r, θ, ø, untuk bola r=1, 0 ‹ θ ‹ π, -π/4 ‹ ø ‹ 7π/4
- x= r dosa θ cos ø
- kamu= r dosa θ dosa ø
- z= r karena θ
memproyeksikan ini secara terpusat ke kubus. Pertama kita bagi menjadi empat wilayah berdasarkan garis lintang -π/4 ‹ ø ‹ π/4, π/4 ‹ ø ‹ 3π/4, 3π/4 ‹ ø ‹ 5π/4, 5π/4 ‹ ø ‹ 7π/4. Ini akan memproyeksikan ke salah satu dari empat sisi atas atau bawah.
Asumsikan kita berada di sisi pertama -π/4 ‹ ø ‹ π/4. Proyeksi sentral dari (sin θ cos ø, sin θ sin ø, cos θ) adalah (a sin θ cos ø, a sin θ sin ø, a cos θ) yang mengenai bidang x=1 ketika
so
dan titik yang diproyeksikan adalah
- (1, tan ø, tempat tidur θ / cos ø)
Jika | tempat tidur θ / cos ø | ‹ 1 ini akan berada di bagian depan. Jika tidak, itu akan diproyeksikan ke atas atau bawah dan Anda memerlukan proyeksi berbeda untuk itu. Pengujian yang lebih baik untuk bagian atas menggunakan fakta bahwa nilai minimum cos ø adalah cos π/4 = 1/√2, sehingga titik proyeksi selalu berada di atas jika cot θ / (1/√2) > 1 atau tan θ ‹ 1/√2. Hasilnya adalah θ ‹ 35º atau 0,615 radian.
Gabungkan ini dengan python
import sys
from PIL import Image
from math import pi,sin,cos,tan
def cot(angle):
return 1/tan(angle)
# Project polar coordinates onto a surrounding cube
# assume ranges theta is [0,pi] with 0 the north poll, pi south poll
# phi is in range [0,2pi]
def projection(theta,phi):
if theta<0.615:
return projectTop(theta,phi)
elif theta>2.527:
return projectBottom(theta,phi)
elif phi <= pi/4 or phi > 7*pi/4:
return projectLeft(theta,phi)
elif phi > pi/4 and phi <= 3*pi/4:
return projectFront(theta,phi)
elif phi > 3*pi/4 and phi <= 5*pi/4:
return projectRight(theta,phi)
elif phi > 5*pi/4 and phi <= 7*pi/4:
return projectBack(theta,phi)
def projectLeft(theta,phi):
x = 1
y = tan(phi)
z = cot(theta) / cos(phi)
if z < -1:
return projectBottom(theta,phi)
if z > 1:
return projectTop(theta,phi)
return ("Left",x,y,z)
def projectFront(theta,phi):
x = tan(phi-pi/2)
y = 1
z = cot(theta) / cos(phi-pi/2)
if z < -1:
return projectBottom(theta,phi)
if z > 1:
return projectTop(theta,phi)
return ("Front",x,y,z)
def projectRight(theta,phi):
x = -1
y = tan(phi)
z = -cot(theta) / cos(phi)
if z < -1:
return projectBottom(theta,phi)
if z > 1:
return projectTop(theta,phi)
return ("Right",x,-y,z)
def projectBack(theta,phi):
x = tan(phi-3*pi/2)
y = -1
z = cot(theta) / cos(phi-3*pi/2)
if z < -1:
return projectBottom(theta,phi)
if z > 1:
return projectTop(theta,phi)
return ("Back",-x,y,z)
def projectTop(theta,phi):
# (a sin θ cos ø, a sin θ sin ø, a cos θ) = (x,y,1)
a = 1 / cos(theta)
x = tan(theta) * cos(phi)
y = tan(theta) * sin(phi)
z = 1
return ("Top",x,y,z)
def projectBottom(theta,phi):
# (a sin θ cos ø, a sin θ sin ø, a cos θ) = (x,y,-1)
a = -1 / cos(theta)
x = -tan(theta) * cos(phi)
y = -tan(theta) * sin(phi)
z = -1
return ("Bottom",x,y,z)
# Convert coords in cube to image coords
# coords is a tuple with the side and x,y,z coords
# edge is the length of an edge of the cube in pixels
def cubeToImg(coords,edge):
if coords[0]=="Left":
(x,y) = (int(edge*(coords[2]+1)/2), int(edge*(3-coords[3])/2) )
elif coords[0]=="Front":
(x,y) = (int(edge*(coords[1]+3)/2), int(edge*(3-coords[3])/2) )
elif coords[0]=="Right":
(x,y) = (int(edge*(5-coords[2])/2), int(edge*(3-coords[3])/2) )
elif coords[0]=="Back":
(x,y) = (int(edge*(7-coords[1])/2), int(edge*(3-coords[3])/2) )
elif coords[0]=="Top":
(x,y) = (int(edge*(3-coords[1])/2), int(edge*(1+coords[2])/2) )
elif coords[0]=="Bottom":
(x,y) = (int(edge*(3-coords[1])/2), int(edge*(5-coords[2])/2) )
return (x,y)
# convert the in image to out image
def convert(imgIn,imgOut):
inSize = imgIn.size
outSize = imgOut.size
inPix = imgIn.load()
outPix = imgOut.load()
edge = inSize[0]/4 # the length of each edge in pixels
for i in xrange(inSize[0]):
for j in xrange(inSize[1]):
pixel = inPix[i,j]
phi = i * 2 * pi / inSize[0]
theta = j * pi / inSize[1]
res = projection(theta,phi)
(x,y) = cubeToImg(res,edge)
#if i % 100 == 0 and j % 100 == 0:
# print i,j,phi,theta,res,x,y
if x >= outSize[0]:
#print "x out of range ",x,res
x=outSize[0]-1
if y >= outSize[1]:
#print "y out of range ",y,res
y=outSize[1]-1
outPix[x,y] = pixel
imgIn = Image.open(sys.argv[1])
inSize = imgIn.size
imgOut = Image.new("RGB",(inSize[0],inSize[0]*3/4),"black")
convert(imgIn,imgOut)
imgOut.show()
Fungsi projection
mengambil nilai theta
dan phi
dan mengembalikan koordinat dalam kubus dari -1 hingga 1 di setiap arah. cubeToImg mengambil koordinat (x,y,z) dan menerjemahkannya ke koordinat gambar keluaran.
Algoritme di atas sepertinya mendapatkan geometri yang benar dengan menggunakan gambar istana buckingham kita mendapatkan < img src="https://i.stack.imgur.com/rfgE8.png" alt="peta kubus istana buckingham"> Tampaknya ini membuat sebagian besar garis di paving benar.
Kami mendapatkan beberapa artefak gambar. Hal ini disebabkan tidak memiliki peta piksel 1 banding 1. Yang perlu kita lakukan adalah menggunakan transformasi terbalik. Daripada mengulang setiap piksel di sumber dan menemukan piksel yang sesuai di target, kita mengulangi gambar target dan menemukan piksel sumber terdekat yang sesuai.
import sys
from PIL import Image
from math import pi,sin,cos,tan,atan2,hypot,floor
from numpy import clip
# get x,y,z coords from out image pixels coords
# i,j are pixel coords
# face is face number
# edge is edge length
def outImgToXYZ(i,j,face,edge):
a = 2.0*float(i)/edge
b = 2.0*float(j)/edge
if face==0: # back
(x,y,z) = (-1.0, 1.0-a, 3.0 - b)
elif face==1: # left
(x,y,z) = (a-3.0, -1.0, 3.0 - b)
elif face==2: # front
(x,y,z) = (1.0, a - 5.0, 3.0 - b)
elif face==3: # right
(x,y,z) = (7.0-a, 1.0, 3.0 - b)
elif face==4: # top
(x,y,z) = (b-1.0, a -5.0, 1.0)
elif face==5: # bottom
(x,y,z) = (5.0-b, a-5.0, -1.0)
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 # the length of each edge in pixels
for i in xrange(outSize[0]):
face = int(i/edge) # 0 - back, 1 - left 2 - front, 3 - right
if face==2:
rng = xrange(0,edge*3)
else:
rng = xrange(edge,edge*2)
for j in rng:
if j<edge:
face2 = 4 # top
elif j>=2*edge:
face2 = 5 # bottom
else:
face2 = face
(x,y,z) = outImgToXYZ(i,j,face2,edge)
theta = atan2(y,x) # range -pi to pi
r = hypot(x,y)
phi = atan2(z,r) # range -pi/2 to pi/2
# source img coords
uf = ( 2.0*edge*(theta + pi)/pi )
vf = ( 2.0*edge * (pi/2 - phi)/pi)
# Use bilinear interpolation between the four surrounding pixels
ui = floor(uf) # coord of pixel to bottom left
vi = floor(vf)
u2 = ui+1 # coords of pixel to top right
v2 = vi+1
mu = uf-ui # fraction of way across pixel
nu = vf-vi
# Pixel values of four corners
A = inPix[ui % inSize[0],clip(vi,0,inSize[1]-1)]
B = inPix[u2 % inSize[0],clip(vi,0,inSize[1]-1)]
C = inPix[ui % inSize[0],clip(v2,0,inSize[1]-1)]
D = inPix[u2 % inSize[0],clip(v2,0,inSize[1]-1)]
# interpolate
(r,g,b) = (
A[0]*(1-mu)*(1-nu) + B[0]*(mu)*(1-nu) + C[0]*(1-mu)*nu+D[0]*mu*nu,
A[1]*(1-mu)*(1-nu) + B[1]*(mu)*(1-nu) + C[1]*(1-mu)*nu+D[1]*mu*nu,
A[2]*(1-mu)*(1-nu) + B[2]*(mu)*(1-nu) + C[2]*(1-mu)*nu+D[2]*mu*nu )
outPix[i,j] = (int(round(r)),int(round(g)),int(round(b)))
imgIn = Image.open(sys.argv[1])
inSize = imgIn.size
imgOut = Image.new("RGB",(inSize[0],inSize[0]*3/4),"black")
convertBack(imgIn,imgOut)
imgOut.save(sys.argv[1].split('.')[0]+"Out2.png")
imgOut.show()
Hasilnya adalah
person
Salix alba
schedule
16.04.2015