示例#1
0
	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)
示例#2
0
def soften_composite(src_fn, dst_fn=None):
    tmp_file = ManagedTempFile.from_same_extension(src_fn)
    soften_gauss(src_fn, tmp_file.file_name)

    if dst_fn is None:
        dst_fn = src_fn

    args = ["convert"]
    args.append(src_fn)
    args.append(tmp_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
    args.append(dst_fn)
    print 'going to execute: %s' % (args,)
    subp = subprocess.Popen(args, stdout=None, stderr=None, shell=False)
    subp.communicate()
    print 'Execute done, rc: %s' % (subp.returncode,)
    if not subp.returncode == 0:
        raise Exception('failed to form strong blur')

    # having some problems that looks like file isn't getting written to disk
    # monitoring for such errors
    # remove if I can root cause the source of these glitches
    for i in xrange(30):
        if os.path.exists(dst_fn):
            break
        if i == 0:
            print 'WARNING: soften missing strong blur dest file name %s, waiting a bit...' % (dst_fn,)
        time.sleep(0.1)
    else:
        raise Exception('Missing soften strong blur output file name %s' % dst_fn)
示例#3
0
    def run(self):
        from pr0ntools.stitch.pto.project import PTOProject
        
        '''Take in a list of pto files and merge them into pto'''
        pto_temp_file = ManagedTempFile.get(None, ".pto")

        args = ["pto_merge"]
        args.append("--output=%s" % pto_temp_file)

        for pto in self.ptos:
            args.append(pto.get_a_file_name())
    
        print 'MERGING: %s' % (args,)

        rc = execute.without_output(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 not os.path.exists(str(pto_temp_file)):
            raise Exception('Output file missing: %s' % (pto_temp_file,))

        return PTOProject.from_temp_file(pto_temp_file)
示例#4
0
 def from_file_name(file_name, is_temporary = False):
     ret = PTOProject()
     ret.file_name = file_name
     if is_temporary:
         ret.temp_file = ManagedTempFile.from_existing(file_name)
     ret.parse()
     return ret
示例#5
0
    def run(self):
        from pr0ntools.stitch.pto.project import PTOProject
        '''Take in a list of pto files and merge them into pto'''
        pto_temp_file = ManagedTempFile.get(None, ".pto")

        args = ["pto_merge"]
        args.append("--output=%s" % pto_temp_file)

        for pto in self.ptos:
            args.append(pto.get_a_file_name())

        print 'MERGING: %s' % (args, )

        rc = execute.without_output(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 not os.path.exists(str(pto_temp_file)):
            raise Exception('Output file missing: %s' % (pto_temp_file, ))

        return PTOProject.from_temp_file(pto_temp_file)
示例#6
0
	def parse_from_file_name(file_name, is_temporary = False):
		ret = PTOProject()
		ret.file_name = file_name
		if is_temporary:
			ret.temp_file = ManagedTempFile.from_existing(file_name)
		ret.parse()
		return ret
示例#7
0
	def do_get_a_file_name(self, prefix = None, postfix = None):
		'''If doesn't have a real file, create a temp file'''
		if self.file_name:
			return self.file_name
		if postfix is None:
			postfix = ".pto"
		self.temp_file = ManagedTempFile.get(prefix, postfix)
		self.file_name = self.temp_file.file_name
		return self.file_name
示例#8
0
    def get_a_file_name(self, prefix = None, postfix = None):
        '''Return a file name that has current .pto contents'''
        '''If doesn't have a real file, create a temp file'''
        if self.file_name:
            return self.file_name
        if postfix is None:
            postfix = ".pto"
        self.temp_file = ManagedTempFile.get(prefix, postfix)
        self.file_name = self.temp_file.file_name

        # hmmm...
        self.save()
        return self.file_name
示例#9
0
	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)
示例#10
0
    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)
        rc, output = exc_ret_istr(command, args, print_out=True)

        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/")
        if 0:
            print
            print
            print
            print project_text
            print
            print
            print
        f.close()
        f = open(project_file.file_name, "w")
        f.write(project_text)
        return PTOProject.from_temp_file(project_file)
示例#11
0
    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)
        (rc, output) = (exc_ret_istr(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)
示例#12
0
	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')
示例#13
0
    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)
        rc, output = exc_ret_istr(command, args, print_out=True)

        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/')
        if 0:
            print
            print
            print
            print project_text
            print
            print
            print
        f.close()
        f = open(project_file.file_name, 'w')
        f.write(project_text)
        return PTOProject.from_temp_file(project_file)
示例#14
0
    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)
        (rc, output) = (exc_ret_istr(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)
示例#15
0
def soften_composite(src_fn, dst_fn=None):
    tmp_file = ManagedTempFile.from_same_extension(src_fn)
    soften_gauss(src_fn, tmp_file.file_name)

    if dst_fn is None:
        dst_fn = src_fn

    args = ["convert"]
    args.append(src_fn)
    args.append(tmp_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
    args.append(dst_fn)
    print 'going to execute: %s' % (args, )
    subp = subprocess.Popen(args, stdout=None, stderr=None, shell=False)
    subp.communicate()
    print 'Execute done, rc: %s' % (subp.returncode, )
    if not subp.returncode == 0:
        raise Exception('failed to form strong blur')

    # having some problems that looks like file isn't getting written to disk
    # monitoring for such errors
    # remove if I can root cause the source of these glitches
    for i in xrange(30):
        if os.path.exists(dst_fn):
            break
        if i == 0:
            print 'WARNING: soften missing strong blur dest file name %s, waiting a bit...' % (
                dst_fn, )
        time.sleep(0.1)
    else:
        raise Exception('Missing soften strong blur output file name %s' %
                        dst_fn)
示例#16
0
    def generate_core(self, img_fns):
        # cpfind (and likely cpclean) trashes absolute file names
        # we need to restore them so that tools recognize the file names
        real_fn_base2full = {}

        args = list()
        project = PTOProject.from_default2()
        fn_obj = ManagedTempFile.get(None, ".pto")
        project.set_file_name(fn_obj.file_name)

        # Start with cpfind
        args.append("--multirow")
        args.append("--fullscale")
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        # Images
        for img_fn in img_fns:
            # xxx: why do we take the realpath?
            real_fn = os.path.realpath(img_fn)
            real_fn_base2full[os.path.basename(real_fn)] = img_fn
            project.add_image(real_fn, def_opt=True)

        project.save()
        print
        print
        print
        print project.get_text()
        print
        print
        print

        # (rc, output) = Execute.with_output('cpfind', args, print_output=self.print_output)
        (rc, output) = exc_ret_istr("cpfind", args, print_out=self.print_output)

        print "PanoCP: cpfind done"
        if not rc == 0:
            print
            print
            print
            print "output:"
            print output
            print
            raise Exception("Bad rc: %d" % rc)

        # Now run cpclean
        args = list()
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        (rc, output) = exc_ret_istr("cpclean", args, print_out=self.print_output)
        print "PanoCP: cpclean done"
        if not rc == 0:
            print
            print
            print
            print "output:"
            print output
            print
            raise Exception("Bad rc: %d" % rc)

        project.reopen()
        print "Fixing image lines..."
        for il in project.image_lines:
            src = il.get_name()
            dst = real_fn_base2full[src]
            print "  %s => %s" % (src, dst)
            il.set_name(dst)

        project.set_file_name(None)
        fn_obj = None

        # Will happen if failed to match
        # be optimistic: cpclean work will be wasted but avoids parsing project twice
        if len(project.get_control_point_lines()) == 0:
            print "WARNING: failed"
            return None
        return project
示例#17
0
    def try_supertile(self, st_bounds):
        '''x0/1 and y0/1 are global absolute coordinates'''
        # First generate all of the valid tiles across this area to see if we can get any useful work done?
        # every supertile should have at least one solution or the bounds aren't good
        x0, x1, y0, y1 = st_bounds

        bench = Benchmark()
        try:
            if self.st_dir:
                # nah...tiff takes up too much space
                dst = os.path.join(self.st_dir,
                                   'st_%06dx_%06dy.jpg' % (x0, y0))
                if os.path.exists(dst):
                    # normally this is a .tif so slight loss in quality
                    img = PImage.from_file(dst)
                    print 'supertile short circuit on already existing: %s' % (
                        dst, )
                    return img

            # st_081357x_000587y.jpg
            temp_file = ManagedTempFile.get(None,
                                            '.tif',
                                            prefix_mangle='st_%06dx_%06dy_' %
                                            (x0, y0))

            stitcher = PartialStitcher(self.pto,
                                       st_bounds,
                                       temp_file.file_name,
                                       self.i,
                                       self.running,
                                       pprefix=self.pprefix)
            stitcher.enblend_lock = self.enblend_lock
            stitcher.nona_args = self.nona_args
            stitcher.enblend_args = self.enblend_args

            if self.dry:
                print 'dry: skipping partial stitch'
                stitcher = None
            else:
                stitcher.run()

            print
            print 'phase 3: loading supertile image'
            if self.dry:
                print 'dry: skipping loading PTO'
                img_fn = None
            else:
                if self.st_dir:
                    self.st_fns.put(dst)

                    #shutil.copyfile(temp_file.file_name, dst)
                    args = [
                        'convert', '-quality', '90', temp_file.file_name, dst
                    ]
                    print 'going to execute: %s' % (args, )
                    subp = subprocess.Popen(args,
                                            stdout=None,
                                            stderr=None,
                                            shell=False)
                    subp.communicate()
                    if subp.returncode != 0:
                        raise Exception('Failed to copy stitched file')

                    # having some problems that looks like file isn't getting written to disk
                    # monitoring for such errors
                    # remove if I can root cause the source of these glitches
                    for i in xrange(30):
                        if os.path.exists(dst):
                            break
                        if i == 0:
                            print 'WARNING: soften missing strong blur dest file name %s, waiting a bit...' % (
                                dst, )
                        time.sleep(0.1)
                    else:
                        raise Exception(
                            'Missing soften strong blur output file name %s' %
                            dst)

                # FIXME: was passing loaded image object
                # Directory should delete on exit
                # otherwise parent can delete it
                #img = PImage.from_file(temp_file.file_name)
                img_fn = temp_file.file_name
                # prevent deletion
                temp_file.file_name = ''

                #print 'supertile width: %d, height: %d' % (img.width(), img.height())
                print 'Supertile done w/ fn %s' % (img_fn, )
            return img_fn
        except:
            print 'supertile failed at %s' % (bench, )
            raise
示例#18
0
	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
示例#19
0
    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()        
示例#20
0
	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()		
示例#21
0
	def control_points_by_subimage(self, pair, pair_images):
		'''
		Just work on the overlap section, maybe even less
		'''
		overlap = 1.0 / 3.0
		
		images = [PImage.from_file(image_file_name) for image_file_name in pair_images]
		
		'''
		image_0 used as reference
		4 basic situations: left, right, up right
		8 extended: 4 basic + corners
		Pairs should be sorted, which simplifies the logic
		'''
		sub_image_0_x_delta = 0
		sub_image_0_y_delta = 0
		sub_image_1_x_end = images[1].width()
		sub_image_1_y_end = images[1].height()

		# image 0 left of image 1?
		if pair.first.col < pair.second.col:
			# Keep image 0 right, image 1 left
			sub_image_0_x_delta = int(images[0].width() * (1.0 - overlap))
			sub_image_1_x_end = int(images[1].width() * overlap)
		
		# image 0 above image 1?
		if pair.first.row < pair.second.row:
			# Keep image 0 top, image 1 bottom
			sub_image_0_y_delta = int(images[0].height() * (1.0 - overlap))
			sub_image_1_y_end = int(images[1].height() * overlap)
		
		'''
		print 'image 0 x delta: %d, y delta: %d' % (sub_image_0_x_delta, sub_image_0_y_delta)
		Note y starts at top in PIL
		'''
		sub_image_0 = images[0].subimage(sub_image_0_x_delta, None, sub_image_0_y_delta, None)
		sub_image_1 = images[1].subimage(None, sub_image_1_x_end, None, sub_image_1_y_end)
		sub_image_0_file = ManagedTempFile.get(None, '.jpg')
		sub_image_1_file = ManagedTempFile.get(None, '.jpg')
		print 'sub image 0: width=%d, height=%d, name=%s' % (sub_image_0.width(), sub_image_0.height(), sub_image_0_file.file_name)
		print 'sub image 1: width=%d, height=%d, name=%s' % (sub_image_1.width(), sub_image_1.height(), sub_image_0_file.file_name)
		#sys.exit(1)
		sub_image_0.image.save(sub_image_0_file.file_name)
		sub_image_1.image.save(sub_image_1_file.file_name)
		
		sub_pair_images = (sub_image_0_file.file_name, sub_image_1_file.file_name)
		# image index to subimage file name link (not symbolic link)
		index_to_sub_file_name = dict()
		imgfile_index = 0
		# subimage file name symbolic link to subimage file name
		# this should be taken care of inside of control point actually
		#sub_link_to_sub = dict()
		# subimage to the image it came from
		sub_to_real = dict()
		sub_to_real[sub_image_0_file.file_name] = pair_images[0]
		sub_to_real[sub_image_1_file.file_name] = pair_images[1]

		'''
		# Hugin project file
		# generated by Autopano

		# Panorama settings:
		p w8000 h1200 f2 v250 n"PSD_mask"

		# input images:
		#-imgfile 2816 704 "/tmp/pr0ntools_C21F246F52E9D691/AA9627DC60B39FC8.jpg"
		o f0 y+0.000000 r+0.000000 p+0.000000 u20 d0.000000 e0.000000 v70.000000 a0.000000 b0.000000 c0.000000
		#-imgfile 2816 704 "/tmp/pr0ntools_C21F246F52E9D691/EDE10C14171B2078.jpg"
		o f0 y+0.000000 r+0.000000 p+0.000000 u20 d0.000000 e0.000000 v70.000000 a0.000000 b0.000000 c0.000000

		# Control points:
		c n0 N1 x1024 y176 X555 Y119
		# Control Point No 0: 1.00000
		c n0 N1 x1047 y160 X578 Y105
		...




		autopano-sift-c style file
		
		# Hugin project file generated by APSCpp

		p f2 w3000 h1500 v360  n"JPEG q90"
		m g1 i0

		i w2816 h704 f0 a0 b-0.01 c0 d0 e0 p0 r0 v180 y0  u10 n"/tmp/pr0ntools_6691335AD228382E.jpg"
		i w2816 h938 f0 a0 b-0.01 c0 d0 e0 p0 r0 v180 y0  u10 n"/tmp/pr0ntools_64D97FF4621BC36E.jpg"

		v p1 r1 y1

		# automatically generated control points
		c n0 N1 x1142.261719 y245.074757 X699.189408 Y426.042661 t0
		c n0 N1 x887.417450 y164.602097 X1952.346197 Y921.975829 t0
		...
		c n0 N1 x823.803714 y130.802771 X674.596763 Y335.994699 t0
		c n0 N1 x1097.192159 y121.170416 X937.394996 Y329.998934 t0

		# :-)
		'''
		fast_pair_project = self.control_point_gen.generate_core(sub_pair_images)
		if fast_pair_project is None:
			print 'WARNING: failed to gen control points @ %s' % repr(pair)
			return None
		out = ''
		part_pair_index = 0
		for line in fast_pair_project.__repr__().split('\n'):
			if len(line) == 0:
				new_line = ''
			# This type of line is gen by autopano-sift-c
			elif line[0] == 'c':
				# c n0 N1 x1142.261719 y245.074757 X699.189408 Y426.042661 t0
				
				'''
				Okay def alphabetical issues
				# Not strictly related to this code, but close enough
				if not index_to_sub_file_name[0] == sub_image_0_file:
					print '0 index indicated file: %s, pair gen order expected %s' % (index_to_sub_file_name[0], sub_image_0_file)
					raise Exception('mismatch')
				if not index_to_sub_file_name[1] == sub_image_1_file:
					print '1 index indicated file: %s, pair gen order expected %s' % (index_to_sub_file_name[1], sub_image_1_file)
					raise Exception('mismatch')
				'''
				
				# Parse
				parts = line.split()
				if not parts[1] == 'n0':
					print parts[1]
					raise Exception('mismatch')
				if not parts[2] == 'N1':
					print parts[2]
					raise Exception('mismatch')
					
				x = float(parts[3][1:])								
				y = float(parts[4][1:])
				X = float(parts[5][1:])
				Y = float(parts[6][1:])
		
				#sub_image_1_x_end = image_1.width()
				#sub_image_1_y_end = image_1.height()

				# Adjust the image towards the upper left hand corner
				if index_to_sub_file_name[0] == sub_image_0_file.file_name:
					# normal adjustment
					x += sub_image_0_x_delta
					y += sub_image_0_y_delta
				elif index_to_sub_file_name[1] == sub_image_0_file.file_name:
					# they got flipped
					X += sub_image_0_x_delta
					Y += sub_image_0_y_delta
				else:
					print index_to_sub_file_name
					print 'index_to_sub_file_name[0]: %s' % repr(index_to_sub_file_name[0])
					print 'index_to_sub_file_name[1]: %s' % repr(index_to_sub_file_name[1])
					print 'sub_image_0_file: %s' % repr(sub_image_0_file)
					print 'sub_image_1_file: %s' % repr(sub_image_1_file)
					raise Exception("confused")
		
				# Write
				new_line = "c n0 N1 x%f y%f X%f Y%f t0" % (x, y, X, Y)
				out += new_line + '\n'
			# This type of line is generated by pto_merge
			elif line[0] == 'i':
				# i w2816 h704 f0 a0 b-0.01 c0 d0 e0 p0 r0 v180 y0  u10 n"/tmp/pr0ntools_6691335AD228382E.jpg"
				new_line = ''
				for part in line.split():
					t = part[0]
					if t == 'i':
						new_line += 'i'
					elif t == 'w':
						new_line += ' w%d' % images[0].width()
					elif t == 'h':
						new_line += ' w%d' % images[0].height()
					elif t == 'n':
						new_line += ' n%s' % pair_images[part_pair_index]
						part_pair_index += 1
					else:
						new_line += ' %s' % part
				print 'new line: %s' % new_line
			# These lines are generated by autopanoaj
			# The comment line is literally part of the file format, some sort of bizarre encoding
			# #-imgfile 2816 704 "/tmp/pr0ntools_2D24DE9F6CC513E0/pr0ntools_6575AA69EA66B3C3.jpg"
			# o f0 y+0.000000 r+0.000000 p+0.000000 u20 d0.000000 e0.000000 v70.000000 a0.000000 b0.000000 c0.000000
			elif line.find('#-imgfile') == 0:
				# Replace pseudo file names with real ones
				new_line = line
				index_to_sub_file_name[imgfile_index] = line.split('"')[1]
				imgfile_index += 1
			else:
				new_line = line
			out += new_line + '\n'
		else:
			out += line + '\n'

		
		for k in sub_to_real:
			v = sub_to_real[k]
			print 'Replacing %s => %s' % (k, v)
			out = out.replace(k, v)

		final_pair_project = PTOProject.from_text(out)
		return final_pair_project
示例#22
0
    def control_points_by_subimage(self, pair, image_fn_pair):
        '''Stitch two images together by cropping to restrict overlap'''

        # subimage_factor: (y, x) overlap percent tuple or none for default
        # pair: pair of row/col or coordinate positions (used to determine relative positions)
        # (0, 0) at upper left
        # image_fn_pair: pair of image file names

        print 'Preparing subimage stitch on %s:%s' % (image_fn_pair[0], image_fn_pair[1])
        '''
        Just work on the overlap section, maybe even less
        '''

        images = [PImage.from_file(image_file_name) for image_file_name in image_fn_pair]

        '''
        image_0 used as reference
        4 basic situations: left, right, up right
        8 extended: 4 basic + corners
        Pairs should be sorted, which simplifies the logic
        '''
        sub_image_0_x_delta = 0
        sub_image_0_y_delta = 0
        sub_image_1_x_end = images[1].width()
        sub_image_1_y_end = images[1].height()

        # Add some backlash margin
        # "more overlap" means will try a slightly larger area
        #margin = 0.05
        x_overlap = self.x_overlap
        y_overlap = self.y_overlap

        # image 0 left of image 1?
        if pair.first.col < pair.second.col:
            # Keep image 0 right, image 1 left
            sub_image_0_x_delta = int(images[0].width() * x_overlap)
            sub_image_1_x_end = int(round(images[1].width() * (1.0 - x_overlap)))

        # image 0 above image 1?
        if pair.first.row < pair.second.row:
            # Keep image 0 top, image 1 bottom
            sub_image_0_y_delta = int(images[0].height() * y_overlap)
            sub_image_1_y_end = int(round(images[1].height() * (1.0 - y_overlap)))

        '''
        print 'image 0 x delta: %d, y delta: %d' % (sub_image_0_x_delta, sub_image_0_y_delta)
        Note y starts at top in PIL
        '''
        sub_image_0 = images[0].subimage(sub_image_0_x_delta, None, sub_image_0_y_delta, None)
        sub_image_1 = images[1].subimage(None, sub_image_1_x_end, None, sub_image_1_y_end)
        sub_image_0_file = ManagedTempFile.get(None, '.jpg')
        sub_image_1_file = ManagedTempFile.get(None, '.jpg')
        print 'sub image 0: width=%d, height=%d, name=%s' % (sub_image_0.width(), sub_image_0.height(), sub_image_0_file.file_name)
        print 'sub image 1: width=%d, height=%d, name=%s' % (sub_image_1.width(), sub_image_1.height(), sub_image_1_file.file_name)
        #sys.exit(1)
        sub_image_0.image.save(sub_image_0_file.file_name)
        sub_image_1.image.save(sub_image_1_file.file_name)

        sub_image_fn_pair = (sub_image_0_file.file_name, sub_image_1_file.file_name)
        # subimage file name symbolic link to subimage file name
        # this should be taken care of inside of control point actually
        #sub_link_to_sub = dict()
        # subimage to the image it came from
        sub_to_real = dict()
        sub_to_real[sub_image_0_file.file_name] = image_fn_pair[0]
        sub_to_real[sub_image_1_file.file_name] = image_fn_pair[1]

        # Returns a pto project object
        pair_project = self.control_point_gen.generate_core(sub_image_fn_pair)
        if pair_project is None:
            print 'WARNING: failed to gen control points @ %s' % repr(pair)
            return None

        # all we need to do is adjust xy positions
        # afaik above is way overcomplicated
        final_pair_project = pto_unsub(pair_project, (sub_image_0_file, sub_image_1_file), (sub_image_0_x_delta, sub_image_0_y_delta), sub_to_real)

        # Filenames become absolute
        #sys.exit(1)
        return final_pair_project
示例#23
0
    def control_points_by_subimage(self,
                                   pair,
                                   image_fn_pair,
                                   subimage_factor=None):
        '''Stitch two images together by cropping to restrict overlap'''

        # subimage_factor: (y, x) overlap percent tuple or none for default
        # pair: pair of row/col or coordinate positions (used to determine relative positions)
        # (0, 0) at upper left
        # image_fn_pair: pair of image file names

        print 'Preparing subimage stitch on %s:%s' % (image_fn_pair[0],
                                                      image_fn_pair[1])
        '''
        Just work on the overlap section, maybe even less
        '''

        images = [
            PImage.from_file(image_file_name)
            for image_file_name in image_fn_pair
        ]
        '''
        image_0 used as reference
        4 basic situations: left, right, up right
        8 extended: 4 basic + corners
        Pairs should be sorted, which simplifies the logic
        '''
        sub_image_0_x_delta = 0
        sub_image_0_y_delta = 0
        sub_image_1_x_end = images[1].width()
        sub_image_1_y_end = images[1].height()

        if subimage_factor:
            y_overlap = subimage_factor[0]
            x_overlap = subimage_factor[1]
        else:
            x_overlap = self.x_overlap
            y_overlap = self.y_overlap

        # image 0 left of image 1?
        if pair.first.col < pair.second.col:
            # Keep image 0 right, image 1 left
            sub_image_0_x_delta = int(images[0].width() * (1.0 - x_overlap))
            sub_image_1_x_end = int(images[1].width() * x_overlap)

        # image 0 above image 1?
        if pair.first.row < pair.second.row:
            # Keep image 0 top, image 1 bottom
            sub_image_0_y_delta = int(images[0].height() * (1.0 - y_overlap))
            sub_image_1_y_end = int(images[1].height() * y_overlap)
        '''
        print 'image 0 x delta: %d, y delta: %d' % (sub_image_0_x_delta, sub_image_0_y_delta)
        Note y starts at top in PIL
        '''
        sub_image_0 = images[0].subimage(sub_image_0_x_delta, None,
                                         sub_image_0_y_delta, None)
        sub_image_1 = images[1].subimage(None, sub_image_1_x_end, None,
                                         sub_image_1_y_end)
        sub_image_0_file = ManagedTempFile.get(None, '.jpg')
        sub_image_1_file = ManagedTempFile.get(None, '.jpg')
        print 'sub image 0: width=%d, height=%d, name=%s' % (sub_image_0.width(
        ), sub_image_0.height(), sub_image_0_file.file_name)
        print 'sub image 1: width=%d, height=%d, name=%s' % (sub_image_1.width(
        ), sub_image_1.height(), sub_image_0_file.file_name)
        #sys.exit(1)
        sub_image_0.image.save(sub_image_0_file.file_name)
        sub_image_1.image.save(sub_image_1_file.file_name)

        sub_image_fn_pair = (sub_image_0_file.file_name,
                             sub_image_1_file.file_name)
        # subimage file name symbolic link to subimage file name
        # this should be taken care of inside of control point actually
        #sub_link_to_sub = dict()
        # subimage to the image it came from
        sub_to_real = dict()
        sub_to_real[sub_image_0_file.file_name] = image_fn_pair[0]
        sub_to_real[sub_image_1_file.file_name] = image_fn_pair[1]

        # Returns a pto project object
        pair_project = self.control_point_gen.generate_core(sub_image_fn_pair)
        if pair_project is None:
            print 'WARNING: failed to gen control points @ %s' % repr(pair)
            return None

        # all we need to do is adjust xy positions
        # afaik above is way overcomplicated
        final_pair_project = pto_unsub(
            pair_project, (sub_image_0_file, sub_image_1_file),
            (sub_image_0_x_delta, sub_image_0_y_delta), sub_to_real)

        # Filenames become absolute
        #sys.exit(1)
        return final_pair_project
示例#24
0
    def generate_core(self, img_fns):
        # cpfind (and likely cpclean) trashes absolute file names
        # we need to restore them so that tools recognize the file names
        real_fn_base2full = {}

        args = list()
        project = PTOProject.from_default2()
        fn_obj = ManagedTempFile.get(None, ".pto")
        project.set_file_name(fn_obj.file_name)

        # Start with cpfind
        args.append("--prealigned")
        args.append("--fullscale")
        args.append("--minmatches")
        args.append("1")
        args.append("--ransacdist")
        args.append("5")
        args.append("--kdtreeseconddist")
        args.append("0.5")
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        # Images
        for img_fn in img_fns:
            # xxx: why do we take the realpath?
            real_fn = os.path.realpath(img_fn)
            real_fn_base2full[os.path.basename(real_fn)] = img_fn
            project.add_image(real_fn, def_opt=True)

        project.save()
        print
        print
        print
        print project.get_text()
        print
        print
        print

        #(rc, output) = Execute.with_output('cpfind', args, print_output=self.print_output)
        print 'cpfind' + ' '.join(args)
        (rc, output) = exc_ret_istr('cpfind',
                                    args,
                                    print_out=self.print_output)

        print 'PanoCP: cpfind done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            # Happens very rarely
            # 2018-01-24T04:00:18.720954: Exception: Bad rc: -11
            # Log it but consider it a known failure
            if rc == -11:
                return None
            raise Exception('Bad rc: %d' % rc)

        # Now run cpclean
        args = list()
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        (rc, output) = exc_ret_istr('cpclean',
                                    args,
                                    print_out=self.print_output)
        print 'PanoCP: cpclean done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            raise Exception('Bad rc: %d' % rc)

        # Now run geocpset
        args = list()
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        (rc, output) = exc_ret_istr('geocpset',
                                    args,
                                    print_out=self.print_output)
        print 'PanoCP: geocpset done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            raise Exception('Bad rc: %d' % rc)

        project.reopen()
        print 'Fixing image lines...'
        for il in project.image_lines:
            src = il.get_name()
            dst = real_fn_base2full[src.split('/')[-1]]
            print '  %s => %s' % (src, dst)
            il.set_name(dst)

        project.set_file_name(None)
        fn_obj = None

        # Will happen if failed to match
        # be optimistic: cpclean work will be wasted but avoids parsing project twice
        if len(project.get_control_point_lines()) == 0:
            print 'WARNING: failed'
            return None
        return project
示例#25
0
    def generate_core(self, img_fns):
        # cpfind (and likely cpclean) trashes absolute file names
        # we need to restore them so that tools recognize the file names
        real_fn_base2full = {}

        args = list()
        project = PTOProject.from_default2()
        fn_obj = ManagedTempFile.get(None, ".pto")
        project.set_file_name(fn_obj.file_name)

        # Start with cpfind
        args.append("--multirow")
        args.append("--fullscale")
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        # Images
        for img_fn in img_fns:
            # xxx: why do we take the realpath?
            real_fn = os.path.realpath(img_fn)
            real_fn_base2full[os.path.basename(real_fn)] = img_fn
            project.add_image(real_fn, def_opt=True)

        project.save()
        print
        print
        print
        print project.get_text()
        print
        print
        print

        #(rc, output) = Execute.with_output('cpfind', args, print_output=self.print_output)
        print 'cpfind' + ' '.join(args)
        (rc, output) = exc_ret_istr('cpfind', args, print_out=self.print_output)

        print 'PanoCP: cpfind done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            # Happens very rarely
            # 2018-01-24T04:00:18.720954: Exception: Bad rc: -11
            # Log it but consider it a known failure
            if rc == -11:
                return None
            raise Exception('Bad rc: %d' % rc)


        # Now run cpclean
        args = list()
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)

        (rc, output) = exc_ret_istr('cpclean', args, print_out=self.print_output)
        print 'PanoCP: cpclean done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            raise Exception('Bad rc: %d' % rc)


        project.reopen()
        print 'Fixing image lines...'
        for il in project.image_lines:
            src = il.get_name()
            dst = real_fn_base2full[src]
            print '  %s => %s' % (src, dst)
            il.set_name(dst)

        project.set_file_name(None)
        fn_obj = None

        # Will happen if failed to match
        # be optimistic: cpclean work will be wasted but avoids parsing project twice
        if len(project.get_control_point_lines()) == 0:
            print 'WARNING: failed'
            return None
        return project
示例#26
0
	def control_points_by_subimage(self, pair, image_fn_pair, subimage_factor = None):
		'''Stitch two images together by cropping to restrict overlap'''
		
		# subimage_factor: (y, x) overlap percent tuple or none for default
		# pair: pair of row/col or coordinate positions (used to determine relative positions)
		# (0, 0) at upper left
		# image_fn_pair: pair of image file names
		
		print 'Preparing subimage stitch on %s:%s' % (image_fn_pair[0], image_fn_pair[1])
		'''
		Just work on the overlap section, maybe even less
		'''
		
		images = [PImage.from_file(image_file_name) for image_file_name in image_fn_pair]
		
		'''
		image_0 used as reference
		4 basic situations: left, right, up right
		8 extended: 4 basic + corners
		Pairs should be sorted, which simplifies the logic
		'''
		sub_image_0_x_delta = 0
		sub_image_0_y_delta = 0
		sub_image_1_x_end = images[1].width()
		sub_image_1_y_end = images[1].height()

		if subimage_factor:
			y_overlap = subimage_factor[0]
			x_overlap = subimage_factor[1]
		else:
			x_overlap = self.x_overlap
			y_overlap = self.y_overlap

		# image 0 left of image 1?
		if pair.first.col < pair.second.col:
			# Keep image 0 right, image 1 left
			sub_image_0_x_delta = int(images[0].width() * (1.0 - x_overlap))
			sub_image_1_x_end = int(images[1].width() * x_overlap)
		
		# image 0 above image 1?
		if pair.first.row < pair.second.row:
			# Keep image 0 top, image 1 bottom
			sub_image_0_y_delta = int(images[0].height() * (1.0 - y_overlap))
			sub_image_1_y_end = int(images[1].height() * y_overlap)
		
		'''
		print 'image 0 x delta: %d, y delta: %d' % (sub_image_0_x_delta, sub_image_0_y_delta)
		Note y starts at top in PIL
		'''
		sub_image_0 = images[0].subimage(sub_image_0_x_delta, None, sub_image_0_y_delta, None)
		sub_image_1 = images[1].subimage(None, sub_image_1_x_end, None, sub_image_1_y_end)
		sub_image_0_file = ManagedTempFile.get(None, '.jpg')
		sub_image_1_file = ManagedTempFile.get(None, '.jpg')
		print 'sub image 0: width=%d, height=%d, name=%s' % (sub_image_0.width(), sub_image_0.height(), sub_image_0_file.file_name)
		print 'sub image 1: width=%d, height=%d, name=%s' % (sub_image_1.width(), sub_image_1.height(), sub_image_0_file.file_name)
		#sys.exit(1)
		sub_image_0.image.save(sub_image_0_file.file_name)
		sub_image_1.image.save(sub_image_1_file.file_name)
		
		sub_image_fn_pair = (sub_image_0_file.file_name, sub_image_1_file.file_name)
		# subimage file name symbolic link to subimage file name
		# this should be taken care of inside of control point actually
		#sub_link_to_sub = dict()
		# subimage to the image it came from
		sub_to_real = dict()
		sub_to_real[sub_image_0_file.file_name] = image_fn_pair[0]
		sub_to_real[sub_image_1_file.file_name] = image_fn_pair[1]

		# Returns a pto project object
		fast_pair_project = self.control_point_gen.generate_core(sub_image_fn_pair)
		if fast_pair_project is None:
			print 'WARNING: failed to gen control points @ %s' % repr(pair)
			return None
		oto_text = str(fast_pair_project)
		if 0:
			print oto_text
		# are we actually doing anything useful here?
		# The original intention was to make dead sure we had the right file order
		# but I'm pretty sure its consistent and we don't need to parse the comments
		final_pair_project = ajpto2pto_text(oto_text, sub_image_0_file, sub_image_1_file, sub_image_0_x_delta, sub_image_0_y_delta, sub_to_real)
		
		# Filenames become absolute
		#sys.exit(1)
		return final_pair_project
示例#27
0
    def try_supertile(self, st_bounds):
        '''x0/1 and y0/1 are global absolute coordinates'''
        # First generate all of the valid tiles across this area to see if we can get any useful work done?
        # every supertile should have at least one solution or the bounds aren't good
        x0, x1, y0, y1 = st_bounds

        bench = Benchmark()
        try:
            if self.st_dir:
                # nah...tiff takes up too much space
                dst = os.path.join(self.st_dir, 'st_%06dx_%06dy.jpg' % (x0, y0))
                if os.path.exists(dst):
                    # normally this is a .tif so slight loss in quality
                    print 'supertile short circuit on already existing: %s' % (dst,)
                    return dst
                
            # st_081357x_000587y.jpg
            temp_file = ManagedTempFile.get(None, '.tif', prefix_mangle='st_%06dx_%06dy_' % (x0, y0))

            stitcher = PartialStitcher(self.pto, st_bounds, temp_file.file_name, self.i, self.running, pprefix=self.pprefix)
            stitcher.enblend_lock = self.enblend_lock
            stitcher.nona_args = self.nona_args
            stitcher.enblend_args = self.enblend_args

            if self.dry:
                print 'dry: skipping partial stitch'
                stitcher = None
            else:
                stitcher.run()
        
            print
            print 'phase 3: loading supertile image'
            if self.dry:
                print 'dry: skipping loading PTO'
                img_fn = None
            else:
                if self.st_dir:
                    self.st_fns.put(dst)
                    
                    #shutil.copyfile(temp_file.file_name, dst)
                    args = ['convert',
                            '-quality', '90', 
                            temp_file.file_name, dst]                    
                    print 'going to execute: %s' % (args,)
                    subp = subprocess.Popen(args, stdout=None, stderr=None, shell=False)
                    subp.communicate()
                    if subp.returncode != 0:
                        raise Exception('Failed to copy stitched file')

                    # having some problems that looks like file isn't getting written to disk
                    # monitoring for such errors
                    # remove if I can root cause the source of these glitches
                    for i in xrange(30):
                        if os.path.exists(dst):
                            break
                        if i == 0:
                            print 'WARNING: soften missing strong blur dest file name %s, waiting a bit...' % (dst,)
                        time.sleep(0.1)
                    else:
                        raise Exception('Missing soften strong blur output file name %s' % dst)

                # FIXME: was passing loaded image object
                # Directory should delete on exit
                # otherwise parent can delete it
                #img = PImage.from_file(temp_file.file_name)
                img_fn = temp_file.file_name
                # prevent deletion
                temp_file.file_name = ''
                
                #print 'supertile width: %d, height: %d' % (img.width(), img.height())
                print 'Supertile done w/ fn %s' % (img_fn,)
            return img_fn
        except:
            print 'supertile failed at %s' % (bench,)
            raise
示例#28
0
	def try_supertile(self, x0, x1, y0, y1):
		'''x0/1 and y0/1 are global absolute coordinates'''
		# First generate all of the valid tiles across this area to see if we can get any useful work done?
		# every supertile should have at least one solution or the bounds aren't good
		
		bench = Benchmark()
		try:
			temp_file = ManagedTempFile.get(None, '.tif')

			bounds = [x0, x1, y0, y1]
			#out_name_base = "%s/r%03d_c%03d" % (self.out_dir, row, col)
			#print 'Working on %s' % out_name_base
			stitcher = PartialStitcher(self.pto, bounds, temp_file.file_name)
			if self.dry:
				print 'Dry: skipping partial stitch'
				stitcher = None
			else:
				stitcher.run()
		
			print
			print 'Phase 3: loading supertile image'
			if self.dry:
				print 'Dry: skipping loading PTO'
				img = None
			else:
				img = PImage.from_file(temp_file.file_name)
				print 'Supertile width: %d, height: %d' % (img.width(), img.height())
			new = 0
		
			
		
			'''
			A tile is valid if its in a safe location
			There are two ways for the location to be safe:
			-No neighboring tiles as found on canvas edges
			-Sufficiently inside the blend area that artifacts should be minimal
			'''
			gen_tiles = 0
			print
			# TODO: get the old info back if I miss it after yield refactor
			print 'Phase 4: chopping up supertile'
			self.msg('step(x: %d, y: %d)' % (self.tw, self.th), 3)
			#self.msg('x in xrange(%d, %d, %d)' % (xt0, xt1, self.tw), 3)
			#self.msg('y in xrange(%d, %d, %d)' % (yt0, yt1, self.th), 3)
		
			for (y, x) in self.gen_supertile_tiles(x0, x1, y0, y1):	
				# If we made it this far the tile can be constructed with acceptable enblend artifacts
				row = self.y2row(y)
				col = self.x2col(x)
			
				# Did we already do this tile?
				if self.is_done(row, col):
					# No use repeating it although it would be good to diff some of these
					print 'Rejecting tile x%d, y%d / r%d, c%d: already done' % (x, y, row, col)
					continue
			
				# note that x and y are in whole pano coords
				# we need to adjust to our frame
				# row and col on the other hand are used for global naming
				self.make_tile(img, x - x0, y - y0, row, col)
				gen_tiles += 1
			bench.stop()
			print 'Generated %d new tiles for a total of %d / %d in %s' % (gen_tiles, len(self.closed_list), self.net_expected_tiles, str(bench))
			if gen_tiles == 0:
				raise Exception("Didn't generate any tiles")
			# temp_file should be automatically deleted upon exit
		except:
			print 'Supertile failed at %s' % bench
			raise
示例#29
0
    def do_generate_control_points_by_pair(self, pair, image_fn_pair):
        '''high level function uses by sub-stitches.  Given a pair of images make a best effort to return a .pto object'''
        '''
        pair: ImageCoordinatePair() object
        image_fn_pair: tuple of strings
        
        Algorithm:
        First try to stitch normally (either whole image or partial depending on the mode)
        If that doesn't succeed and softening is enabled try up to three times to soften to produce a match
        If that still doesn't produce a decent solution return None and let higher levels deal with
        '''
        soften_iterations = 3

        print
        print
        #print 'Generating project for image pair (%s / %s, %s / %s)' % (image_fn_pair[0], str(pair[0]), image_fn_pair[1], str(pair[1]))
        print 'Generating project for image pair (%s, %s)' % (image_fn_pair[0],
                                                              image_fn_pair[1])

        if True:
            # Try raw initially
            print 'Attempting sharp match...'
            ret_project = self.try_control_points_with_position(
                pair, image_fn_pair)
            if ret_project:
                return ret_project

        print 'WARNING: bad project, attempting soften...'

        soften_image_file_0_managed = ManagedTempFile.from_same_extension(
            image_fn_pair[0])
        soften_image_file_1_managed = ManagedTempFile.from_same_extension(
            image_fn_pair[1])
        print 'Soften fn0: %s' % soften_image_file_0_managed.file_name
        print 'Soften fn1: %s' % soften_image_file_1_managed.file_name

        for i in xrange(soften_iterations):
            self.soften_try[i] += 1

            # And then start screwing with it
            # Wonder if we can combine features from multiple soften passes?
            # Or at least take the maximum
            # Do features get much less accurate as the soften gets up there?

            print 'Attempting soften %d / %d' % (i + 1, soften_iterations)

            if i == 0:
                soften_composite(image_fn_pair[0],
                                 soften_image_file_0_managed.file_name)
                soften_composite(image_fn_pair[1],
                                 soften_image_file_1_managed.file_name)
            else:
                soften_composite(soften_image_file_0_managed.file_name)
                soften_composite(soften_image_file_1_managed.file_name)

            pair_soften_image_file_names = (
                soften_image_file_0_managed.file_name,
                soften_image_file_1_managed.file_name)
            ret_project = self.try_control_points_with_position(
                pair, pair_soften_image_file_names)
            # Did we win?
            if ret_project:
                # Fixup the project to reflect the correct file names
                text = str(ret_project)
                if 0:
                    print
                    print 'Before sub'
                    print
                    print str(ret_project)
                    print
                    print
                    print
                print '%s => %s' % (soften_image_file_0_managed.file_name,
                                    image_fn_pair[0])
                text = text.replace(soften_image_file_0_managed.file_name,
                                    image_fn_pair[0])
                print '%s => %s' % (soften_image_file_1_managed.file_name,
                                    image_fn_pair[1])
                text = text.replace(soften_image_file_1_managed.file_name,
                                    image_fn_pair[1])

                ret_project.set_text(text)
                if 0:
                    print
                    print 'After sub'
                    print
                    print str(ret_project)
                    print
                    print
                    print
                    #sys.exit(1)
                self.soften_ok[i] += 1
                print 'Soften try: %s' % (self.soften_try, )
                print 'Soften ok: %s' % (self.soften_ok, )
                return ret_project

        print 'WARNING: gave up on generating control points!'
        return None
示例#30
0
	def generate_control_points(self, pair, pair_images):
		soften_iterations = 3
	
		if True:
			# Try raw initially
			ret_project = self.try_control_points(pair, pair_images)
			if ret_project:
				return ret_project
		
		print 'WARNING: bad project, attempting soften...'

		soften_image_file_0_managed = ManagedTempFile.from_same_extension(pair_images[0])
		soften_image_file_1_managed = ManagedTempFile.from_same_extension(pair_images[1])

		softener = Softener()
		first_run = True

		for i in range(0, soften_iterations):
			# And then start screwing with it
			# Wonder if we can combine features from multiple soften passes?
			# Or at least take the maximum
			# Do features get much less accurate as the soften gets up there?
		
			print 'Attempting soften %d / %d' % (i + 1, soften_iterations)

			if first_run:			
				softener.run(pair_images[0], soften_image_file_0_managed.file_name)
				softener.run(pair_images[1], soften_image_file_1_managed.file_name)
			else:
				softener.run(soften_image_file_0_managed.file_name)
				softener.run(soften_image_file_1_managed.file_name)			
			
			pair_soften_image_file_names = (soften_image_file_0_managed.file_name, soften_image_file_1_managed.file_name)
			ret_project = self.try_control_points(pair, pair_soften_image_file_names)
			# Did we win?
			if ret_project:
				# Fixup the project to reflect the correct file names
				text = ret_project.__repr__()
				print
				print 'Before sub'
				print
				print ret_project.__repr__()
				print
				print
				print
				print '%s => %s' % (soften_image_file_0_managed.file_name, pair_images[0])
				text = text.replace(soften_image_file_0_managed.file_name, pair_images[0])
				print '%s => %s' % (soften_image_file_1_managed.file_name, pair_images[1])
				text = text.replace(soften_image_file_1_managed.file_name, pair_images[1])

				ret_project.set_text(text)
				print
				print 'After sub'
				print
				print ret_project.__repr__()
				print
				print
				print
				#sys.exit(1)
				return ret_project
				
			first_run = False

		print 'WARNING: gave up on generating control points!' 
		return None
示例#31
0
    def do_generate_control_points_by_pair(self, pair, image_fn_pair):
        '''high level function uses by sub-stitches.  Given a pair of images make a best effort to return a .pto object'''
        '''
        pair: ImageCoordinatePair() object
        image_fn_pair: tuple of strings

        Algorithm:
        First try to stitch normally (either whole image or partial depending on the mode)
        If that doesn't succeed and softening is enabled try up to three times to soften to produce a match
        If that still doesn't produce a decent solution return None and let higher levels deal with
        '''
        soften_iterations = 3

        print
        print
        #print 'Generating project for image pair (%s / %s, %s / %s)' % (image_fn_pair[0], str(pair[0]), image_fn_pair[1], str(pair[1]))
        print 'Generating project for image pair (%s, %s)' % (image_fn_pair[0], image_fn_pair[1])

        if True:
            # Try raw initially
            print 'Attempting sharp match...'
            ret_project = self.try_control_points_with_position(pair, image_fn_pair)
            if ret_project:
                return ret_project

        print 'WARNING: bad project, attempting soften...'

        soften_image_file_0_managed = ManagedTempFile.from_same_extension(image_fn_pair[0])
        soften_image_file_1_managed = ManagedTempFile.from_same_extension(image_fn_pair[1])
        print 'Soften fn0: %s' % soften_image_file_0_managed.file_name
        print 'Soften fn1: %s' % soften_image_file_1_managed.file_name

        for i in xrange(soften_iterations):
            self.soften_try[i] += 1

            # And then start screwing with it
            # Wonder if we can combine features from multiple soften passes?
            # Or at least take the maximum
            # Do features get much less accurate as the soften gets up there?

            print 'Attempting soften %d / %d' % (i + 1, soften_iterations)

            if i == 0:
                soften_composite(image_fn_pair[0], soften_image_file_0_managed.file_name)
                soften_composite(image_fn_pair[1], soften_image_file_1_managed.file_name)
            else:
                soften_composite(soften_image_file_0_managed.file_name)
                soften_composite(soften_image_file_1_managed.file_name)

            pair_soften_image_file_names = (soften_image_file_0_managed.file_name, soften_image_file_1_managed.file_name)
            ret_project = self.try_control_points_with_position(pair, pair_soften_image_file_names)
            # Did we win?
            if ret_project:
                # Fixup the project to reflect the correct file names
                text = str(ret_project)
                if 0:
                    print
                    print 'Before sub'
                    print
                    print str(ret_project)
                    print
                    print
                    print
                print '%s => %s' % (soften_image_file_0_managed.file_name, image_fn_pair[0])
                text = text.replace(soften_image_file_0_managed.file_name, image_fn_pair[0])
                print '%s => %s' % (soften_image_file_1_managed.file_name, image_fn_pair[1])
                text = text.replace(soften_image_file_1_managed.file_name, image_fn_pair[1])

                ret_project.set_text(text)
                if 0:
                    print
                    print 'After sub'
                    print
                    print str(ret_project)
                    print
                    print
                    print
                    #sys.exit(1)
                self.soften_ok[i] += 1
                print 'Soften try: %s' % (self.soften_try,)
                print 'Soften ok: %s' % (self.soften_ok,)
                return ret_project

        print 'WARNING: gave up on generating control points!'
        return None
示例#32
0
    def generate_core(self, img_fns):
        # cpfind (and likely cpclean) trashes absolute file names
        # we need to restore them so that tools recognize the file names
        real_fn_base2full = {}
        
        args = list()
        project = PTOProject.from_default2()
        fn_obj = ManagedTempFile.get(None, ".pto")
        project.set_file_name(fn_obj.file_name)
        
        # Start with cpfind
        args.append("--multirow")
        args.append("--fullscale")
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)
        
        # Images
        for img_fn in img_fns:
            # xxx: why do we take the realpath?
            real_fn = os.path.realpath(img_fn)
            real_fn_base2full[os.path.basename(real_fn)] = img_fn
            project.add_image(real_fn, def_opt=True)

        project.save()
        print
        print
        print
        print project.get_text()
        print
        print
        print
 
        #(rc, output) = Execute.with_output('cpfind', args, print_output=self.print_output)
        (rc, output) = exc_ret_istr('cpfind', args, print_out=self.print_output)
        
        print 'PanoCP: cpfind done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            raise Exception('Bad rc: %d' % rc)
        
        
        # Now run cpclean
        args = list()
        # output file
        args.append("-o")
        args.append(project.file_name)
        # input file
        args.append(project.file_name)
        
        (rc, output) = exc_ret_istr('cpclean', args, print_out=self.print_output)
        print 'PanoCP: cpclean done'
        if not rc == 0:
            print
            print
            print
            print 'output:'
            print output
            print
            raise Exception('Bad rc: %d' % rc)


        project.reopen()
        print 'Fixing image lines...'
        for il in project.image_lines:
            src = il.get_name()
            dst = real_fn_base2full[src]
            print '  %s => %s' % (src, dst)
            il.set_name(dst)
        
        project.set_file_name(None)
        fn_obj = None

        # Will happen if failed to match
        # be optimistic: cpclean work will be wasted but avoids parsing project twice
        if len(project.get_control_point_lines()) == 0:
            print 'WARNING: failed'
            return None
        return project