def do_merge(self, others): pto_temp_file = ManagedTempFile.get(None, ".pto") command = "pto_merge" args = list() args.append("--output=%s" % pto_temp_file) # Possible this is still empty if self.file_name and os.path.exists(self.file_name): args.append(self.file_name) for other in others: args.append(other.get_a_file_name()) print_debug(args) (rc, output) = Execute.with_output(command, args) # go go go if not rc == 0: print print print print 'Output:' print output print 'rc: %d' % rc raise Exception('failed pto_merge') return PTOProject.from_temp_file(pto_temp_file)
def run(self): args = list() args.append("-o") args.append(self.output_file) if self.compression: args.append('--compression=%s' % str(self.compression)) if self.gpu: args.append('--gpu') for arg in self.additional_args: args.append(arg) for f in self.input_files: args.append(f) for opt in config.enblend_opts().split(): args.append(opt) rc = Execute.show_output("enblend", args) if not rc == 0: print print print print 'Failed to blend' print 'rc: %d' % rc print args raise BlenderFailed('failed to remap')
def run(self): args = list() args.append("-o") args.append(self.pto_project.get_a_file_name()) args.append(self.pto_project.get_a_file_name()) (rc, output) = Execute.with_output("ptoclean", args) if not rc == 0: raise Exception('failed to clean control points') self.pto_project.reopen()
def run(self, source_file_name, dest_file_name = None): ''' http://www.imagemagick.org/Usage/convolve/#soft_blur convert face.png -morphology Convolve Gaussian:0x3 face_strong_blur.png convert face.png face_strong_blur.png \ -compose Blend -define compose:args=60,40% -composite \ face_soft_blur.png If dest_file_name is not given, done in place ''' strong_blur_mtemp_file = ManagedTempFile.from_same_extension(source_file_name) args = list() args.append(source_file_name) args.append("-morphology") args.append("Convolve") args.append("Gaussian:0x3") args.append(strong_blur_mtemp_file.file_name) (rc, output) = Execute.with_output("convert", args) if not rc == 0: raise Exception('failed to form strong blur') args = list() args.append(source_file_name) args.append(strong_blur_mtemp_file.file_name) args.append("-compose") args.append("Blend") args.append("-define") args.append("compose:args=60,40%") args.append("-composite") # If we got a dest file, use it if dest_file_name: args.append(dest_file_name) # Otherwise, overwrite else: args.append(source_file_name) (rc, output) = Execute.with_output("convert", args) if not rc == 0: raise Exception('failed to form strong blur')
def run(self, to_pto = False): from pr0ntools.stitch.pto.project import PTOProject others = self.files pto = self.pto '''Take in a list of pto files and merge them into pto''' if to_pto: pto_temp_file = self.pto.get_a_file_name() else: pto_temp_file = ManagedTempFile.get(None, ".pto") command = "pto_merge" args = list() args.append("--output=%s" % pto_temp_file) # Possible this is still empty if pto.file_name and os.path.exists(pto.file_name): args.append(pto.file_name) for other in others: args.append(other.get_a_file_name()) print_debug(args) (rc, output) = Execute.with_output(command, args) # go go go if not rc == 0: print print print print 'Output:' print output print 'rc: %d' % rc if rc == 35072: # ex: empty projects seem to cause this print 'Out of memory, expect malformed project file' raise Exception('failed pto_merge') if to_pto: self.pto.reopen() return self.pto else: return PTOProject.from_temp_file(pto_temp_file)
def generate_core(self, image_file_names): project_file = ManagedTempFile.get(None, ".pto") command = "autopano-sift-c" args = list() # Try to post process them to make them more accurate #args.append("--refine") # Perform RANSAC to try to get bad control points out #args.append("--ransac") #args.append("on") # Unlimited matches args.append("--maxmatches") args.append("0") # ? #args.append("--maxdim") #args.append("10000") # Project file args.append(project_file.file_name) # Images for image_file_name in image_file_names: args.append(image_file_name) # go go go (rc, output) = Execute.with_output(command, args) if not rc == 0: print print print print 'output:\n%s' % output raise Exception('Bad rc: %d' % rc) # We return PTO object, not string return PTOProject.from_temp_file(project_file)
def generate_core(self, image_file_names): command = "autopanoaj" args = list() project_file = ManagedTempFile.get(None, ".pto") # default is .oto args.append("/project:hugin") # Use image args instead of dir args.append("/f"); args.append('/path:Z:\\tmp') # Images for image_file_name in image_file_names: args.append(image_file_name.replace("/tmp/", "Z:\\tmp\\")) # go go go (rc, output) = Execute.with_output(command, args) if not rc == 0: raise Exception('Bad rc: %d' % rc) # We return PTO object, not string # Ditch the gen file because its unreliable shutil.move("/tmp/panorama0.pto", project_file.file_name) f = open(project_file.file_name, 'r') project_text = f.read() # Under WINE, do fixup project_text = project_text.replace('Z:\\tmp\\', '/tmp/') print print print print project_text print print print #sys.exit(1) f.close() f = open(project_file.file_name, 'w') f.write(project_text) return PTOProject.from_temp_file(project_file)
def old_merge(self): ''' [mcmaster@gespenst 2X2-ordered]$ enblend -o my_prefix.tif my_prefix_000* enblend: info: loading next image: my_prefix_0000.tif 1/1 enblend: info: loading next image: my_prefix_0001.tif 1/1 enblend: excessive overlap detected; remove one of the images enblend: info: remove invalid output image "my_prefix.tif" ''' args = list() args.append("-m") args.append("TIFF_m") args.append("-z") args.append("LZW") #args.append("-g") args.append("-o") args.append(self.pto_project.get_a_file_name()) args.append(self.pto_project.get_a_file_name()) (rc, output) = Execute.with_output("enblend", args) if not rc == 0: raise BlenderFailed('failed to blend') self.project.reopen()
def hugin_form(self): ''' Something is causing pto_merge to hang, but NOT ptomerge Only occurs if I wrap my commands in a script... The script doesn't do any fancy I/O redirection clear rm -rf /tmp/pr0ntools_* pr0nstitch *.jpg out.pto pto_merge produces nicer output than ptomerge While ptomerge produces the fields I need, it leaves some other junk I think pto_merge also calculates width/heigh attributes part of Hugin [mcmaster@gespenst first]$ pto_merge Warning: pto_merge requires at least 2 project files pto_merge: merges several project files pto_merge version 2010.4.0.854952d82c8f part of perl-Panotools-Script [mcmaster@gespenst first]$ ptomerge --help cannot read-open --help at /usr/share/perl5/Panotools/Script.pm line 91. man ptomerge ... ptomerge infile1.pto infile2.pto infile3.pto [...] outfile.pto ... ''' # However, this tool also generates an archaic .pto format that pto can parse, but I don't want to # pretend to merge into an empty project to force Hugin to clean it up # pto_merge --output=temp.pto /dev/null temp.pto if False: args = list() args.append("%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) (rc, output) = Execute.with_output("ptomerge", args) else: args = list() args.append("--output=%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) if False: args.append("/dev/null") else: empty_file = ManagedTempFile.get(None, ".pto") open(empty_file.file_name, 'w').write('') args.append(empty_file.file_name) (rc, output) = Execute.with_output("pto_merge", args) if not rc == 0: print print print print 'output:%s' % output raise Exception('Bad rc: %d' % rc) self.reopen()
def generate_core(self, image_file_names): command = "autopanoaj" args = list() final_project_file = ManagedTempFile.get(None, ".pto") temp_dir = ManagedTempDir.get() # default is .oto args.append("/project:hugin") # Use image args instead of dir # Images image_links = dict() for image_file_name in image_file_names: # args.append(image_file_name.replace("/tmp/", "Z:\\tmp\\")) image_file_name = os.path.realpath(image_file_name) link_file_name = os.path.join(temp_dir.file_name, os.path.basename(image_file_name)) print 'Linking %s -> %s' % (link_file_name, image_file_name) os.symlink(image_file_name, link_file_name) #sys.exit(1) # go go go (rc, output) = Execute.with_output(command, args, temp_dir.file_name) print 'Finished control point pair execution' if not rc == 0: print print print print 'output:\n%s' % output if output.find('This application has requested the Runtime to terminate it in an unusual way'): print 'WARNING: skipping crash' return None raise Exception('Bad rc: %d' % rc) ''' Doesn't like the match: PICTURE PAIRS VALIDATION Pair ( 0, 1) Ransac (In : 21, Out : 4, Residu : 4.43799) REMOVED Timing : 583.7 us ''' if output.find('REMOVED') >= 0: print 'WARNING: RANSAC invalidated control points' return None output_file_name = os.path.join(temp_dir.file_name, "panorama0.pto") # This happens occassionally, not sure why if not os.path.exists(output_file_name): print 'WARNING: missing output pto file!' return None # We return PTO object, not string # Ditch the gen file because its unreliable shutil.move(output_file_name, final_project_file.file_name) f = open(final_project_file.file_name, 'r') project_text = f.read() # Under WINE, do fixup # #-imgfile 2816 704 "Z:\tmp\pr0ntools_471477ADA1679A2E\pr0ntools_3CD1C0B1BB218E40.jpg" project_text = project_text.replace('Z:\\', '/').replace('\\', '/') for image_file_name in image_file_names: link_file_name = os.path.join(temp_dir.file_name, os.path.basename(image_file_name)) print 'Replacing %s -> %s' % (link_file_name, image_file_name) project_text = project_text.replace(link_file_name, image_file_name) if False: print print 'Raw control point project (after symbolic link and WINE file name substitution)' print print print project_text print print print #sys.exit(1) f.close() f = open(final_project_file.file_name, 'w') f.write(project_text) project = PTOProject.from_temp_file(final_project_file) return project
def remap(self): project = self.pto_project.copy() old_files = get_nona_files(self.output_prefix, len(self.pto_project.get_image_lines())) # For my purposes right now I think this will always be 0 if len(old_files) != 0: print old_files raise RemapperFailed('Found some old files') args = list() args.append("-m") args.append(self.image_type) pl = project.get_panorama_line() crop_opt = "" if self.image_type == Remapper.TIFF_SINGLE: if self.output_cropped: # FIXME: this needs to go into the n argument in the file, not a CLI option # p f0 w1000 h500 v120 n"TIFF_m c:LZW r:CROP" #args.append("r:CROP") #pl.set_variable("n", "TIFF_m %s ", self.compression_opt) # will be saved when we get the file name #pl.save() crop_opt = "r:CROP" pl.set_variable("n", "%s %s %s" % (self.image_type, crop_opt, self.compression_opt)) args.append("-verbose") args.append("-z") args.append("LZW") #args.append("-g") args.append("-o") args.append(self.output_prefix) args.append(project.get_a_file_name()) #(rc, output) = Execute.with_output("nona", args) rc = Execute.show_output("nona", args) if not rc == 0: print print print print 'Failed to remap' #print output raise RemapperFailed('failed to remap') #project.reopen() if self.image_type == Remapper.TIFF_MULTILAYER: self.output_files = [self.output_prefix + '.tif'] elif self.image_type == Remapper.TIFF_SINGLE: self.output_files = list() # This algorithm breaks down once you start doing cropping if 0: # The images shouldn't change, use the old loaded project for i in range(len(self.pto_project.get_image_lines())): fn = '%s%04d.tif' % (self.output_prefix, i) print 'Think we generated file %s' % fn if not os.path.exists(fn): raise RemapperFailed('Missing output file %s' % fn) self.output_files.append(fn) new_files = get_nona_files(self.output_prefix, len(self.pto_project.get_image_lines())) self.output_files = new_files.difference(old_files) print 'Think nona just generated files (%d new - %d old = %d delta):' % (len(new_files), len(old_files), len(self.output_files)) # it may be a set but lists have advantages trying to trace whats happening self.output_files = sorted(list(self.output_files)) if 0: for f in self.output_files: print ' %s' % f else: raise RemapperFailed('bad image type')
def run(self): ''' The base Hugin project seems to work if you take out a few things: Eb1 Eev0 Er1 Ra0 Rb0 Rc0 Rd0 Re0 Va1 Vb0 Vc0 Vd0 Vx-0 Vy-0 So say generate a project file with all of those replaced In particular we will generate new i lines To keep our original object intact we will instead do a diff and replace the optimized things on the old project Output is merged into the original file and starts after a line with a single * Even Hugin wpon't respect this optimization if loaded in as is Gives lines out like this o f0 r0 p0 y0 v51 a0.000000 b0.000000 c0.000000 g-0.000000 t-0.000000 d-0.000000 e-0.000000 u10 -buf These are the lines we care about C i0 c0 x3996.61 y607.045 X3996.62 Y607.039 D1.4009 Dx-1.15133 Dy0.798094 Where D is the magnitutde of the distance and x and y are the x and y differences to fitted solution There are several other lines that are just the repeats of previous lines ''' bench = Benchmark() # The following will assume all of the images have the same size self.verify_images() # Copy project so we can trash it project = self.project.to_ptoptimizer() prepare_pto(project, self.reoptimize) pre_run_text = project.get_text() if 0: print print print 'PT optimizer project:' print pre_run_text print print # "PToptimizer out.pto" args = list() args.append(project.get_a_file_name()) #project.save() rc = Execute.show_output("PToptimizer", args) if not rc == 0: print print print 'Failed rc: %d' % rc print 'Failed project:' print pre_run_text print print raise Exception('failed position optimization') # API assumes that projects don't change under us project.reopen() ''' Line looks like this # final rms error 24.0394 units ''' rms_error = None for l in project.get_comment_lines(): if l.find('final rms error') >= 00: rms_error = float(l.split()[4]) break print 'Optimize: RMS error of %f' % rms_error # Filter out gross optimization problems if self.rms_error_threshold and rms_error > self.rms_error_threshold: raise Exception("Max RMS error threshold %f but got %f" % (self.rms_error_threshold, rms_error)) if self.debug: print 'Parsed: %s' % str(project.parsed) if self.debug: print print print print 'Optimized project:' print project #sys.exit(1) print 'Optimized project parsed: %d' % project.parsed print 'Merging project...' merge_pto(project, self.project) if self.debug: print self.project bench.stop() print 'Optimized project in %s' % bench # These are beyond this scope # Move them somewhere else if we want them if 0: # The following will assume all of the images have the same size self.verify_images() # Final dimensions are determined by field of view and width # Calculate optimial dimensions self.calc_dimensions() print 'Centering project...' self.center_project() ''' WARNING WARNING WARNING The panotools model is too advanced for what I'm doing right now The image correction has its merits but is mostly getting in the way to distort images Therefore, I'd like to complete this to understand the intended use but I suspect its not a good idea and I could do my own nona style program much better The only downside is that if / when I start doing lens model corrections I'll have to rethink this a little Actually, a lot of these problems go away if I trim to a single tile I can use the same FOV as the source image or something similar ''' print 'Calculating optimial field of view to match desired size...' self.calc_fov()
def hugin_form(self): ''' This is used when merging through fortify stitch Something is causing pto_merge to hang, but NOT ptomerge Only occurs if I wrap my commands in a script... The script doesn't do any fancy I/O redirection clear rm -rf /tmp/pr0ntools_* pr0nstitch *.jpg out.pto pto_merge produces nicer output than ptomerge While ptomerge produces the fields I need, it leaves some other junk I think pto_merge also calculates width/heigh attributes part of Hugin [mcmaster@gespenst first]$ pto_merge Warning: pto_merge requires at least 2 project files pto_merge: merges several project files pto_merge version 2010.4.0.854952d82c8f part of perl-Panotools-Script [mcmaster@gespenst first]$ ptomerge --help cannot read-open --help at /usr/share/perl5/Panotools/Script.pm line 91. man ptomerge ... ptomerge infile1.pto infile2.pto infile3.pto [...] outfile.pto ... ''' # However, this tool also generates an archaic .pto format that pto can parse, but I don't want to # pretend to merge into an empty project to force Hugin to clean it up # pto_merge --output=temp.pto /dev/null temp.pto if False: args = list() args.append("%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) (rc, output) = Execute.with_output("ptomerge", args) else: args = list() args.append("--output=%s" % self.get_a_file_name()) args.append("%s" % self.get_a_file_name()) if False: args.append("/dev/null") else: empty_file = ManagedTempFile.get(None, ".pto") open(empty_file.file_name, 'w').write('') args.append(empty_file.file_name) (rc, output) = Execute.with_output("pto_merge", args) if not rc == 0: print print print if rc == 35072: # ex: empty projects seem to cause this print 'Out of memory, expect malformed project file' print 'output:%s' % output raise Exception('Bad rc: %d' % rc) self.reopen()