def main(): description = 'This script is for merging multiple SfM output models to one SfM model.' + \ 'Please prepare multiple OpenMVG projects which have output SfM models, and matrix to convert to global coordinate.' parser = argparse.ArgumentParser(description=description) parser.add_argument('input_csv', action='store', nargs=None, const=None, \ default=None, type=str, choices=None, metavar=None, \ help='Input CSV file which lists OpenMVG projects which will be merged.') parser.add_argument('output_dir', action='store', nargs=None, const=None, \ default=None, type=str, choices=None, metavar=None, \ help='Output directory path where merged model will be saved.') args = parser.parse_args() input_csv = args.input_csv output_dir = args.output_dir # load reconstruct parameters reconstructParam = ReconstructParam.ReconstructParam # read projects list projectList = [] with open(input_csv, "r") as f: reader = csv.reader(f) for row in reader: project = {} project["dir"] = row[0] project["sfm_data"] = row[1] project["A"] = row[2] projectList.append(project) # copy source files to output directory for project in projectList: copyOriginalFiles(project["dir"], output_dir) # prepare output directory if not os.path.isdir(os.path.join(output_dir, "Ref")): FileUtils.makedir(os.path.join(output_dir, "Ref")) if not os.path.isdir(os.path.join(output_dir, "Ref", "loc")): FileUtils.makedir(os.path.join(output_dir, "Ref", "loc")) if not os.path.isdir(os.path.join(output_dir, "Output", "SfM")): FileUtils.makedir(os.path.join(output_dir, "Output", "SfM")) if not os.path.isdir( os.path.join(output_dir, "Output", "SfM", "reconstruction")): FileUtils.makedir( os.path.join(output_dir, "Output", "SfM", "reconstruction")) if not os.path.isdir( os.path.join(output_dir, "Output", "SfM", "reconstruction", "global")): FileUtils.makedir( os.path.join(output_dir, "Output", "SfM", "reconstruction", "global")) sfmDataList = [] sfmViewBeaconDataList = [] sfmBeaconMap = None for project in projectList: if not os.path.exists(project["sfm_data"]): print "cannot find sfm data : " + project["sfm_data"] sys.exit() with open(project["sfm_data"]) as jsonFile: sfmDataList.append(json.load(jsonFile)) sfmBeaconFile = os.path.join(os.path.dirname(project["sfm_data"]), "beacon.txt") if os.path.exists(sfmBeaconFile): print "find beacon.txt for sfm data : " + project["sfm_data"] imgBeaconList, beaconMap = iBeaconUtils.readBeaconData( sfmBeaconFile) sfmViewBeaconDataList.append(imgBeaconList) if sfmBeaconMap is None: sfmBeaconMap = beaconMap else: if sfmBeaconMap != beaconMap: print "invalid find beacon.txt for sfm data : " + project[ "sfm_data"] print "beacon.txt should be same for all merged sfm_data" sys.exit() else: print "valid beacon.txt for sfm data : " + project[ "sfm_data"] AList = [] for project in projectList: AList.append(np.loadtxt(project["A"])) print "load mat : " + project["A"] print(np.loadtxt(project["A"])) print "Load 3D points" pointIdList = [] pointList = [] for sfmData in sfmDataList: pointId, point = mergeSfM.getAll3DPointloc(sfmData) pointn = np.asarray(point, dtype=np.float).T pointIdList.append(pointId) pointList.append(pointn) # merge models mergeSfmData = None mergePointId = None mergePointn = None mergeSfmViewBeaconData = None for idx in range(0, len(sfmDataList)): if idx == 0: mergeSfmData = sfmDataList[0] mergeSfM.transform_sfm_data(mergeSfmData, AList[0]) if len(sfmViewBeaconDataList) > 0: mergeSfmViewBeaconData = sfmViewBeaconDataList[0] else: ransacThres = mergeSfM.findMedianStructurePointsThres( mergeSfmData, reconstructParam.ransacStructureThresMul) print "thres to merge 3D points : " + str(ransacThres) inlierMap = findInliersByKnownTransform(mergePointId, pointIdList[idx], mergePointn, pointList[idx], AList[idx], ransacThres) print "number of points in base model : " + str(len( mergePointn[0])) print "number of points in model " + str(idx) + " : " + str( len(pointList[idx])) print "number of inliers : " + str(len(inlierMap)) if len(sfmViewBeaconDataList) > 0: mergeSfM.merge_sfm_data(mergeSfmData, sfmDataList[idx], AList[idx], {x[0]: x[1] for x in inlierMap}, mergeSfmViewBeaconData, sfmViewBeaconDataList[idx]) else: mergeSfM.merge_sfm_data(mergeSfmData, sfmDataList[idx], AList[idx], {x[0]: x[1] for x in inlierMap}) mergePointId, mergePoint = mergeSfM.getAll3DPointloc(mergeSfmData) mergePointn = np.asarray(mergePoint, dtype=np.float).T # go back to coordinate of the first model _invA = np.linalg.inv(AList[0][0:3, 0:3]) invA = np.c_[_invA, -np.dot(_invA, AList[0][:, 3])] mergeSfM.transform_sfm_data(mergeSfmData, invA) mergeSfmData["root_path"] = os.path.join(output_dir, "Input", "inputImg") resultSfMDataFile = os.path.join(output_dir, "Output", "SfM", "reconstruction", "global", "sfm_data.json") with open(os.path.join(resultSfMDataFile), "w") as jsonfile: json.dump(mergeSfmData, jsonfile) if mergeSfmViewBeaconData is not None: mergeSfmViewBeaconDataMapList = [] for key in mergeSfmViewBeaconData: mergeSfmViewBeaconDataMap = {} mergeSfmViewBeaconDataMap[key] = mergeSfmViewBeaconData[key] mergeSfmViewBeaconDataMapList.append(mergeSfmViewBeaconDataMap) iBeaconUtils.exportBeaconData( len(mergeSfmData["views"]), sfmBeaconMap, mergeSfmViewBeaconDataMapList, os.path.join(os.path.dirname(resultSfMDataFile), "beacon.txt")) ''' os.system(reconstructParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) ''' Amat = AList[0] with open(os.path.join(output_dir, "Ref", "Amat.txt"), "w") as AmatFile: np.savetxt(AmatFile, Amat) FileUtils.convertNumpyMatTxt2OpenCvMatYml( os.path.join(output_dir, "Ref", "Amat.txt"), os.path.join(output_dir, "Ref", "Amat.yml"), "A") # To create same directory structure before merging, create sfm_data.json without structure information in matches directory with open(resultSfMDataFile) as fpr: sfmData = json.load(fpr) sfmData["extrinsics"] = [] sfmData["control_points"] = [] sfmData["structure"] = [] with open( os.path.join(output_dir, "Output", "matches", "sfm_data.json"), "w") as fpw: json.dump(sfmData, fpw) print "Execute : " + reconstructParam.WORKSPACE_DIR + "/TrainBoW/Release/TrainBoW " + os.path.join(output_dir,"Output") + " " + \ os.path.join(output_dir,"Output", "matches", "BOWfile.yml") + " -p=" + os.path.join(output_dir,"Output", "matches", "PCAfile.yml") os.system(reconstructParam.WORKSPACE_DIR + "/TrainBoW/Release/TrainBoW " + os.path.join(output_dir,"Output") + " " + \ os.path.join(output_dir,"Output", "matches", "BOWfile.yml") + " -p=" + os.path.join(output_dir,"Output", "matches", "PCAfile.yml")) os.system("openMVG_main_ComputeSfM_DataColor -i " + resultSfMDataFile + \ " -o " + os.path.join(output_dir,"Output","SfM","reconstruction","global","colorized.ply"))
def main(): description = 'This script is for merging multiple SfM output models to one SfM model.' + \ 'Please prepare multiple OpenMVG projects which have output SfM models, and matrix to convert to global coordinate.' parser = argparse.ArgumentParser(description=description) parser.add_argument('input_csv', action='store', nargs=None, const=None, \ default=None, type=str, choices=None, metavar=None, \ help='Input CSV file which lists OpenMVG projects which will be merged.') parser.add_argument('output_dir', action='store', nargs=None, const=None, \ default=None, type=str, choices=None, metavar=None, \ help='Output directory path where merged model will be saved.') args = parser.parse_args() input_csv = args.input_csv output_dir = args.output_dir # load reconstruct parameters reconstructParam = ReconstructParam.ReconstructParam # read projects list projectList = [] with open(input_csv, "r") as f: reader = csv.reader(f) for row in reader: project = {} project["dir"] = row[0] project["sfm_data"] = row[1] project["A"] = row[2] projectList.append(project) # copy source files to output directory for project in projectList: copyOriginalFiles(project["dir"], output_dir) # prepare output directory if not os.path.isdir(os.path.join(output_dir,"Ref")): FileUtils.makedir(os.path.join(output_dir,"Ref")) if not os.path.isdir(os.path.join(output_dir,"Ref","loc")): FileUtils.makedir(os.path.join(output_dir,"Ref","loc")) if not os.path.isdir(os.path.join(output_dir,"Output","SfM")): FileUtils.makedir(os.path.join(output_dir,"Output","SfM")) if not os.path.isdir(os.path.join(output_dir,"Output","SfM","reconstruction")): FileUtils.makedir(os.path.join(output_dir,"Output","SfM","reconstruction")) if not os.path.isdir(os.path.join(output_dir,"Output","SfM","reconstruction","global")): FileUtils.makedir(os.path.join(output_dir,"Output","SfM","reconstruction","global")) sfmDataList = [] sfmViewBeaconDataList = [] sfmBeaconMap = None for project in projectList: if not os.path.exists(project["sfm_data"]): print "cannot find sfm data : " + project["sfm_data"] sys.exit() with open(project["sfm_data"]) as jsonFile: sfmDataList.append(json.load(jsonFile)) sfmBeaconFile = os.path.join(os.path.dirname(project["sfm_data"]), "beacon.txt") if os.path.exists(sfmBeaconFile): print "find beacon.txt for sfm data : " + project["sfm_data"] imgBeaconList, beaconMap = iBeaconUtils.readBeaconData(sfmBeaconFile) sfmViewBeaconDataList.append(imgBeaconList) if sfmBeaconMap is None: sfmBeaconMap = beaconMap else: if sfmBeaconMap!=beaconMap: print "invalid find beacon.txt for sfm data : " + project["sfm_data"] print "beacon.txt should be same for all merged sfm_data" sys.exit() else: print "valid beacon.txt for sfm data : " + project["sfm_data"] AList = [] for project in projectList: AList.append(np.loadtxt(project["A"])) print "load mat : " + project["A"] print (np.loadtxt(project["A"])) print "Load 3D points" pointIdList = [] pointList = [] for sfmData in sfmDataList: pointId, point = mergeSfM.getAll3DPointloc(sfmData) pointn = np.asarray(point, dtype=np.float).T pointIdList.append(pointId) pointList.append(pointn) # merge models mergeSfmData = None mergePointId = None mergePointn = None mergeSfmViewBeaconData = None for idx in range(0, len(sfmDataList)): if idx==0: mergeSfmData = sfmDataList[0] mergeSfM.transform_sfm_data(mergeSfmData, AList[0]) if len(sfmViewBeaconDataList)>0: mergeSfmViewBeaconData = sfmViewBeaconDataList[0] else: mergePointThres = mergeSfM.findMedianStructurePointsThres(mergeSfmData, reconstructParam.mergePointThresMul) print "thres to merge 3D points : " + str(mergePointThres) inlierMap = findInliersByKnownTransform(mergePointId, pointIdList[idx], mergePointn, pointList[idx], AList[idx], mergePointThres) print "number of points in base model : " + str(len(mergePointn[0])) print "number of points in model " + str(idx) + " : " + str(len(pointList[idx])) print "number of inliers : " + str(len(inlierMap)) if len(sfmViewBeaconDataList)>0: mergeSfM.merge_sfm_data(mergeSfmData, sfmDataList[idx], AList[idx], {x[0]: x[1] for x in inlierMap}, mergeSfmViewBeaconData, sfmViewBeaconDataList[idx]) else: mergeSfM.merge_sfm_data(mergeSfmData, sfmDataList[idx], AList[idx], {x[0]: x[1] for x in inlierMap}) mergePointId, mergePoint = mergeSfM.getAll3DPointloc(mergeSfmData) mergePointn = np.asarray(mergePoint, dtype=np.float).T # go back to coordinate of the first model _invA = np.linalg.inv(AList[0][0:3,0:3]) invA = np.c_[_invA, -np.dot(_invA,AList[0][:,3])] mergeSfM.transform_sfm_data(mergeSfmData, invA) mergeSfmData["root_path"] = os.path.join(output_dir,"Input","inputImg") resultSfMDataFile = os.path.join(output_dir,"Output","SfM","reconstruction","global","sfm_data.json") with open(os.path.join(resultSfMDataFile),"w") as jsonfile: json.dump(mergeSfmData, jsonfile) if mergeSfmViewBeaconData is not None: mergeSfmViewBeaconDataMapList = [] for key in mergeSfmViewBeaconData: mergeSfmViewBeaconDataMap = {} mergeSfmViewBeaconDataMap[key] = mergeSfmViewBeaconData[key] mergeSfmViewBeaconDataMapList.append(mergeSfmViewBeaconDataMap) iBeaconUtils.exportBeaconData(len(mergeSfmData["views"]), sfmBeaconMap, mergeSfmViewBeaconDataMapList, os.path.join(os.path.dirname(resultSfMDataFile), "beacon.txt")) ''' os.system(reconstructParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) ''' os.system(reconstructParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile + \ " -c=" + "rst,rsti" + " -r=" + "1") Amat = AList[0] with open(os.path.join(output_dir,"Ref","Amat.txt"),"w") as AmatFile: np.savetxt(AmatFile,Amat) FileUtils.convertNumpyMatTxt2OpenCvMatYml(os.path.join(output_dir,"Ref","Amat.txt"), os.path.join(output_dir,"Ref","Amat.yml"), "A") # To create same directory structure before merging, create sfm_data.json without structure information in matches directory with open(resultSfMDataFile) as fpr: sfmData = json.load(fpr) sfmData["extrinsics"] = [] sfmData["control_points"] = [] sfmData["structure"] = [] with open(os.path.join(output_dir,"Output","matches","sfm_data.json"),"w") as fpw: json.dump(sfmData, fpw) print "Execute : " + reconstructParam.WORKSPACE_DIR + "/TrainBoW/Release/TrainBoW " + os.path.join(output_dir,"Output") + " " + \ os.path.join(output_dir,"Output", "matches", "BOWfile.yml") + " -p=" + os.path.join(output_dir,"Output", "matches", "PCAfile.yml") os.system(reconstructParam.WORKSPACE_DIR + "/TrainBoW/Release/TrainBoW " + os.path.join(output_dir,"Output") + " " + \ os.path.join(output_dir,"Output", "matches", "BOWfile.yml") + " -p=" + os.path.join(output_dir,"Output", "matches", "PCAfile.yml")) os.system("openMVG_main_ComputeSfM_DataColor -i " + resultSfMDataFile + \ " -o " + os.path.join(output_dir,"Output","SfM","reconstruction","global","colorized.ply"))