def gen_pairwise_surf_control_points(proj_file, img_fns, display=False): """ Use OpenCV for pairwaise image matching cf. <opencv samples dir>/find_obj.py """ # get the kps of the first frame img1, kp1, ds1 = get_surf_kps(img_fns[0]) # match the frame t with t+1 cpoints = [] for i2 in range(1, len(img_fns)): # get the kps of frame t+1 img2, kp2, ds2 = get_surf_kps(img_fns[i2]) # get the control points cp1, cp2 = get_pairwise_matches(kp1, ds1, kp2, ds2) # estimate the homography H, mask = cv2.findHomography(cp1, cp2, cv2.RANSAC) mask = mask.squeeze() > 0 # display the matches and homography if display: hom_warp_image(img1, cp1, img2, cp2, H, mask) # filter out the outlier matches cp1 = cp1[mask] cp2 = cp2[mask] # add the control points cpoints.extend([hsi.ControlPoint(i2 - 1, x1, y1, i2, x2, y2) for (x1, y1), (x2, y2) in zip(cp1, cp2)]) # next -> cur img1, kp1, ds1 = img2, kp2, ds2 # write to pto pano = hsi.Panorama() pano.readData(hsi.ifstream(proj_file)) pano.setCtrlPoints(cpoints) pano.writeData(hsi.ofstream(proj_file))
def standalone() : import sys # to look at the argument vector import hsi # to use hugin's scripting interface if len ( sys.argv ) < 2 : print ( 'usage: %s <pto file>' % sys.argv[0] ) sys.exit ( -1 ) panofile = sys.argv[1] # the only parameter: a pto file ifs = hsi.ifstream ( panofile ) # create a C++ ifstream from it pano = hsi.Panorama() # and a Panorama object success = pano.readData ( ifs ) # feed the ifstream to the pano object # check if all went well if success != hsi.DocumentData.SUCCESSFUL : # if it failed, complain print ( 'input file %s contains invalid data' % panofile ) success = -1 else : # if it succeeded, call the workhorse entry ( pano ) success = 0 # and that's it return success
def gen_pairwise_surf_control_points(proj_file, img_fns, display=False): """ Use OpenCV for pairwise image matching """ # get the kps of the first frame img1, kp1, ds1 = get_surf_kps(img_fns[0]) # match the frame t with t+1 cpoints = [] for i2 in range(1, len(img_fns)): # get the kps of frame t+1 img2, kp2, ds2 = get_surf_kps(img_fns[i2]) # get the control points cp1, cp2 = get_pairwise_matches(kp1, ds1, kp2, ds2) # estimate the homography H, mask = cv2.findHomography(cp1, cp2, cv2.RANSAC) mask = mask.squeeze() > 0 # display the matches and homography if display: homo_warp_image(img1, cp1, img2, cp2, H, mask) # filter out the outlier matches cp1 = cp1[mask] cp2 = cp2[mask] # add the control points cpoints.extend([ hsi.ControlPoint(i2 - 1, x1, y1, i2, x2, y2) for (x1, y1), (x2, y2) in zip(cp1, cp2) ]) # next -> cur img1, kp1, ds1 = img2, kp2, ds2 # write to pto pano = hsi.Panorama() pano.readData(hsi.ifstream(proj_file)) pano.setCtrlPoints(cpoints) pano.writeData(hsi.ofstream(proj_file))
def standalone(): import sys # to look at the argument vector import hsi # to use hugin's scripting interface if len(sys.argv) < 2: print('usage: %s <pto file>' % sys.argv[0]) sys.exit(-1) panofile = sys.argv[1] # the only parameter: a pto file ifs = hsi.ifstream(panofile) # create a C++ ifstream from it pano = hsi.Panorama() # and a Panorama object success = pano.readData(ifs) # feed the ifstream to the pano object # check if all went well if success != hsi.DocumentData.SUCCESSFUL: # if it failed, complain print('input file %s contains invalid data' % panofile) success = -1 else: # if it succeeded, call the workhorse entry(pano) success = 0 # and that's it return success
def stichable(self, proj_pto): ifs = ifstream(proj_pto) p = Panorama() p.readData(ifs) cpv = p.getCtrlPoints() picLinkNb = [0 for x in range(6)] distSum = 0 nbPoints = 0 for cp in cpv: picLinkNb[cp.image1Nr] += 1 picLinkNb[cp.image2Nr] += 1 nbPoints += 1 minLinksNeeded = 4 isStitchable = all(x > minLinksNeeded for x in picLinkNb) self.cp.nb_cp = nbPoints self.cp.stichable = isStitchable self.cp.save()
def main(): # when called from the command line, we import the argparse module. # This may not be part of the standard library on your system. import argparse # and create an argument parser. parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description=gpl + ''' crop_cp will remove all CPs which are either outside the panorama's ROI or inside it's ROI if the inside flag is set ''') parser.add_argument('-o', '--output', metavar='<output file>', default=None, type=str, help='write output to a different file') parser.add_argument('-i', '--inside', action='store_true', default=False, help='remove CPs inside ROI') parser.add_argument('input', metavar='<pto file>', type=str, help='pto file to be processed') if len(sys.argv) < 2: parser.print_help() return # we parse the arguments into a global variable so we can access # them from everywhere without having to pass them around global args args = parser.parse_args() if args.output: print('output: ', args.output) print('ptofile:', args.input) # first we see if we can open the input file ifs = hsi.ifstream(args.input) if not ifs.good(): raise CropCpError('cannot open input file %s' % args.input) pano = hsi.Panorama() success = pano.readData(ifs) del ifs if success != hsi.DocumentData.SUCCESSFUL: raise CropCpError('input file %s contains invalid data' % args.input) # if a separate output file was chosen, we open it now to avoid # later disappointments if args.output: ofs = hsi.ofstream(args.output) if not ofs.good(): raise CropCpError('cannot open output file %s' % args.output) # we've checked the args, now we call crop_cps() crop_cps(pano, args.inside) # if no different output file was specified, overwrite the input if not args.output: ofs = hsi.ofstream(args.input) if not ofs.good(): raise CropCpError('cannot open file %s for output' % args.input) success = pano.writeData(ofs) del ofs if success != hsi.DocumentData.SUCCESSFUL: raise CropCpError('error writing pano to %s' % args.input) # done. return 0
import hsi # hpi.py has been called standalone rather than having been # mported as a module. In this case we want to look at the # argument vector: if len ( sys.argv ) < 3 : print("use: %s panorama.pto plugin.py [plugin args]" % sys.argv[0]) sys.exit ( -12 ) # okay, there are some arguments, let's go ahead and try # opening the first one as a panorama. p = hsi.Panorama() ifs = hsi.ifstream ( sys.argv[1] ) if not ifs.good() : print("failed to open %s" % sys.argv[1]) sys.exit ( -13 ) # next, make the panorama object read the file if p.readData ( ifs ) != hsi.DocumentData.SUCCESSFUL : print("failed to read panorama data from %s" % sys.argv[1]) sys.exit ( -14 ) del ifs # if we're here, the load succeeded and we can finally call # the plugin
import sys import hsi # hpi.py has been called standalone rather than having been # mported as a module. In this case we want to look at the # argument vector: if len(sys.argv) < 3: print("use: %s panorama.pto plugin.py [plugin args]" % sys.argv[0]) sys.exit(-12) # okay, there are some arguments, let's go ahead and try # opening the first one as a panorama. p = hsi.Panorama() ifs = hsi.ifstream(sys.argv[1]) if not ifs.good(): print("failed to open %s" % sys.argv[1]) sys.exit(-13) # next, make the panorama object read the file if p.readData(ifs) != hsi.DocumentData.SUCCESSFUL: print("failed to read panorama data from %s" % sys.argv[1]) sys.exit(-14) del ifs # if we're here, the load succeeded and we can finally call # the plugin
def main() : # when called from the command line, we import the argparse module. # This may not be part of the standard library on your system. import argparse # and create an argument parser. parser = argparse.ArgumentParser ( formatter_class=argparse.RawDescriptionHelpFormatter , description = gpl + ''' crop_cp will remove all CPs which are either outside the panorama's ROI or inside it's ROI if the inside flag is set ''' ) parser.add_argument('-o', '--output', metavar='<output file>', default = None, type=str, help='write output to a different file') parser.add_argument('-i', '--inside', action='store_true', default = False, help='remove CPs inside ROI') parser.add_argument('input' , metavar = '<pto file>' , type = str , help = 'pto file to be processed' ) if len ( sys.argv ) < 2 : parser.print_help() return # we parse the arguments into a global variable so we can access # them from everywhere without having to pass them around global args args = parser.parse_args() if args.output : print ( 'output: ' , args.output ) print ( 'ptofile:' , args.input ) # first we see if we can open the input file ifs = hsi.ifstream ( args.input ) if not ifs.good() : raise CropCpError ( 'cannot open input file %s' % args.input ) pano = hsi.Panorama() success = pano.readData ( ifs ) del ifs if success != hsi.DocumentData.SUCCESSFUL : raise CropCpError ( 'input file %s contains invalid data' % args.input ) # if a separate output file was chosen, we open it now to avoid # later disappointments if args.output: ofs = hsi.ofstream ( args.output ) if not ofs.good() : raise CropCpError ( 'cannot open output file %s' % args.output ) # we've checked the args, now we call crop_cps() crop_cps ( pano , args.inside ) # if no different output file was specified, overwrite the input if not args.output : ofs = hsi.ofstream ( args.input ) if not ofs.good() : raise CropCpError ( 'cannot open file %s for output' % args.input ) success = pano.writeData ( ofs ) del ofs if success != hsi.DocumentData.SUCCESSFUL : raise CropCpError ( 'error writing pano to %s' % args.input ) # done. return 0
def optimize_geometry(proj_file, optim_vars, optim_ref_fov=False): """ Optimise the geometric parameters Parameters ---------- proj_file: string, the path to the Hugin project file (.pto) optim_vars: string, the set of variables to optimize for (separated by '_') - v: view point - p: pitch - y: yaw - r: roll - Tr{X,Y,Z}: translation optim_ref_fov: boolean, optional, default: False, whether to optimize the input's reference horizontal field of view (risky) Returns ------- optim_proj_file: string, path of the Hugin project file containing the optimized values for the desired variables. Notes ----- This is (by far) the most time consuming operation (because of hugin's autooptimiser). This is also the most likely function where the compensation process tends to fail. """ optim_proj_file = proj_file + '.optim.pto' # modify the input pto to specify the optimization variables pano = hsi.Panorama() pano.readData(hsi.ifstream(proj_file)) n_imgs = pano.getNrOfImages() var_tup = tuple(optim_vars.split('_')) for v in var_tup: assert v in ('v', 'p', 'y', 'r', 'TrX', 'TrY', 'TrZ'), \ "Unknown var {0} in {1}".format(v, optim_vars) optim_opts = [var_tup] * n_imgs # fov, pitch, roll, yaw if optim_ref_fov: # optim only field of view for 1st (reference) frame optim_opts[0] = ('v') # Note: do not optim. pitch, roll and yaw for this one, weird otherwise else: # 1st reference frame has the same fov as those of the input images optim_opts[0] = () pano.setOptimizeVector(optim_opts) pano.writeData(hsi.ofstream(proj_file)) # perform the optimization (TODO through hsi?) cmd = "autooptimiser -n -s -o {opto} {pto}" # leveling can screw things up exec_shell(cmd.format(pto=proj_file, opto=optim_proj_file)) # check for too large output (e.g. too wide panning or traveling) pano = hsi.Panorama() pano.readData(hsi.ifstream(optim_proj_file)) opts = pano.getOptions() oh = opts.getHeight() ow = opts.getWidth() if oh * ow > 1e3 * 5e3: raise ValueError( "Degenerate case: too big output size ({0}, {1})\n".format(ow, oh) + \ "May be caused by too large panning or translations\n" + \ "=> Possible fixes: use a different field of view parameter or " + \ "optimize only for different variables than {0}\n".format(optim_vars)) return optim_proj_file
def readPTO(self, filename): self.pto_nev = filename ifs = hsi.ifstream(filename) self.p.readData(ifs) del ifs
def readPTO(self, filename): self.pto_nev = filename ifs=hsi.ifstream(filename) self.p.readData(ifs) del ifs