diff options
| author | yo mama <pepper@scannerjammer.com> | 2017-06-25 16:35:58 -0700 |
|---|---|---|
| committer | yo mama <pepper@scannerjammer.com> | 2017-06-25 16:35:58 -0700 |
| commit | 91ca7d68e4caa9d6875549bfd2c329b9d0ef48ec (patch) | |
| tree | 71746ed9cabf5126b70ced19582053e8b16a5f4b | |
| parent | 95cf222e29dfce0f2c3e2771912aa007c64cd874 (diff) | |
almost done
| -rwxr-xr-x | bin/3Drotate.py | 495 |
1 files changed, 230 insertions, 265 deletions
diff --git a/bin/3Drotate.py b/bin/3Drotate.py index 63281b7..962a285 100755 --- a/bin/3Drotate.py +++ b/bin/3Drotate.py @@ -261,7 +261,7 @@ else: sys.exit(1) if arg == "-": break #fixme - test = re.match(r'pan=(\d+\.\d+)', arg) + test = re.match(r'pan=(\d+\.\d+)', arg, flags=re.IGNORECASE) if test: pan = float(test.group(1)) if (pan > 180) or (pan < -180): @@ -277,10 +277,10 @@ else: # do matrix multiply to get new rotation matrix newmat = matmul3(Rp0, Rp1, Rp2, R0, R1, R2) #RESETS CONSTANTS HERE, the GLOBAL ROTATION MATRIX - R0=newmat[0] - R1=newmat[1] - R2=newmat[2] - test = re.match(r'tilt=(\d+\.\d+)', arg) # tilt angle + R0 = newmat[0] + R1 = newmat[1] + R2 = newmat[2] + test = re.match(r'tilt=(\d+\.\d+)', arg, flags=re.IGNORECASE) # tilt angle if test: tilt = float(test.group(1)) if not (tilt > -180) or not (tilt < 180): @@ -299,282 +299,247 @@ else: R0 = newmat[0] R1 = newmat[1] R2 = newmat[2] - roll[=]*) # roll angle - arg="$1=" - roll=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - roll=`echo "$roll" | sed 's/^[+]\(.*\)$/\1/'` - # rolltest>0 if floating point number; otherwise rolltest=0 - testFloat "$roll"; rolltest=$floatresult - rolltestA=`echo "$roll < - 180" | bc` - rolltestB=`echo "$roll > 180" | bc` - [ $rolltest -eq 0 ] && errMsg "roll=$roll IS NOT A NUMBER" - [ $rolltestA -eq 1 -o $rolltestB -eq 1 ] && errMsg "ROLL=$roll MUST BE GREATER THAN -180 AND LESS THAN +180" - rollang=`echo "scale=10; $pi * $roll / 180" | bc` - sinroll=`echo "scale=10; s($rollang)" | bc -l` - sinrollm=`echo "scale=10; - $sinroll" | bc` - cosroll=`echo "scale=10; c($rollang)" | bc -l` - Rr0=($cosroll $sinroll 0) - Rr1=($sinrollm $cosroll 0) - Rr2=(0 0 1) - # do matrix multiply to get new rotation matrix - matmul3 "${Rr0[*]}" "${Rr1[*]}" "${Rr2[*]}" "${R0[*]}" "${R1[*]}" "${R2[*]}" - R0=(${P0[*]}) - R1=(${P1[*]}) - R2=(${P2[*]}) - ;; - pef[=]*) # pef - arg="$1=" - pef=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - pef=`echo "$pef" | sed 's/^[+]\(.*\)$/\1/'` - # peftest>0 if floating point number; otherwise peftest=0 - testFloat "$pef"; peftest=$floatresult - peftestA=`echo "$pef < 0" | bc` - peftestB=`echo "$pef > 3.19" | bc` - [ $peftest -eq 0 ] && errMsg "PEF=$pef IS NOT A NUMBER" - ;; - idx[=]*) # input x shift - arg="$1=" - di=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - di=`echo "$di" | sed 's/^[+]\(.*\)$/\1/'` - # ditest>0 if floating point number; otherwise ditest=0 - testFloat "$di"; ditest=$floatresult - [ $ditest -eq 0 ] && errMsg "ISHIFTX=$di IS NOT A NUMBER" - ;; - idy[=]*) # input y shift - arg="$1=" - dj=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - dj=`echo "$dj" | sed 's/^[+]\(.*\)$/\1/'` - # djtest>0 if floating point number; otherwise ditest=0 - testFloat "$dj"; djtest=$floatresult - [ $djtest -eq 0 ] && errMsg "ISHIFTY=$dj IS NOT A NUMBER" - ;; - odx[=]*) # output x shift - arg="$1=" - du=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - du=`echo "$du" | sed 's/^[+]\(.*\)$/\1/'` - # dutest>0 if floating point number; otherwise ditest=0 - testFloat "$du"; dutest=$floatresult - [ $dutest -eq 0 ] && errMsg "OSHIFTX=$du IS NOT A NUMBER" - ;; - ody[=]*) # output y shift - arg="$1=" - dv=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - dv=`echo "$dv" | sed 's/^[+]\(.*\)$/\1/'` - # dvtest>0 if floating point number; otherwise ditest=0 - testFloat "$dv"; dvtest=$floatresult - [ $dvtest -eq 0 ] && errMsg "OSHIFTY=$dv IS NOT A NUMBER" - ;; - zoom[=]*) # output zoom - arg="$1=" - zoom=`echo "$arg" | cut -d= -f2` - # function bc does not seem to like numbers starting with + sign, so strip off - zoom=`echo "$zoom" | sed 's/^[+]\(.*\)$/\1/'` - # zoomtest>0 if floating point number; otherwise peftest=0 - testFloat "$zoom"; zoomtest=$floatresult - zoomtest=`echo "$zoom < 1 && $zoom > -1" | bc` - [ $zoomtest -eq 1 ] && errMsg "ZOOM=$zoom MUST BE GREATER THAN 1 OR LESS THAN -1" - ;; - bgcolor[=]*) # output background color - arg="$1=" - bgcolor=`echo "$arg" | cut -d= -f2` - ;; - skycolor[=]*) # output sky color - arg="$1=" - skycolor=`echo "$arg" | cut -d= -f2` - ;; - vp[=]*) # virtual pixel method - arg="$1=" - vp=`echo "$arg" | cut -d= -f2` - [ "$vp" != "background" -a "$vp" != "dither" -a "$vp" != "edge" -a "$vp" != "mirror" -a "$vp" != "random" -a "$vp" != "tile" -a "$vp" != "transparent" ] && errMsg "VP=$vp IS NOT A VALID VALUE" - ;; - auto[=]*) # output background color - arg="$1=" - auto=`echo "$arg" | cut -d= -f2` - [ "$auto" != "c" -a "$auto" != "zc" -a "$auto" != "out" ] && errMsg "AUTO=$auto IS NOT A VALID VALUE" - ;; - *[=]*) # not valid - errMsg "$1 IS NOT A VALID ARGUMENT" - ;; - *) # end of arguments - break - ;; - esac - shift # next option - done - # + test = re.match(r'roll=(\d+\.\d+)', arg, flags=re.IGNORECASE) # roll angle + if test: + roll = float(test.group(1)) + if not (roll > -180) or not (roll < 180): + errMsg("ROLL=%s MUST BE LESS THAN 180 AND GREATER THAN -180" + ) % roll + + rollang = numpy.multiply(numpy.py, numpy.divide(roll, 180)) + sinroll = numpy.sin(rollang) + cosroll = numpy.cos(rollang) + Rr0 = [cosroll, sinroll, 0] + Rr1 = [-sinroll, cosroll, 0] + Rr2 = [0, 0, 1] + # do matrix multiply to get new rotation matrix + newmat = matmul3(Rr0, Rr1, Rr2, R0, R1, R2) + R0 = newmat[0] + R1 = newmat[1] + R2 = newmat[2] + test = re.match(r'pef=(\d+\.\d+)', arg, flags=re.IGNORECASE) # pef angle + if test: + pef = float(test.group(1)) + if not (pef > 0) or not (pef < numpy.pi): + errMsg("PEF=%s MUST BE LESS THAN PI AND GREATER THAN 0" + ) % pef + test = re.match(r'idx=(\d+\.\d+)', arg, flags=re.IGNORECASE) # idx angle + if test: + idx = float(test.group(1)) + if not (idx >= 0): + errMsg("IDX=%s MUST BE 0 or GREATER" + ) % idx + di = idx + test = re.match(r'idy=(\d+\.\d+)', arg, flags=re.IGNORECASE) + if test: + idy = float(test.group(1)) + if not (idy >= 0): + errMsg("IDY=%s MUST BE 0 or GREATER" + ) % idy + dj = idy + test = re.match(r'odx=(\d+\.\d+)', arg, flags=re.IGNORECASE) + if test: + odx = float(test.group(1)) + if not (odx >= 0): + errMsg("ODX=%s MUST BE 0 or GREATER" + ) % odx + du = odx + test = re.match(r'ody=(\d+\.\d+)', arg, flags=re.IGNORECASE) + if test: + ody = float(test.group(1)) + if not (ody > 0): + errMsg("ODY=%s MUST BE 0 or GREATER" + ) % ody + dv = ody + test = re.match(r'zoom=(\d+\.\d+)', arg, flags=re.IGNORECASE) + if test: + zoom = float(test.group(1)) + if not (zoom < -1 or zoom > 1): + errMsg("ODY=%s MUST BE GREATER THAN 1 OR LESS THAN -1" + ) % zoom + test = re.match(r'bgcolor=([^ ]+)', arg, flags=re.IGNORECASE) + if test: + bgcolor = test.group(1) + test = re.match(r'skycolor=([^ ]+)', arg, flags=re.IGNORECASE) + if test: + skycolor = test.group(1) + test = re.match(r'vp=([^ ]+)', arg, flags=re.IGNORECASE) + if test: + vp = test.group(1).lower() + if vp not in [ + "background", "dither", "edge", + "mirror", "random", "tile", "transparent" + ]: + errMsg("VP=%s IS NOT A VALID VALUE" % (vp)) + test = re.match(r'auto=([^ ]+)', arg, flags=re.IGNORECASE) + if test: + auto = test.group(1).lower() + if auto not in [ + "c", "zc", "out" + ]: + errMsg("AUTO=%s IS NOT A VALID VALUE" % (auto)) + # # get infile and outfile - infile=$1 - outfile=$2 -fi + infile = sys.argv[-2] + outfile = sys.argv[-1] + for a in [infile, outfile]: + if re.match(r'.*=.*', a): + errMsg("%s is not a valid filepath" % a) -# setup temporary images and auto delete upon exit -# use mpc/cache to hold input image temporarily in memory -pid = os.getpid() -tmpA = "%s/3Drotate_%s.mpc" % (directory, pid) -tmpB = "%s/3Drotate_%s.cache" % (directory, pid) -os.unlink(tmpA,tmpB) -os.unlink(tmpA,tmpB) + # setup temporary images and auto delete upon exit + # use mpc/cache to hold input image temporarily in memory + pid = os.getpid() -# test that infile provided -[ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED" -# test that outfile provided -[ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED" + tmpA = "%s/3Drotate_%s.mpc" % (directory, pid) + tmpB = "%s/3Drotate_%s.cache" % (directory, pid) + os.unlink(tmpA,tmpB) + os.unlink(tmpA,tmpB) -if convert -quiet -regard-warnings "$infile" +repage "$tmpA" - then - [ "$pef" = "" ] && pef=1 -else - errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---" -fi + # test that infile provided + if not os.path.exists(infile): + errMsg("NO INPUT FILE SPECIFIED") + # test that outfile provided + if not outfile: + errMsg("NO OUTPUT FILE SPECIFIED") -# get input image width and height -imagesize -maxwidth=`expr $width - 1` -maxheight=`expr $height - 1` + cmd = ['convert', '-quiet', '-regard-warnings', infile, '+repage', tmpA] + call_cmd(cmd) + if not pef: + pef = 1 -# deal with auto adjustments to values -if [ "$auto" = "zc" ] - then - du=0 - dv=0 - zoom=1 -elif [ "$...auto" = "c" ] - then - du=0 - dv=0 -fi + # get input image width and height + imagesize() + maxwidth = width - 1 + maxheight = height - 1 -# convert offsets of rotation point to relative to pixel 0,0 -di=`echo "scale=10; ($di + (($width - 1) / 2)) / 1" | bc` -dj=`echo "scale=10; ($dj + (($height - 1) / 2)) / 1" | bc` -du=`echo "scale=10; $du / 1" | bc` -dv=`echo "scale=10; $dv / 1" | bc` + # deal with auto adjustments to values + if auto == "zc": + du = 0 + dv = 0 + zoom = 1 + elif auto == "c": + du = 0 + dv = 0 -# convert zoom to scale factors -if [ `echo "$zoom >= 1" | bc` -eq 1 ] - then - sx=`echo "scale=10; 1 / $zoom" | bc` - sy=$sx -elif [ `echo "$zoom <= -1" | bc` -eq 1 ] - then - sx=`echo "scale=10; - $zoom / 1" | bc` - sy=$sx -fi + # convert offsets of rotation point to relative to pixel 0,0 + di = numpy.divide(numpy.add(di, numpy.divide(numpy.subtract(width,1), 2)),1) + dj = numpy.divide( + numpy.add(dj, numpy.divide(numpy.subtract(height, 1), 2)), 1) + du = numpy.divide(du, 1) + dv = numpy.divide(dv, 1) -#{{{explanation -# Consider the picture placed on the Z=0 plane and the camera a distance -# Zc=f above the picture plane looking straight down at the image center. -# Now the perspective equations (in 3-D) are defined as (x,y,f) = M (X',Y',Z'), -# where the camera orientation matrix M is the identity matrix but with M22=-1 -# because the camera is looking straight down along -Z. -# Thus a reflection transformation relative to the ground plane coordinates. -# Let the camera position Zc=f=(sqrt(ins*ins + inl*inl)) / ( 2 tan(fov/2) ) -# Now we want to rotate the ground points corresponding to the picture corners. -# The basic rotation is (X',Y',Z') = R (X,Y,0), where R is the rotation matrix -# involving pan, tilt and roll. -# But we need to convert (X,Y,0) to (X,Y,1) and also to offset for Zc=f -# First we note that (X,Y,0) = (X,Y,1) - (0,0,1) -# Thus the equation becomes (x,y,f) = M {R [(X,Y,1) - (0,0,1)] - (0,0,Zc)} = MT (X,Y,1) -# But R [(X,Y,1) - (0,0,1)] = R [II (X,Y,1) - S (X,Y,1)] = R (II-S) (X,Y,1), where -# II is the identity matrix and S is an all zero matrix except for S22=1. -# Thus (II-S) is the identity matrix with I22=0 and -# RR = R (II-S) is just R with the third column all zeros. -# Thus we get (x,y,f) = M {RR (X,Y,1) - (0,0,Zc)}. -# But M {RR (X,Y,1) - (0,0,Zc)} = M {RR(X,Y,1) - D (X,Y,1)}, where -# D is an all zero matrix with D22 = Zc = f. -# So that we get M (RR-D) (X,Y,1) = MT (X,Y,1), where -# where T is just R with the third column (0,0,-f), i.e. T02=0, T12=0, T22=-f -# But we need to allow for scaling and offset of the output coordinates and -# conversion from (x,y,f) to (u,v,1)=O and conversion of input coordinates -# from (X,Y,1) to (i,j,1)=I. -# Thus the forward transformation becomes AO=MTBI or O=A'MTBI or O=PI, -# where prime means inverse. -# However, to do the scaling of the output correctly, need to offset by the input -# plus output offsets, then scale, which is all put into A'. -# Thus the forward transformation becomes AO=MTBI or O=A'MTBI where A'=Ai -# but we will merge A'M into Aim -# Thus the inverse transform becomes -# I=QO where Q=P' -# A=output scaling, offset and conversion matrix -# B=input offset and conversion matrix (scaling only needs to be done in one place) -# M=camera orientation matrix -# R=image rotation matrix Rroll Rtilt Rpan -# T=matrix that is R but R33 offset by f + 1 -# O=output coords vector (i,j,1) -# I=input coords vector (u,v,1)=(is,il,1) -# P=forward perspective transformation matrix -# Q=inverse perspective transformation matrix -# -# For a 35 mm camera whose film format is 36mm wide and 24mm tall, when the focal length -# is equal to the diagonal, the field of view is 53.13 degrees and this is -# considered a normal view equivalent to the human eye. -# See http://www.panoramafactory.com/equiv35/equiv35.html -# Max limit on dfov is 180 degrees (pef=3.19) where get single line like looking at picture on edge. -# Above this limit the picture becomes like the angles get reversed. -# Min limit on dfov seems to be slightly greater than zero degrees. -# Practical limits on dfov depend upon orientation angles. -# For tilt=45, this is about 2.5 dfov (pef=2.5). Above this, some parts of the picture -# that are cut off at the bottom, get wrapped and stretched in the 'sky'. -#}}} + # convert zoom to scale factors + if zoom >= 1: + sx = numpy.divide(1, zoom) + sy = sx + elif zoom <= -1: + sx = numpy.divide(-zoom, 1) + sy = sx -dfov=`echo "scale=10; 180 * a(36/24) / $pi" | bc -l` -if [ "$pef" = "" ] - then - pfact=1 -elif [ "$pef" = "0" ] - then - pfact=`echo "scale=10; 0.01 / $dfov" | bc` -else - pfact=$pef -fi -#maxpef=`echo "scale=5; 180 / $dfov" | bc` -#echo "maxpef=$maxpef" + #{{{explanation + # Consider the picture placed on the Z=0 plane and the camera a distance + # Zc=f above the picture plane looking straight down at the image center. + # Now the perspective equations (in 3-D) are defined as (x,y,f) = M (X',Y',Z'), + # where the camera orientation matrix M is the identity matrix but with M22=-1 + # because the camera is looking straight down along -Z. + # Thus a reflection transformation relative to the ground plane coordinates. + # Let the camera position Zc=f=(sqrt(ins*ins + inl*inl)) / ( 2 tan(fov/2) ) + # Now we want to rotate the ground points corresponding to the picture corners. + # The basic rotation is (X',Y',Z') = R (X,Y,0), where R is the rotation matrix + # involving pan, tilt and roll. + # But we need to convert (X,Y,0) to (X,Y,1) and also to offset for Zc=f + # First we note that (X,Y,0) = (X,Y,1) - (0,0,1) + # Thus the equation becomes (x,y,f) = M {R [(X,Y,1) - (0,0,1)] - (0,0,Zc)} = MT (X,Y,1) + # But R [(X,Y,1) - (0,0,1)] = R [II (X,Y,1) - S (X,Y,1)] = R (II-S) (X,Y,1), where + # II is the identity matrix and S is an all zero matrix except for S22=1. + # Thus (II-S) is the identity matrix with I22=0 and + # RR = R (II-S) is just R with the third column all zeros. + # Thus we get (x,y,f) = M {RR (X,Y,1) - (0,0,Zc)}. + # But M {RR (X,Y,1) - (0,0,Zc)} = M {RR(X,Y,1) - D (X,Y,1)}, where + # D is an all zero matrix with D22 = Zc = f. + # So that we get M (RR-D) (X,Y,1) = MT (X,Y,1), where + # where T is just R with the third column (0,0,-f), i.e. T02=0, T12=0, T22=-f + # But we need to allow for scaling and offset of the output coordinates and + # conversion from (x,y,f) to (u,v,1)=O and conversion of input coordinates + # from (X,Y,1) to (i,j,1)=I. + # Thus the forward transformation becomes AO=MTBI or O=A'MTBI or O=PI, + # where prime means inverse. + # However, to do the scaling of the output correctly, need to offset by the input + # plus output offsets, then scale, which is all put into A'. + # Thus the forward transformation becomes AO=MTBI or O=A'MTBI where A'=Ai + # but we will merge A'M into Aim + # Thus the inverse transform becomes + # I=QO where Q=P' + # A=output scaling, offset and conversion matrix + # B=input offset and conversion matrix (scaling only needs to be done in one place) + # M=camera orientation matrix + # R=image rotation matrix Rroll Rtilt Rpan + # T=matrix that is R but R33 offset by f + 1 + # O=output coords vector (i,j,1) + # I=input coords vector (u,v,1)=(is,il,1) + # P=forward perspective transformation matrix + # Q=inverse perspective transformation matrix + # + # For a 35 mm camera whose film format is 36mm wide and 24mm tall, when the focal length + # is equal to the diagonal, the field of view is 53.13 degrees and this is + # considered a normal view equivalent to the human eye. + # See http://www.panoramafactory.com/equiv35/equiv35.html + # Max limit on dfov is 180 degrees (pef=3.19) where get single line like looking at picture on edge. + # Above this limit the picture becomes like the angles get reversed. + # Min limit on dfov seems to be slightly greater than zero degrees. + # Practical limits on dfov depend upon orientation angles. + # For tilt=45, this is about 2.5 dfov (pef=2.5). Above this, some parts of the picture + # that are cut off at the bottom, get wrapped and stretched in the 'sky'. + #}}} + + dfov = numpy.divide( + numpy.multpily(180, numpy.arctan(36/24)), numpy.pi) + pfact = 1 + if pef == 0: #fixme + pfact = numpy.divide(0.01, dfov) + else: + pfact = pef + + #compute new field of view based upon pef (pfact) + dfov = numpy.multiply(pfact, dfov) + dfov2 = numpy.divide(dfov, 2) + arg = numpy.multiply(numpy.pi, numpy.divide(dfov, 180)) + sfov = numpy.sin(arg) + cfov = numpy.cos(arg) + tfov = numpy.divide(sfov, cfov) -#compute new field of view based upon pef (pfact) -dfov=`echo "scale=10; $pfact * $dfov" | bc` -dfov2=`echo "scale=10; $dfov / 2" | bc` -arg=`echo "scale=10; $pi * $dfov2 / 180" | bc` -sfov=`echo "scale=10; s($arg)" | bc -l` -cfov=`echo "scale=10; c($arg)" | bc -l` -tfov=`echo "scale=10; $sfov / $cfov" | bc -l` -#echo "tfov=$tfov" -# calculate focal length in same units as wall (picture) using dfov -diag=`echo "scale=10; sqrt(($width * $width) + ($height * $height))" | bc` -focal=`echo "scale=10; ($diag / (2 * $tfov))" | bc -l` -#echo "focal=$focal" + # calculate focal length in same units as wall (picture) using dfov + diag = numpy.sqrt( + numpy.multiply(width, width), numpy.multiply(height, height)) + focal = numpy.divide(diag, numpy.multiply(2, tfov)) -# calculate forward transform matrix Q + # calculate forward transform matrix Q -# define the input offset and conversion matrix -dim=`echo "scale=10; - $di" | bc` -B0=(1 0 $dim) -B1=(0 -1 $dj) -B2=(0 0 1) + # define the input offset and conversion matrix + dim = -di + B0 = [1, 0, dim] + B1 = [0, -1, dj] + B2 = [0, 0, 1] -# define the output scaling, offset and conversion matrix inverse Ai and merge with M -# to become Aim -#A0=($sx 0 $sx*(-$du-$di)) -#A1=(0 -$sy $sy*($dv+$dj)) -#A2=(0 0 -$focal) -#M0=(1 0 0) -#M1=(0 1 0) -#M2=(0 0 -1) -aim00=`echo "scale=10; 1 / $sx" | bc` -aim02=`echo "scale=10; -($sx * ($di + $du)) / ($sx * $focal)" | bc` -aim11=`echo "scale=10; -1 / $sy" | bc` -aim12=`echo "scale=10; -($sy * ($dj + $dv)) / ($sy * $focal)" | bc` -aim22=`echo "scale=10; -1 / $focal" | bc` -Aim0=($aim00 0 $aim02) -Aim1=(0 $aim11 $aim12) -Aim2=(0 0 $aim22) + # define the output scaling, offset and conversion matrix inverse Ai and merge with M + # to become Aim + #A0=($sx 0 $sx*(-$du-$di)) + #A1=(0 -$sy $sy*($dv+$dj)) + #A2=(0 0 -$focal) + #M0=(1 0 0) + #M1=(0 1 0) + #M2=(0 0 -1) + aim00 = numpy.divide(1, sx) + aim02 = -numpy.divide( + numpy.multiply(sx, numpy.add(di, du)), numpy.multiply(sx, focal)) + aim11= -1 / $sy" | bc` + aim12= -($sy * ($dj + $dv)) / ($sy * $focal)" | bc` + aim22= -1 / $focal" | bc` + Aim0=($aim00 0 $aim02) + Aim1=(0 $aim11 $aim12) + Aim2=(0 0 $aim22) # now do successive matrix multiplies from right towards left of main equation P=A'RB |
