![]() |
|
|
|
|
|
||||||||||
|
| User list | Rules | You are not logged in.
Pages: 1 2
Has anyone been able to generate an .xml?
Used Dashcode on the Mac and added some code from an earlier post. Works great! Thanks! Gurl!
Last edited by gerardm (2010-07-02 06:09:28)
Offline
I have spent some time making presets for papywizard but they were never quite right
so after members pointing me to the Papyspheric preset maker i read all the info and had a go.
I used portable Python and changed the settings in the program to suite my camera and ran it.
A couple of things that i found that may be useful are that you cannot select and paste the output using the right click mouse
in windows as it does not work so you have to select all the text and use control + V on the keyboard which does copy it all.
The second thing is that if you paste the text into Notepad it makes a bit of a mess even with word wrap selected
which makes it very difficult to see what's going on, i found if you use Wordpad instead it looks the same as the program output
and is very easy to see and edit.
You can save the file as a RTF as a backup which keeps all the text in order when you load it again.
The output for my camera did not look right when i first looked at it and the pitch values seemed as if they would
not work correctly but i spent some time copying and pasting into a XML file for the preset and thought i would test it out.
I was very pleasantly surprised after taking all the images on the Merlin and putting them through Autopano that it stitched
almost perfectly and was one of the best presets i had got so far.
I should have had a lot more faith and would just like to say thanks to the Author Georges (GURL)
for taking the time to write a great little program which is very useful to create presets.
One thing i would love to see if its at all possible and if Georges has the time and this would be that the output
of the program be in a similar order to presets with 0 being straight ahead and +90 at top and -90 at the nadir.
It would make it so much easier to copy the coordinates over to make the preset and probably cut down on mistakes
when copying all the numbers across.
Thanks again
Steve
Offline
Hello
Python 2.6.4 installed, copied the code and saved as a .py file
module runs but just open another python window with nothing inside ....
What is the problem ?
Thanks
Rick
Last edited by Rick (2011-04-10 10:33:17)
Offline
The problem is that papyspheric want Python 3.1 (not 2.6.4)
Though this was probably a mistake, not knowing the customs of the Python country I used the most recent stable version...
Offline
Ok i might not be a super coder, but here's a minor edit:
Changed:
1:Now adds "<pict " and "/>" to each pictch/yaw position in the output for easier conversion to xml
2:The direction of each row is reversed relative to the previous, to keep the head from swinging all the way back to the start, i.e will now go:
>>>>>>
<<<<<<
>>>>>>
rather than
>>>>>>
>>>>>>
>>>>>>
3:added a couple more data points to the sensor sizes at the start of the script
# Version 0.0.2 - mardi 19 Avril 2011
##########----------##########----------##########----------##########----------
# my camera: 23 x 15.5 mm
# Olypus: 13 x 17.3 mm
# Nikon APS-C: 23.6 x 15.8 mm
# Pentax K20D 23.4 x 15.6 mm
# Canon APS-C: 22.3 x 14.9 mm
# Full frame: 36 x 24mm
##################### THE 9 PARAMETERS YOU MUST SET ARE THERE
# ##################################################
f= 50 # mm, for example 50 mm
Vside= 22.3 # mm, for example 36 mm \ portrait / landscape
Hside= 14.9 # mm, for example 24 mm / orientation found there
phiMin= -90 # degrees, from -90 (nadir) toward 90
phiMax= 90 # degrees, up to 90 (zenith) toward -90
Hoverlap= 0.5 # horizontal overlap, coef from 0 to 0.5 (0% to 50 %)
Voverlap= 0.5 # vertical overlap, coef from 0 up to more than 0.5
#
panoheadPhiMin= -90 # degrees, from -90 (nadir) \ avoids the camera or lens
panoheadPhiMax= 90 # degrees, up to 90 (zenith) / hitting the pano head !
#
#####################
from math import *
assert f > 1 and f < 1001, "f: improper focal length"
assert Vside > 1 and Vside < 100, "Vside: improper size"
assert Hside > 1 and Hside < 100, "Vside: improper size"
assert phiMin >= -90 and phiMin < 85, "phiMin not between -90 and +85"
assert phiMax <= 90 and phiMax > -85, "phiMax not between -85 and +90"
assert phiMin != phiMax, "phiMin, phiMax: min and max are equal"
assert phiMin < phiMax, "phiMin, phiMax: min and max are inverted"
assert Hoverlap >= 0, "Hoverlap: minimum possible value is 0"
assert Hoverlap < 0.96, "Hoverlap: maximum possible value is 0.95"
assert Voverlap >= 0, "Voverlap: minimum value is 0"
assert Voverlap < 0.96, "Voverlap: maximum value is 0.95"
assert panoheadPhiMin >= -90, "panoheadPhiMin: extreme value is -90"
assert panoheadPhiMax <= 90, "panoheadPhiMax: maximum value is 90"
assert panoheadPhiMin < panoheadPhiMax, "panoheadPhiMin, panoheadPhiMax:" \
+ "Pano-head extreme top & bottom positions are stupid!"
trueVside= Vside
trueHside= Hside
trueVfov= degrees(2 * atan (trueVside / 2 / f))
trueHfov= degrees(2 * atan (trueHside / 2 / f))
if phiMax - trueVfov / 2 > panoheadPhiMax :
print("\nCAUTION! ...panorama phiMax incompatible",
"with pano-head phiMax has been reduced!\n")
phiMax= panoheadPhiMax - trueVfov / 2
if phiMin + trueVfov / 2 < panoheadPhiMin :
phiMin= panoheadPhiMin + trueVfov / 2
print("\nCAUTION! ...panorama phiMin incompatible",
"with pano-head phiMin has been adjusted!\n")
truePhiMin= phiMin
truePhiMax= phiMax
##########----------##########----------##########----------##########----------
print("Camera:")
print(" Sensor size ", repr(trueHside)[0:4] + " x " + repr(trueVside),"mm")
print(" Focal length ", repr(f)[0:5], "mm")
print(" Lens vertical FOV ", round(degrees(2 * atan (trueVside / 2 / f))), "deg")
print(" Lens horizontal FOV ", round(degrees(2 * atan (trueHside / 2 / f))), "deg")
print("\nPanorama:")
print(" Top at ", repr(phiMax)[0:5], "deg")
print(" Bottom at ", repr(phiMin)[0:5], "deg")
print(" vertical FOV ", repr(phiMax - phiMin)[0:5], "deg")
print(" Vertical overlap ", repr(int(100 * Voverlap))+" %")
print(" Horizontal overlap ", repr(int(100 * Hoverlap))+" %")
if panoheadPhiMin != -90 or panoheadPhiMax != 90 :
print("\nPano-head:")
if panoheadPhiMin != -90 :
print(" downward limit", int(panoheadPhiMin), " deg")
if panoheadPhiMax != 90 :
print(" upward limit", int(panoheadPhiMax), " deg")
print(" ")
##########----------##########----------##########----------##########----------
totalImgNb= int(0)
if trueVfov > trueHfov :
optimalZenith= 90 - ((trueVfov - trueHfov) / 2)
optimalNadir= -90 + ((trueVfov - trueHfov) / 2)
else :
optimalZenith = 90
optimalNadir = -90 # overlap between zenith disc and top row
#########################################
if panoheadPhiMax >= optimalZenith \
and truePhiMax > 90 - (trueHfov / 2 * (1 - max(Voverlap, Hoverlap))) :
zenith= "yes"
phiMax= phiMax - (min(trueHfov, trueVfov) / 2 * (1 - max(Voverlap, Hoverlap)))
totalImgNb= totalImgNb + 1
else :
zenith= "no" # no overlap with zenith hole is wanted
phiMax= phiMax - (trueVfov * Voverlap / 2)
print("# phiMax moved downward by", repr(trueVfov * Voverlap / 2)[0:5],
"deg -----------------------> 0 % overlap with zenith hole")
if (panoheadPhiMin <= optimalNadir) \
and abs(truePhiMin) > 90 - (trueVfov / 2 * (1 - max(Voverlap, Hoverlap))) :
nadir= "yes"
phiMin= phiMin + (min(trueHfov, trueVfov) / 2 * (1 - max(Voverlap, Hoverlap)))
totalImgNb= totalImgNb + 1
else :
nadir= "no" # no overlap with nadir hole is wanted
phiMin= phiMin + (trueVfov * Voverlap / 2)
print("# phiMin moved upward by", repr(trueVfov * Voverlap / 2)[0:5],
"deg -------------------------> 0 % overlap with nadir hole")
Vfov= trueVfov * (1 - Voverlap)
Hfov= trueHfov * (1 - Hoverlap)
Vside= 2 * f * tan(radians(Vfov / 2))
Hside= 2 * f * tan(radians(Hfov / 2))
linV= 1 - Vside / trueVside # Out of disc part of zenith and/or nadir
linH= 1 - Hside / trueHside # not taken into account tough it should be!
if int(linV) != int(linH) :
print("# Linear vertical overlap --> ", repr(100 * (linV))[0:5],
"% of source pixels")
print("# Linear horizontal overlap --> ", repr(100 * (linH))[0:5],
"% of source pixels")
else :
print("# Linear overlap --> ", repr(100 * (linV))[0:5],
"% of source pixels")
anglV= 1 - Vfov / trueVfov # idem about out of disc part of zenith, nadir
anglH= 1 - Hfov / trueHfov
if int(100 * (anglV + anglH)) != int(100 * (linV + linH)) :
if int(anglV) != int(anglH) :
print("# Angular vertical overlap --> ", repr(100 * anglV)[0:5], "%")
print("# Angular horizontal overlap --> ", repr(100 * anglH)[0:5], "%")
else :
print("# Angular overlap --> ", repr(100 * anglV)[0:5], "%")
rowNb= (phiMax - phiMin) // Vfov
if rowNb * Vfov < phiMax - phiMin :
rowNb= rowNb + 1
dPitch= (phiMax - phiMin) / rowNb
sigmaPhi= rowNb * trueVfov
if nadir == "yes" :
sigmaPhi= sigmaPhi + (trueVfov + trueHfov )/ 2 / 2 # sic!
if zenith == "yes" :
sigmaPhi= sigmaPhi + + (trueVfov + trueHfov )/ 2 / 2 # sic!
VangularExcess= (sigmaPhi - (truePhiMax - truePhiMin)) / sigmaPhi
##########----------##########----------##########----------##########----------
toPrint= "\n" + "Number of rows: " + repr(int(rowNb))
if zenith == "yes" :
toPrint= toPrint + " + zenith"
if nadir == "yes" :
toPrint= toPrint + " + nadir"
print (toPrint + "\n")
print("# Lens vertical angles : ",
repr(trueVfov * Voverlap / 2)[0:4], "+", repr(Vfov)[0:4], "+",
repr(trueVfov * Voverlap / 2)[0:4], "=",repr(trueVfov)[0:4] + " deg")
print("# Lens horizontal angles : ",
repr(trueHfov * Hoverlap / 2)[0:4], "+", repr(Hfov)[0:4], "+",
repr(trueHfov * Hoverlap / 2)[0:4], "=", repr(trueHfov)[0:4] + " deg")
if zenith == "yes" or nadir == "yes" :
if Hfov < Vfov :
print("# Zenith and Nadir angles: ", repr(Hfov / 2)[0:4], "+",
repr(trueHfov * Hoverlap / 2)[0:4], "=",
repr(trueHfov / 2)[0:4] + "deg")
else :
print("# Zenith and Nadir angles: ", repr(Vfov / 2)[0:4], "+",
repr(trueVfov * Voverlap / 2)[0:4], "=",
repr(trueVfov / 2)[0:4] + " deg")
print("# Modified phiMax = " + repr(phiMax)[0:4] + " deg")
print("# Modified phiMin = " + repr(phiMin)[0:5] + " deg")
print("# Row to row delta Pitch = " +
repr(dPitch)[0:4] + " deg -----------------------> " +
repr(int(100 * VangularExcess)) +
" % vertical angular excess (total angle: " +
repr(int(sigmaPhi)) + " deg)")
print("#############################")
##########----------##########----------##########----------##########----------
if nadir== "yes" :
if trueVfov > trueHfov :
print("\nNadir shoot at " + repr(optimalNadir)[0:5] + " deg\n")
else :
print("\nNadir shoot at -90 deg\n")
pitchList= [repr(optimalNadir)[0:5]] ## 1 ##
imgNbList= [int(1)] ## 2 ##
imgYawList= ["0.0"] ## 3 ##
else :
pitchList= [] ## 1 ##
imgNbList= [] ## 2 ##
imgYawList= [] ## 3 ##
if rowNb != 1 :
prevTop= phiMin
else :
prevTop= (phiMin + phiMax) / 2 - Vfov / 2
i= 0
while i < rowNb : # begin rows loop <-----------------------------
bottom= prevTop
top= prevTop + dPitch
pitch= (bottom + top) / 2
if pitch < 0 :
pitchList= pitchList + [repr(pitch)[0:5]] ## 1 ##
else :
pitchList= pitchList + [repr(pitch)[0:4]] ## 1 ##
if abs(bottom) < abs(top) : # the smaller the distance
largeCirclePitch= abs(bottom) # between a circle and the equator
smallCirclePitch= abs(top) # ... the larger this circle is
else:
largeCirclePitch= abs(top)
smallCirclePitch= abs(bottom)
largePitch= largeCirclePitch
midlePitch= (largeCirclePitch + smallCirclePitch) / 2
smallPitch= smallCirclePitch
# midlePitch (degrees, unsigned) points to the circle where images
# sides must be adjacent
MoHSD= f / cos(radians(dPitch / 2)) # MoHSD: Middle of Horizontal Sides
# Distance from sphere center
circleRadius= MoHSD * cos (radians(midlePitch))
largeRadius= MoHSD * cos (radians(largePitch))
smallRadius= MoHSD * cos (radians(smallPitch))
# angle under which is seen an image (decreased for overlap) in the:
unadjdYaw= degrees(2 * (atan(Hside / 2 / circleRadius))) # middle circle horizontal plane
largedYaw= degrees(2 * (atan(trueHside / 2 / largeRadius)))# largest circle horizontal plane
smalldYaw= degrees(2 * (atan(trueHside / 2 / smallRadius)))# smallest circle horizontal plane
imgNb= 360 // unadjdYaw
if imgNb * unadjdYaw < 360 :
imgNb = imgNb + 1
dYaw = 360 / imgNb
if largedYaw < dYaw :
imgNb= 360 // largedYaw
if imgNb * largedYaw < 360 :
imgNb = imgNb + 1
dYaw = 360 / imgNb
selected= "# based on LARGE circle, dYaw: " + repr(dYaw)[0:5] + " deg"
else :
selected= "# based on MIDLE circle, dYaw: " + repr(dYaw)[0:5] + " deg"
imgNbList= imgNbList + [int(imgNb)] ## 2 ##
HexcessContiguous= (imgNb * unadjdYaw - 360) / 360
toPrint = "\nrow " + repr(i + 1).ljust(2) + " of " + repr(int(rowNb)) \
+ ", pitch: " + repr(int(pitch)) \
+ " deg # top overlap at " + repr(int(round(top))) \
+ " deg, bottom overlap at " + repr(int(round(bottom))) + " deg"
print (toPrint)
print(" " + selected)
if abs(round(top)) == abs(round(bottom)) :
toPrint= " # large circle is any -----> "
elif largeCirclePitch == abs(bottom) :
toPrint= " # large circle at bottom --> "
else:
toPrint= " # large circle at top -----> "
HexcessLarge= (largedYaw - dYaw) / largedYaw
toPrint= toPrint + repr(int(100 * HexcessLarge)) + " % overlap"
print (toPrint)
toPrint= " deg # small circle ------------> "
HexcessSmall= (smalldYaw - dYaw) / smalldYaw
toPrint= toPrint + repr(int(100 * HexcessSmall)) + " % overlap"
print (toPrint)
dYaw = 360 / imgNb
j= 0 # begin images loop <-----------------
while j < imgNb :
imgYawList= imgYawList + [repr(j * dYaw)[0:5]] ## 3 ##
totalImgNb= totalImgNb + 1
print (" ", repr(j + 1).ljust(2), "yaw:", int(j * dYaw))
j= j + 1 # end images loop <-----------------
i= i + 1
prevTop= top # end rows loop <-------------------
##########----------##########----------##########----------##########----------
if zenith == "yes" :
if trueVfov > trueHfov :
print("\nZenith shoot at " + repr(optimalZenith)[0:4] + " deg")
else :
print("\nZenith shoot at 90 deg")
pitchList= pitchList + [repr(optimalZenith)[0:4]] ## 1 ##
imgNbList= imgNbList + [int(1)] ## 2 ##
imgYawList= imgYawList + ["0.0"] ## 3 ##
print("\nTotal number of images: " + repr(totalImgNb) + "\n")
##########----------##########----------##########----------##########----------
print("#############################\n")
k= 0
for i in range(len(pitchList)) :
pitchString= 'pitch="' + pitchList[i] + '" yaw="'
if pitchString[7] == '-' and pitchString[9] == '.' :
pitchString= pitchString[0:10]+pitchString[11:]
if i%2!=0:
for j in range(imgNbList[i]) :
yawString= imgYawList[k] + '"'; k= k + 1;
print("<pict " + pitchString + yawString +"/>")
else:
for j in range(imgNbList[i]) :
yawString= imgYawList[k+imgNbList[i]-2*j-1] + '"'; k= k + 1;
print("<pict " + pitchString + yawString +"/>")
print("")
print("#############################")
#print("the following is buggy...")
#totalArea= totalImgNb * trueVside * trueHside
#imgDiag = sqrt((trueVside)**2 + (trueHside)**2)
#r = sqrt(f**2 + (imgDiag / 2)**2)
#wrapingCylinderHeight = r * ( sin(radians(abs(truePhiMax)))
# + sin(radians(abs(truePhiMin))))
#wrapingCylinderArea= 2 * pi * r * wrapingCylinderHeight
######################Last edited by wjh31 (2011-04-19 10:06:08)
Offline
I modified the code to write to an xml file, and it takes an argument for focal length. Just setup the script for your camera, and then run it with the desired focal length.
# Version 0.0.3 - Oct 16, 2011
##########----------##########----------##########----------##########----------
# my camera: 23 x 15.5 mm
# Olypus: 13 x 17.3 mm
# Nikon APS-C: 23.6 x 15.8 mm
# Pentax K20D 23.4 x 15.6 mm
# Canon APS-C: 22.3 x 14.9 mm
# Full frame: 36 x 24mm
##################### THE 9 PARAMETERS YOU MUST SET ARE THERE
# ##################################################
f= 50 # mm, for example 50 mm
Vside= 36 # mm, for example 36 mm \ portrait / landscape
Hside= 24 # mm, for example 24 mm / orientation found there
phiMin= -90 # degrees, from -90 (nadir) toward 90
phiMax= 90 # degrees, up to 90 (zenith) toward -90
Hoverlap= 0.23 # horizontal overlap, coef from 0 to 0.5 (0% to 50 %)
Voverlap= 0.23 # vertical overlap, coef from 0 up to more than 0.5
#
panoheadPhiMin= -90 # degrees, from -90 (nadir) \ avoids the camera or lens
panoheadPhiMax= 90 # degrees, up to 90 (zenith) / hitting the pano head !
#
#####################
import os
import sys
if len(sys.argv)>1:
f = int(sys.argv[1])
from math import *
assert f > 1 and f < 1001, "f: improper focal length"
assert Vside > 1 and Vside < 100, "Vside: improper size"
assert Hside > 1 and Hside < 100, "Vside: improper size"
assert phiMin >= -90 and phiMin < 85, "phiMin not between -90 and +85"
assert phiMax <= 90 and phiMax > -85, "phiMax not between -85 and +90"
assert phiMin != phiMax, "phiMin, phiMax: min and max are equal"
assert phiMin < phiMax, "phiMin, phiMax: min and max are inverted"
assert Hoverlap >= 0, "Hoverlap: minimum possible value is 0"
assert Hoverlap < 0.96, "Hoverlap: maximum possible value is 0.95"
assert Voverlap >= 0, "Voverlap: minimum value is 0"
assert Voverlap < 0.96, "Voverlap: maximum value is 0.95"
assert panoheadPhiMin >= -90, "panoheadPhiMin: extreme value is -90"
assert panoheadPhiMax <= 90, "panoheadPhiMax: maximum value is 90"
assert panoheadPhiMin < panoheadPhiMax, "panoheadPhiMin, panoheadPhiMax:" \
+ "Pano-head extreme top & bottom positions are stupid!"
trueVside= Vside
trueHside= Hside
trueVfov= degrees(2 * atan (trueVside / 2 / f))
trueHfov= degrees(2 * atan (trueHside / 2 / f))
if phiMax - trueVfov / 2 > panoheadPhiMax :
print("\nCAUTION! ...panorama phiMax incompatible",
"with pano-head phiMax has been reduced!\n")
phiMax= panoheadPhiMax - trueVfov / 2
if phiMin + trueVfov / 2 < panoheadPhiMin :
phiMin= panoheadPhiMin + trueVfov / 2
print("\nCAUTION! ...panorama phiMin incompatible",
"with pano-head phiMin has been adjusted!\n")
truePhiMin= phiMin
truePhiMax= phiMax
##########----------##########----------##########----------##########----------
print("Camera:")
print(" Sensor size ", repr(trueHside)[0:4] + " x " + repr(trueVside),"mm")
print(" Focal length ", repr(f)[0:5], "mm")
print(" Lens vertical FOV ", round(degrees(2 * atan (trueVside / 2 / f))), "deg")
print(" Lens horizontal FOV ", round(degrees(2 * atan (trueHside / 2 / f))), "deg")
print("\nPanorama:")
print(" Top at ", repr(phiMax)[0:5], "deg")
print(" Bottom at ", repr(phiMin)[0:5], "deg")
print(" vertical FOV ", repr(phiMax - phiMin)[0:5], "deg")
print(" Vertical overlap ", repr(int(100 * Voverlap))+" %")
print(" Horizontal overlap ", repr(int(100 * Hoverlap))+" %")
if panoheadPhiMin != -90 or panoheadPhiMax != 90 :
print("\nPano-head:")
if panoheadPhiMin != -90 :
print(" downward limit", int(panoheadPhiMin), " deg")
if panoheadPhiMax != 90 :
print(" upward limit", int(panoheadPhiMax), " deg")
print(" ")
##########----------##########----------##########----------##########----------
totalImgNb= int(0)
if trueVfov > trueHfov :
optimalZenith= 90 - ((trueVfov - trueHfov) / 2)
optimalNadir= -90 + ((trueVfov - trueHfov) / 2)
else :
optimalZenith = 90
optimalNadir = -90 # overlap between zenith disc and top row
#########################################
if panoheadPhiMax >= optimalZenith \
and truePhiMax > 90 - (trueHfov / 2 * (1 - max(Voverlap, Hoverlap))) :
zenith= "yes"
phiMax= phiMax - (min(trueHfov, trueVfov) / 2 * (1 - max(Voverlap, Hoverlap)))
totalImgNb= totalImgNb + 1
else :
zenith= "no" # no overlap with zenith hole is wanted
phiMax= phiMax - (trueVfov * Voverlap / 2)
print("# phiMax moved downward by", repr(trueVfov * Voverlap / 2)[0:5],
"deg -----------------------> 0 % overlap with zenith hole")
if (panoheadPhiMin <= optimalNadir) \
and abs(truePhiMin) > 90 - (trueVfov / 2 * (1 - max(Voverlap, Hoverlap))) :
nadir= "yes"
phiMin= phiMin + (min(trueHfov, trueVfov) / 2 * (1 - max(Voverlap, Hoverlap)))
totalImgNb= totalImgNb + 1
else :
nadir= "no" # no overlap with nadir hole is wanted
phiMin= phiMin + (trueVfov * Voverlap / 2)
print("# phiMin moved upward by", repr(trueVfov * Voverlap / 2)[0:5],
"deg -------------------------> 0 % overlap with nadir hole")
Vfov= trueVfov * (1 - Voverlap)
Hfov= trueHfov * (1 - Hoverlap)
Vside= 2 * f * tan(radians(Vfov / 2))
Hside= 2 * f * tan(radians(Hfov / 2))
linV= 1 - Vside / trueVside # Out of disc part of zenith and/or nadir
linH= 1 - Hside / trueHside # not taken into account tough it should be!
if int(linV) != int(linH) :
print("# Linear vertical overlap --> ", repr(100 * (linV))[0:5],
"% of source pixels")
print("# Linear horizontal overlap --> ", repr(100 * (linH))[0:5],
"% of source pixels")
else :
print("# Linear overlap --> ", repr(100 * (linV))[0:5],
"% of source pixels")
anglV= 1 - Vfov / trueVfov # idem about out of disc part of zenith, nadir
anglH= 1 - Hfov / trueHfov
if int(100 * (anglV + anglH)) != int(100 * (linV + linH)) :
if int(anglV) != int(anglH) :
print("# Angular vertical overlap --> ", repr(100 * anglV)[0:5], "%")
print("# Angular horizontal overlap --> ", repr(100 * anglH)[0:5], "%")
else :
print("# Angular overlap --> ", repr(100 * anglV)[0:5], "%")
rowNb= (phiMax - phiMin) // Vfov
if rowNb * Vfov < phiMax - phiMin :
rowNb= rowNb + 1
dPitch= (phiMax - phiMin) / rowNb
sigmaPhi= rowNb * trueVfov
if nadir == "yes" :
sigmaPhi= sigmaPhi + (trueVfov + trueHfov )/ 2 / 2 # sic!
if zenith == "yes" :
sigmaPhi= sigmaPhi + + (trueVfov + trueHfov )/ 2 / 2 # sic!
VangularExcess= (sigmaPhi - (truePhiMax - truePhiMin)) / sigmaPhi
##########----------##########----------##########----------##########----------
toPrint= "\n" + "Number of rows: " + repr(int(rowNb))
if zenith == "yes" :
toPrint= toPrint + " + zenith"
if nadir == "yes" :
toPrint= toPrint + " + nadir"
print (toPrint + "\n")
print("# Lens vertical angles : ",
repr(trueVfov * Voverlap / 2)[0:4], "+", repr(Vfov)[0:4], "+",
repr(trueVfov * Voverlap / 2)[0:4], "=",repr(trueVfov)[0:4] + " deg")
print("# Lens horizontal angles : ",
repr(trueHfov * Hoverlap / 2)[0:4], "+", repr(Hfov)[0:4], "+",
repr(trueHfov * Hoverlap / 2)[0:4], "=", repr(trueHfov)[0:4] + " deg")
if zenith == "yes" or nadir == "yes" :
if Hfov < Vfov :
print("# Zenith and Nadir angles: ", repr(Hfov / 2)[0:4], "+",
repr(trueHfov * Hoverlap / 2)[0:4], "=",
repr(trueHfov / 2)[0:4] + "deg")
else :
print("# Zenith and Nadir angles: ", repr(Vfov / 2)[0:4], "+",
repr(trueVfov * Voverlap / 2)[0:4], "=",
repr(trueVfov / 2)[0:4] + " deg")
print("# Modified phiMax = " + repr(phiMax)[0:4] + " deg")
print("# Modified phiMin = " + repr(phiMin)[0:5] + " deg")
print("# Row to row delta Pitch = " +
repr(dPitch)[0:4] + " deg -----------------------> " +
repr(int(100 * VangularExcess)) +
" % vertical angular excess (total angle: " +
repr(int(sigmaPhi)) + " deg)")
print("#############################")
##########----------##########----------##########----------##########----------
if nadir== "yes" :
if trueVfov > trueHfov :
print("\nNadir shoot at " + repr(optimalNadir)[0:5] + " deg\n")
else :
print("\nNadir shoot at -90 deg\n")
pitchList= [repr(optimalNadir)[0:5]] ## 1 ##
imgNbList= [int(1)] ## 2 ##
imgYawList= ["0.0"] ## 3 ##
else :
pitchList= [] ## 1 ##
imgNbList= [] ## 2 ##
imgYawList= [] ## 3 ##
if rowNb != 1 :
prevTop= phiMin
else :
prevTop= (phiMin + phiMax) / 2 - Vfov / 2
i= 0
while i < rowNb : # begin rows loop <-----------------------------
bottom= prevTop
top= prevTop + dPitch
pitch= (bottom + top) / 2
if pitch < 0 :
pitchList= pitchList + [repr(pitch)[0:5]] ## 1 ##
else :
pitchList= pitchList + [repr(pitch)[0:4]] ## 1 ##
if abs(bottom) < abs(top) : # the smaller the distance
largeCirclePitch= abs(bottom) # between a circle and the equator
smallCirclePitch= abs(top) # ... the larger this circle is
else:
largeCirclePitch= abs(top)
smallCirclePitch= abs(bottom)
largePitch= largeCirclePitch
midlePitch= (largeCirclePitch + smallCirclePitch) / 2
smallPitch= smallCirclePitch
# midlePitch (degrees, unsigned) points to the circle where images
# sides must be adjacent
MoHSD= f / cos(radians(dPitch / 2)) # MoHSD: Middle of Horizontal Sides
# Distance from sphere center
circleRadius= MoHSD * cos (radians(midlePitch))
largeRadius= MoHSD * cos (radians(largePitch))
smallRadius= MoHSD * cos (radians(smallPitch))
# angle under which is seen an image (decreased for overlap) in the:
unadjdYaw= degrees(2 * (atan(Hside / 2 / circleRadius))) # middle circle horizontal plane
largedYaw= degrees(2 * (atan(trueHside / 2 / largeRadius)))# largest circle horizontal plane
smalldYaw= degrees(2 * (atan(trueHside / 2 / smallRadius)))# smallest circle horizontal plane
imgNb= 360 // unadjdYaw
if imgNb * unadjdYaw < 360 :
imgNb = imgNb + 1
dYaw = 360 / imgNb
if largedYaw < dYaw :
imgNb= 360 // largedYaw
if imgNb * largedYaw < 360 :
imgNb = imgNb + 1
dYaw = 360 / imgNb
selected= "# based on LARGE circle, dYaw: " + repr(dYaw)[0:5] + " deg"
else :
selected= "# based on MIDLE circle, dYaw: " + repr(dYaw)[0:5] + " deg"
imgNbList= imgNbList + [int(imgNb)] ## 2 ##
HexcessContiguous= (imgNb * unadjdYaw - 360) / 360
toPrint = "\nrow " + repr(i + 1).ljust(2) + " of " + repr(int(rowNb)) \
+ ", pitch: " + repr(int(pitch)) \
+ " deg # top overlap at " + repr(int(round(top))) \
+ " deg, bottom overlap at " + repr(int(round(bottom))) + " deg"
print (toPrint)
print(" " + selected)
if abs(round(top)) == abs(round(bottom)) :
toPrint= " # large circle is any -----> "
elif largeCirclePitch == abs(bottom) :
toPrint= " # large circle at bottom --> "
else:
toPrint= " # large circle at top -----> "
HexcessLarge= (largedYaw - dYaw) / largedYaw
toPrint= toPrint + repr(int(100 * HexcessLarge)) + " % overlap"
print (toPrint)
toPrint= " deg # small circle ------------> "
HexcessSmall= (smalldYaw - dYaw) / smalldYaw
toPrint= toPrint + repr(int(100 * HexcessSmall)) + " % overlap"
print (toPrint)
dYaw = 360 / imgNb
j= 0 # begin images loop <-----------------
while j < imgNb :
imgYawList= imgYawList + [repr(j * dYaw)[0:5]] ## 3 ##
totalImgNb= totalImgNb + 1
print (" ", repr(j + 1).ljust(2), "yaw:", int(j * dYaw))
j= j + 1 # end images loop <-----------------
i= i + 1
prevTop= top # end rows loop <-------------------
##########----------##########----------##########----------##########----------
if zenith == "yes" :
if trueVfov > trueHfov :
print("\nZenith shoot at " + repr(optimalZenith)[0:4] + " deg")
else :
print("\nZenith shoot at 90 deg")
pitchList= pitchList + [repr(optimalZenith)[0:4]] ## 1 ##
imgNbList= imgNbList + [int(1)] ## 2 ##
imgYawList= imgYawList + ["0.0"] ## 3 ##
print("\nTotal number of images: " + repr(totalImgNb) + "\n")
##########----------##########----------##########----------##########----------
xml_file = open(repr(f)[0:5]+ "mm sphere_preset.xml", 'w')
header = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<papywizard>\n <preset name=\""+repr(f)[0:5]+ "mm sphere\">\n <tooltip>\n"
xml_file.write(header)
xml_file.write("Total number of images: " + repr(totalImgNb) + "\n")
xml_file.write("Camera:\n")
xml_file.write(" Sensor size "+ repr(trueHside)[0:4] + " x " + repr(trueVside)+"mm\n")
xml_file.write(" Focal length "+ repr(f)[0:5]+ "mm\n")
xml_file.write(" Lens vertical FOV "+ str(round(degrees(2 * atan (trueVside / 2 / f))))+ "deg\n")
xml_file.write(" Lens horizontal FOV "+ str(round(degrees(2 * atan (trueHside / 2 / f))))+ "deg\n")
xml_file.write("\nPanorama:\n")
xml_file.write(" Top at "+ repr(phiMax)[0:5]+ "deg\n")
xml_file.write(" Bottom at "+ repr(phiMin)[0:5]+ "deg\n")
xml_file.write(" vertical FOV "+ repr(phiMax - phiMin)[0:5]+ "deg\n")
xml_file.write(" Vertical overlap "+ repr(int(100 * Voverlap))+" %\n")
xml_file.write(" Horizontal overlap "+ repr(int(100 * Hoverlap))+" %\n")
header2 = " </tooltip>\n <shoot>\n"
xml_file.write(header2)
print("#############################\n")
k= 0
for i in range(len(pitchList)) :
pitchString= 'pitch="' + pitchList[i] + '" yaw="'
if pitchString[7] == '-' and pitchString[9] == '.' :
pitchString= pitchString[0:10]+pitchString[11:]
if i%2!=0:
for j in range(imgNbList[i]) :
yawString= imgYawList[k] + '"'; k= k + 1;
print("<pict " + pitchString + yawString +"/>")
xml_file.write(" <pict " + pitchString + yawString +"/>\n")
else:
for j in range(imgNbList[i]) :
yawString= imgYawList[k+imgNbList[i]-2*j-1] + '"'; k= k + 1;
print("<pict " + pitchString + yawString +"/>")
xml_file.write(" <pict " + pitchString + yawString +"/>\n")
print("")
xml_file.write("\n")
footer = " </shoot>\n </preset>\n\n</papywizard>"
xml_file.write(footer)
xml_file.close()
print("#############################")
print("Papywizard preset XML saved as: "+repr(f)[0:5]+ "mm sphere_preset.xml")
#print("the following is buggy...")
#totalArea= totalImgNb * trueVside * trueHside
#imgDiag = sqrt((trueVside)**2 + (trueHside)**2)
#r = sqrt(f**2 + (imgDiag / 2)**2)
#wrapingCylinderHeight = r * ( sin(radians(abs(truePhiMax)))
# + sin(radians(abs(truePhiMin))))
#wrapingCylinderArea= 2 * pi * r * wrapingCylinderHeight
######################After you save the file to a .py, and setup your sensor size. Just run the script with the focal length as an argument. Eg. "python sphere_calc.py 24" will make a xml file called "24mm sphere_preset.xml"
edit: I edited this line in the script:
if len(sys.argv)>1:
at the top of the script and changed the 0 to 1. There is always 1 argument being sent to the script, and that's the script name. So this now either works with the data in the file, or with a focal length argument.
Last edited by kevshu (2011-10-19 03:40:59)
Offline
I'm not shure if im doing this correctly but i get an error
Traceback (most recent call last):
File "C:/Users/1337/Desktop/test", line 27, in <module>
f = int(sys.argv[1])
IndexError: list index out of rangeedit: i was doing it wrong
. I got one last question. I have a DX sensor. should i typ in the 55mm DX or the 82.5mm FX ?
Last edited by dekemp (2011-10-19 00:45:22)
Offline
dekemp wrote:
I'm not shure if im doing this correctly but i get an error
edit: i was doing it wrong. I got one last question. I have a DX sensor. should i typ in the 55mm DX or the 82.5mm FX ?
Looking at sensor sizes http://en.wikipedia.org/wiki/Nikon_DX_format, a DX is 23.7mm x 15.5mm (depending on camera).
I plan on putting a simple gui to this script since I think it would be a nice tool for people to have easy access to. Hopefully early next week I should have time to finish it up and post it.
Offline
I meant that my lens is a DX 18-55, and I want to make a script for the 55mm. Do I have to put in the 55mm or the FX equivalent that is 55*1.5=82.5mm in the script?
Offline
The script uses 24x36 as default sensor size (Hside/Vside). So you need to enter the corrected focal (55 * 1.5 = 82.5mm).
Or you can modify the script with your sensor size:
Vside= 23.6
Hside= 15.8
and then give the real focal (55mm).
Offline
fma38 wrote:
The script uses 24x36 as default sensor size (Hside/Vside). So you need to enter the corrected focal (55 * 1.5 = 82.5mm).
Or you can modify the script with your sensor size:
Vside= 23.6
Hside= 15.8
and then give the real focal (55mm).
I have an error too:
Traceback (most recent call last):
File "/Users/lucianocorrea/Pictures/#panoramicas#/PRESETS/NOVOS-PRESETS/papysheric.py", line 137, in <module>
anglV= 1 - Vfov / trueVfov # idem about out of disc part of zenith, nadir
ZeroDivisionError: float division by zeroI am trying to create a preset with this:
# Version 0.0.3 - Oct 16, 2011
##########----------##########----------##########----------##########----------
##################### THE 9 PARAMETERS YOU MUST SET ARE THERE
# ##################################################
f= 35 # mm, for example 50 mm
Vside= 36 # mm, for example 36 mm \ portrait / landscape
Hside= 24 # mm, for example 24 mm / orientation found there
phiMin= -90 # degrees, from -90 (nadir) toward 90
phiMax= 90 # degrees, up to 90 (zenith) toward -90
Hoverlap= 0.23 # horizontal overlap, coef from 0 to 0.5 (0% to 50 %)
Voverlap= 0.23 # vertical overlap, coef from 0 up to more than 0.5
#
panoheadPhiMin= -90 # degrees, from -90 (nadir) \ avoids the camera or lens
panoheadPhiMax= 90 # degrees, up to 90 (zenith) / hitting the pano head !
#
#####################Offline
The script works OK for me.
Here's the output it created using your parameters:
<?xml version="1.0" encoding="utf-8"?>
<papywizard>
<preset name="35mm sphere">
<tooltip>
Total number of images: 46
Camera:
Sensor size 24 x 36mm
Focal length 35mm
Lens vertical FOV 54deg
Lens horizontal FOV 38deg
Panorama:
Top at 75.42deg
Bottom at -75.4deg
vertical FOV 150.8deg
Vertical overlap 23 %
Horizontal overlap 23 %
</tooltip>
<shoot>
<pict pitch="-81.7" yaw="0.0"/>
<pict pitch="-56.5" yaw="0.0"/>
<pict pitch="-56.5" yaw="40.0"/>
<pict pitch="-56.5" yaw="80.0"/>
<pict pitch="-56.5" yaw="120.0"/>
<pict pitch="-56.5" yaw="160.0"/>
<pict pitch="-56.5" yaw="200.0"/>
<pict pitch="-56.5" yaw="240.0"/>
<pict pitch="-56.5" yaw="280.0"/>
<pict pitch="-56.5" yaw="320.0"/>
<pict pitch="-18.8" yaw="332.3"/>
<pict pitch="-18.8" yaw="304.6"/>
<pict pitch="-18.8" yaw="276.9"/>
<pict pitch="-18.8" yaw="249.2"/>
<pict pitch="-18.8" yaw="221.5"/>
<pict pitch="-18.8" yaw="193.8"/>
<pict pitch="-18.8" yaw="166.1"/>
<pict pitch="-18.8" yaw="138.4"/>
<pict pitch="-18.8" yaw="110.7"/>
<pict pitch="-18.8" yaw="83.07"/>
<pict pitch="-18.8" yaw="55.38"/>
<pict pitch="-18.8" yaw="27.69"/>
<pict pitch="-18.8" yaw="0.0"/>
<pict pitch="18.8" yaw="0.0"/>
<pict pitch="18.8" yaw="27.69"/>
<pict pitch="18.8" yaw="55.38"/>
<pict pitch="18.8" yaw="83.07"/>
<pict pitch="18.8" yaw="110.7"/>
<pict pitch="18.8" yaw="138.4"/>
<pict pitch="18.8" yaw="166.1"/>
<pict pitch="18.8" yaw="193.8"/>
<pict pitch="18.8" yaw="221.5"/>
<pict pitch="18.8" yaw="249.2"/>
<pict pitch="18.8" yaw="276.9"/>
<pict pitch="18.8" yaw="304.6"/>
<pict pitch="18.8" yaw="332.3"/>
<pict pitch="56.5" yaw="320.0"/>
<pict pitch="56.5" yaw="280.0"/>
<pict pitch="56.5" yaw="240.0"/>
<pict pitch="56.5" yaw="200.0"/>
<pict pitch="56.5" yaw="160.0"/>
<pict pitch="56.5" yaw="120.0"/>
<pict pitch="56.5" yaw="80.0"/>
<pict pitch="56.5" yaw="40.0"/>
<pict pitch="56.5" yaw="0.0"/>
<pict pitch="81.7" yaw="0.0"/>
</shoot>
</preset>
</papywizard>Offline
Reporting ... I was trying on my iMac with Python 2.7
I installed on my Macbook to Python 3.2 and it worked perfect.
Offline
Any news on the GUI?
I'm trying to run the script but it doesn't make a xml file. And when i run it in the pyhton GUI (run module) it is completely diffrend and unusable for papywizard.
Offline
The zero division error comes from the way different python major releases deal with integer division:
In python 2.x:
1 / 2 = 0
In python 3.x :
1 / 2 = 0.5
If you want a float division in python 2.x, you need to write:
1 / 2. = 0.5
or
1. / 2 = 0.5
So, just change the lines 48/49 from:
trueVfov= degrees(2 * atan (trueVside / 2 / f)) trueHfov= degrees(2 * atan (trueHside / 2 / f))
to:
trueVfov= degrees(2 * atan (trueVside / 2. / f)) trueHfov= degrees(2 * atan (trueHside / 2. / f))
Offline
Here's a web interface for creating the PapySpheric templates. I'll keep this hosted at this location.
http://exposedbykevin.com/PapySpheric/papyspheric.html
Source & html available for download http://exposedbykevin.com/PapySpheric/p … gi_web.zip
Last edited by kevshu (2013-04-26 06:44:52)
Offline
Good job! I added a link to your converter on Papywizard web site...
BTW, I started, some months ago, to re-write GURL's script in a more pythonic way (more object), but I'm stuck on the maths; there are too many global vars and so, and it is hard to find what is needed and what is optionnal.
Could someone re-write the maths in a programming-language independant way? I could then write something more robust, which could be integrated to Papywizard or in another applications...
Thanks!
Offline
Hello Kevin,
I wish to thank-you ! ![]()
This is a long time we are all waiting for a Web interface of PapySpheric ...
I have try to save your sources on my PC but without success (the Zip file is empty ...!?)
Could-you see this small problem ?
Offline
The problem was the name of the script. I guess the internet doesn't like .CGI files being downloaded or emailed. I renamed the file to a .TXT and put instructions to rename to .CGI in the zip.
Offline
fma38 wrote:
BTW, I started, some months ago, to re-write GURL's script in a more pythonic way (more object), but I'm stuck on the maths; there are too many global vars and so, and it is hard to find what is needed and what is optionnal.
Take a look at this script, maybe you will find it usefull. Its more pythonic and way easier to embed, but math there not that good.
https://github.com/snable/pano_360_tool … y-conf2.py
Last edited by AlexKuro (2013-04-26 19:33:10)
Offline
Thanks!
Offline
thanks for the help
Offline
Pages: 1 2
Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
|
CHOOSING KOLOR Why choose Kolor? Which solution to choose? Download a trial Where can I buy? Education |
SOFTWARE Autopano Pro Autopano Giga Panotour Panotour Pro XnView |
ACCESSORIES Training DVD Panobook PROJECTS Paris 26 Gigapixels Yosemite 17 Gigapixels |
COMMUNITY Forums YouTube channel Google+ |
COMPANY Blog About Kolor Resellers Contact Visit us |
PRESS Press center Press review TOOLS My account |
