Esempio n. 1
0
    def run(self):
        from xystitch.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)
Esempio n. 2
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
Esempio n. 3
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)
Esempio n. 4
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)
Esempio n. 5
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/xystitch_*
            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()
Esempio n. 6
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
Esempio n. 7
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