def mergeOneModel(self, model1, model2, reconParam, reconBOWParam): sfmOutPath = os.path.join(self.mSfMPath, "global" + str(self.nMergedModel)) # modified by T. IShihara 2016.06.14 # fix file name too long issue # # create a temporary folder for reconstructed image of model2 #inputImgTmpFolder = os.path.join(self.mSfMPath,"inputImgTmp","inputImgTmp"+model2.name) inputImgTmpFolder = os.path.join(self.mSfMPath, "inputImgTmp", "inputImgTmpModel2") if os.path.isdir(inputImgTmpFolder): FileUtils.removedir(inputImgTmpFolder) # copy reconstructed image fom model2 to tmp folder sfm_data2 = FileUtils.loadjson(model2.sfm_dataLoc) if not os.path.isdir(inputImgTmpFolder): listReconFrameName = [ sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"] ["filename"] for x in range(0, len(sfm_data2["views"])) if sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"] ["id_view"] in model2.reconFrame ] FileUtils.makedir(inputImgTmpFolder) for reconFrameName in listReconFrameName: os.system("cp -s " + os.path.join(model2.imgFolLoc, reconFrameName) + " " + inputImgTmpFolder) # remove all old localization result FileUtils.removedir(model2.locFolLoc) FileUtils.makedir(model2.locFolLoc) # localize the images from model2 on model1 guideMatchOption = "" if reconParam.bGuidedMatchingLocalize: guideMatchOption = " -gm" os.system(reconParam.LOCALIZE_PROJECT_PATH + \ " " + inputImgTmpFolder + \ " " + os.path.dirname(model1.sfm_dataLoc) + \ " " + self.mMatchesPath + \ " " + model2.locFolLoc + \ " -f=" + str(reconParam.locFeatDistRatio) + \ " -r=" + str(reconParam.locRansacRound) + \ " -i=" + str(reconParam.locSkipFrame) + \ " -k=" + str(reconBOWParam.locKNNnum) + \ " -a=" + os.path.join(self.mMatchesPath, "BOWfile.yml") + \ " -p=" + os.path.join(self.mMatchesPath, "PCAfile.yml") + \ guideMatchOption) # remove temporary image folder # removedir(inputImgTmpFolder) # extract centers from all json file and write to a file fileLoc = open(os.path.join(model2.locFolLoc, "center.txt"), "w") countLocFrame = 0 for filename in sorted(os.listdir(model2.locFolLoc)): if filename[-4:] != "json": continue countLocFrame = countLocFrame + 1 with open(os.path.join(model2.locFolLoc, filename)) as locJson: #print os.path.join(sfm_locOut,filename) locJsonDict = json.load(locJson) loc = locJsonDict["t"] fileLoc.write( str(loc[0]) + " " + str(loc[1]) + " " + str(loc[2]) + " 255 0 0\n") fileLoc.close() # get inlier matches FileUtils.makedir(sfmOutPath) resultSfMDataFile = os.path.join(sfmOutPath, "sfm_data.json") # below also checks if the ratio between first and last svd of M[0:3,0:3] # is good or not. If not then reject # TODO : revisit ransacRound parameter, use number of reconstruction frame to determine structure points transform seems small nMatchPointsTmp, nInlierTmp, M = mergeSfM.mergeModel( model1.sfm_dataLoc, model2.sfm_dataLoc, model2.locFolLoc, resultSfMDataFile, ransacThres=model1.ransacStructureThres, mergePointThres=model1.mergeStructureThres, ransacRoundMul=reconParam.ransacRoundMul, inputImgDir=self.mInputImgPath, minLimit=reconParam.min3DnInliers) ratioInlierMatchPoints = 0.0 if nMatchPointsTmp > 0: ratioInlierMatchPoints = float(nInlierTmp) / nMatchPointsTmp # 3. perform test whether merge is good sfm_merge_generated = True countFileAgree = 0 countFileLoc = 1 if os.path.isfile(resultSfMDataFile): os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) countFileLoc, countFileAgree = mergeSfM.modelMergeCheckLocal( resultSfMDataFile, model2.locFolLoc, model1.validMergeRansacThres) else: sfm_merge_generated = False ratioAgreeFrameReconFrame = 0.0 if (len(model2.reconFrame) > 0): ratioAgreeFrameReconFrame = float(countFileAgree) / len( model2.reconFrame) ratioAgreeFrameLocFrame = 0.0 if (countFileLoc > 0): ratioAgreeFrameLocFrame = float(countFileAgree) / countFileLoc # write log file with open( os.path.join(self.mSfMPath, "global" + str(self.nMergedModel), "log.txt"), "a") as filelog: filelog.write(("M1: " + model1.name + "\n" + \ "M2: " + model2.name + "\n" + \ "nMatchedPoints: " + str(nMatchPointsTmp) + "\n" + \ "nInliers: " + str(nInlierTmp) + "\n" + \ "ratioInlierWithMatchedPoints: " + str(ratioInlierMatchPoints) + "\n" + \ "countLocFrame: " + str(countLocFrame) + "\n" + \ "nReconFrame M2: " + str(len(model2.reconFrame)) + "\n" + \ "countFileAgree: " + str(countFileAgree) + "\n" + \ "countFileLoc: " + str(countFileLoc) + "\n" + \ "not sfm_merge_generated: " + str(not sfm_merge_generated) + "\n" + \ # obsolete condition by T. Ishihara 2015.11.10 #"nInlierTmp > "+str(reconParam.vldMergeRatioInliersFileagree)+"*countFileAgree: " + str(nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree) + "\n" + \ "countFileAgree > "+str(reconParam.vldMergeMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileAgree > "+str(reconParam.vldMergeSmallMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeSmallMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileLoc < countFileAgree*" +str(reconParam.vldMergeShortRatio)+ ": " + str(countFileLoc < countFileAgree*reconParam.vldMergeShortRatio) + "\n" + \ "ratioLocAgreeWithReconFrame: " + str(ratioAgreeFrameReconFrame) + "\n" + \ "ratioLocAgreeWithReconFrame > " + str(reconParam.vldMergeRatioAgrFReconF) + ": " + str(ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) + "\n" + \ "ratioLocAgreeWithLocFrame: " + str(ratioAgreeFrameLocFrame) + "\n" + \ "ratioLocAgreeWithLocFrame > " + str(reconParam.vldMergeRatioAgrFLocF) + ": " + str(ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF) + "\n" + \ str(M) + "\n\n")) # rename the localization folder to save localization result ''' if os.path.isdir(model2.locFolLoc+model1.name): FileUtils.removedir(model2.locFolLoc+model1.name) os.rename(model2.locFolLoc,model2.locFolLoc+model1.name) ''' # obsolete merge condition ''' if not sfm_merge_generated or \ not (nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree and \ ((countFileAgree > reconParam.vldMergeMinCountFileAgree or (countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and countFileLoc < countFileAgree*reconParam.vldMergeShortRatio)) and \ ((nInlierTmp > reconParam.vldMergeNInliers and float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconFNInliers) or float(countFileAgree)/countFileLoc > reconParam.vldMergeRatioAgrFLocF) and (float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconF))): ''' # update merge condition by T. Ishihara 2015.11.10 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and \ countFileLoc < countFileAgree*reconParam.vldMergeShortRatio and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.04.02 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.06.09 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF and \ nInlierTmp > reconParam.min3DnInliers and \ ratioInlierMatchPoints > reconParam.vldMergeRatioInliersMatchPoints): ''' # update merge condition by T. Ishihara 2016.06.20 if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF and \ nInlierTmp > reconParam.min3DnInliers): print "Transformed locations do not agree with localization. Skip merge between " + model1.name + " and " + model2.name + "." ''' if os.path.isfile(os.path.join(sfmOutPath,"sfm_data.json")): os.rename(os.path.join(sfmOutPath,"sfm_data.json"), \ os.path.join(sfmOutPath,"sfm_data_("+model1.name + "," + model2.name+").json")) ''' if os.path.isfile(os.path.join(sfmOutPath, "sfm_data.json")): os.rename(os.path.join(sfmOutPath,"sfm_data.json"), \ os.path.join(sfmOutPath,"sfm_data_fail_merge.json")) # move to next video return False, sfmModelBOW("", "", "", "", "", "", validMergeRansacThres=0, validMergeRansacThresK=0, ransacStructureThres=0, ransacStructureThresK=0, mergeStructureThres=0, mergeStructureThresK=0) # generate colorized before bundle adjustment for comparison os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath, "sfm_data.json") + " -o " + os.path.join(sfmOutPath, "colorized_pre.ply")) # TODO : try computing structure from know pose here # https://github.com/openMVG/openMVG/issues/246 # http://openmvg.readthedocs.io/en/latest/software/SfM/ComputeStructureFromKnownPoses/ # TODO : revisit the order of bundle adjustment # perform bundle adjustment ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rs,rst,rsti" + " -r=" + "1") ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rst,rsti" + " -r=" + "1") os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath, "sfm_data.json") + " -o " + os.path.join(sfmOutPath, "colorized.ply")) return True, sfmModelBOW( "A" + model1.name + "," + model2.name + "Z", self.mInputImgPath, self.mCsvPath, self.mMatchesPath, os.path.join(sfmOutPath, "loc"), resultSfMDataFile, validMergeRansacThres=model1.validMergeRansacThres, ransacStructureThres=model1.ransacStructureThres, mergeStructureThres=model1.mergeStructureThres)
def mergeOneModel(self, model1, model2, reconParam): sfmOutPath = os.path.join(self.mSfMPath,"global"+str(self.nMergedModel)) # create a temporary folder for reconstructed image of model2 inputImgTmpFolder = os.path.join(self.mSfMPath,"inputImgTmp","inputImgTmp"+model2.name) # copy reconstructed image fom model2 to tmp folder sfm_data2 = FileUtils.loadjson(model2.sfm_dataLoc) if not os.path.isdir(inputImgTmpFolder): listReconFrameName = [sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"]["filename"] for x in range(0,len(sfm_data2["views"])) if sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"]["id_view"] in model2.reconFrame] FileUtils.makedir(inputImgTmpFolder) for reconFrameName in listReconFrameName: os.system("cp -s " + os.path.join(model2.imgFolLoc,reconFrameName) + " " + inputImgTmpFolder) # remove all old localization result FileUtils.removedir(model2.locFolLoc) FileUtils.makedir(model2.locFolLoc) # localize the images from model2 on model1 os.system(reconParam.LOCALIZE_PROJECT_PATH + \ " " + inputImgTmpFolder + \ " " + os.path.dirname(model1.sfm_dataLoc) + \ " " + self.mMatchesPath + \ " " + model2.locFolLoc + \ " -f=" + str(reconParam.locFeatDistRatio) + \ " -r=" + str(reconParam.locRansacRound) + \ " -e=" + model2.csvFolLoc + \ " -i=" + str(reconParam.locSkipFrame)) # remove temporary image folder # removedir(inputImgTmpFolder) # extract centers from all json file and write to a file fileLoc = open(os.path.join(model2.locFolLoc,"center.txt"),"w") countLocFrame = 0 for filename in sorted(os.listdir(model2.locFolLoc)): if filename[-4:]!="json": continue countLocFrame = countLocFrame + 1 with open(os.path.join(model2.locFolLoc,filename)) as locJson: #print os.path.join(sfm_locOut,filename) locJsonDict = json.load(locJson) loc = locJsonDict["t"] fileLoc.write(str(loc[0]) + " " + str(loc[1]) + " " +str(loc[2]) + " 255 0 0\n" ) fileLoc.close() # get inlier matches FileUtils.makedir(sfmOutPath) resultSfMDataFile = os.path.join(sfmOutPath,"sfm_data.json") # below also checks if the ratio between first and last svd of M[0:3,0:3] # is good or not. If not then reject nInlierTmp, M = mergeSfM.mergeModel(model1.sfm_dataLoc, model2.sfm_dataLoc, model2.locFolLoc, resultSfMDataFile, ransacK=reconParam.ransacStructureThresMul, ransacRound=reconParam.ransacRoundMul*len(model1.reconFrame), inputImgDir=self.mInputImgPath, minLimit=reconParam.min3DnInliers) # 3. perform test whether merge is good sfm_merge_generated = True countFileAgree = 0 countFileLoc = 1 if os.path.isfile(resultSfMDataFile): os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) countFileLoc, countFileAgree = mergeSfM.modelMergeCheckLocal(resultSfMDataFile, model2.locFolLoc, reconParam.vldMergeAgrFrameThresK) else: sfm_merge_generated = False ratioAgreeFrameReconFrame = 0.0 if (len(model2.reconFrame)>0): ratioAgreeFrameReconFrame = float(countFileAgree)/len(model2.reconFrame) ratioAgreeFrameLocFrame = 0.0 if (countFileLoc>0): ratioAgreeFrameLocFrame = float(countFileAgree)/countFileLoc # write log file with open(os.path.join(self.mSfMPath,"global"+str(self.nMergedModel),"log.txt"),"a") as filelog: filelog.write(("M1: " + model1.name + "\n" + \ "M2: " + model2.name + "\n" + \ "nInliers: " + str(nInlierTmp) + "\n" + \ "countLocFrame: " + str(countLocFrame) + "\n" + \ "nReconFrame M2: " + str(len(model2.reconFrame)) + "\n" + \ "countFileAgree: " + str(countFileAgree) + "\n" + \ "countFileLoc: " + str(countFileLoc) + "\n" + \ "not sfm_merge_generated: " + str(not sfm_merge_generated) + "\n" + \ # obsolete condition by T. Ishihara 2015.11.10 #"nInlierTmp > "+str(reconParam.vldMergeRatioInliersFileagree)+"*countFileAgree: " + str(nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree) + "\n" + \ "countFileAgree > "+str(reconParam.vldMergeMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileAgree > "+str(reconParam.vldMergeSmallMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeSmallMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileLoc < countFileAgree*" +str(reconParam.vldMergeShortRatio)+ ": " + str(countFileLoc < countFileAgree*reconParam.vldMergeShortRatio) + "\n" + \ "ratioLocAgreeWithReconFrame: " + str(ratioAgreeFrameReconFrame) + "\n" + \ "ratioLocAgreeWithReconFrame > " + str(reconParam.vldMergeRatioAgrFReconF) + ": " + str(ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) + "\n" + \ "ratioLocAgreeWithLocFrame: " + str(ratioAgreeFrameLocFrame) + "\n" + \ "ratioLocAgreeWithLocFrame > " + str(reconParam.vldMergeRatioAgrFLocF) + ": " + str(ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF) + "\n" + \ str(M) + "\n\n")) # rename the localization folder to save localization result if os.path.isdir(model2.locFolLoc+model1.name): FileUtils.removedir(model2.locFolLoc+model1.name) os.rename(model2.locFolLoc,model2.locFolLoc+model1.name) # obsolete merge condition ''' if not sfm_merge_generated or \ not (nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree and \ ((countFileAgree > reconParam.vldMergeMinCountFileAgree or (countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and countFileLoc < countFileAgree*reconParam.vldMergeShortRatio)) and \ ((nInlierTmp > reconParam.vldMergeNInliers and float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconFNInliers) or float(countFileAgree)/countFileLoc > reconParam.vldMergeRatioAgrFLocF) and (float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconF))): ''' # update merge condition by T. Ishihara 2015.11.10 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and \ countFileLoc < countFileAgree*reconParam.vldMergeShortRatio and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.04.02 if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): print "Transformed locations do not agree with localization. Skip merge between " + model1.name + " and " + model2.name + "." if os.path.isfile(os.path.join(sfmOutPath,"sfm_data.json")): os.rename(os.path.join(sfmOutPath,"sfm_data.json"), \ os.path.join(sfmOutPath,"sfm_data_("+model1.name + "," + model2.name+").json")) # move to next video return False, sfmModel("","","","","","") # generate colorized before bundle adjustment for comparison os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath,"sfm_data.json") + " -o " + os.path.join(sfmOutPath,"colorized_pre.ply")) # perform bundle adjustment # modified by T.Ishihara 2016.04.08 # fix only translation at first ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rs,rst,rsti" + " -r=" + "1") ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "st,rst,rsti" + " -r=" + "1") os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath,"sfm_data.json") + " -o " + os.path.join(sfmOutPath,"colorized.ply")) return True, sfmModel("A" + model1.name + "," + model2.name +"Z", self.mInputImgPath, self.mCsvPath, self.mMatchesPath, os.path.join(sfmOutPath,"loc"), resultSfMDataFile)
def mergeOneModel(self, model1, model2, reconParam, reconIBeaconParam, reconBOWParam): sfmOutPath = os.path.join(self.mSfMPath,"global"+str(self.nMergedModel)) # modified by T. IShihara 2016.06.14 # fix file name too long issue # # create a temporary folder for reconstructed image of model2 #inputImgTmpFolder = os.path.join(self.mSfMPath,"inputImgTmp","inputImgTmp"+model2.name) inputImgTmpFolder = os.path.join(self.mSfMPath,"inputImgTmp","inputImgTmpModel2") if os.path.isdir(inputImgTmpFolder): FileUtils.removedir(inputImgTmpFolder) # copy reconstructed image fom model2 to tmp folder sfm_data2 = FileUtils.loadjson(model2.sfm_dataLoc) if not os.path.isdir(inputImgTmpFolder): listReconFrameName = [sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"]["filename"] for x in range(0,len(sfm_data2["views"])) if sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"]["id_view"] in model2.reconFrame] FileUtils.makedir(inputImgTmpFolder) for reconFrameName in listReconFrameName: os.system("cp -s " + os.path.join(model2.imgFolLoc,reconFrameName) + " " + inputImgTmpFolder) # remove all old localization result FileUtils.removedir(model2.locFolLoc) FileUtils.makedir(model2.locFolLoc) # localize the images from model2 on model1 if self.useBow: os.system(reconIBeaconParam.LOCALIZE_PROJECT_PATH + \ " " + inputImgTmpFolder + \ " " + os.path.dirname(model1.sfm_dataLoc) + \ " " + self.mMatchesPath + \ " " + model2.locFolLoc + \ " -f=" + str(reconParam.locFeatDistRatio) + \ " -r=" + str(reconParam.locRansacRound) + \ " -b=" + model1.beaconFileLoc + \ " -e=" + model2.csvFolLoc + \ " -k=" + str(reconIBeaconParam.locKNNnum) + \ " -c=" + str(reconIBeaconParam.coocThres) + \ " -i=" + str(reconParam.locSkipFrame) + \ " -v=" + str(reconIBeaconParam.locSkipSelKNN) + \ " -n=" + str(reconIBeaconParam.normApproach) + \ " -kb=" + str(reconBOWParam.locKNNnum) + \ " -a=" + os.path.join(self.mMatchesPath, "BOWfile.yml") + \ " -p=" + os.path.join(self.mMatchesPath, "PCAfile.yml")) else: os.system(reconIBeaconParam.LOCALIZE_PROJECT_PATH + \ " " + inputImgTmpFolder + \ " " + os.path.dirname(model1.sfm_dataLoc) + \ " " + self.mMatchesPath + \ " " + model2.locFolLoc + \ " -f=" + str(reconParam.locFeatDistRatio) + \ " -r=" + str(reconParam.locRansacRound) + \ " -b=" + model1.beaconFileLoc + \ " -e=" + model2.csvFolLoc + \ " -k=" + str(reconIBeaconParam.locKNNnum) + \ " -c=" + str(reconIBeaconParam.coocThres) + \ " -i=" + str(reconParam.locSkipFrame) + \ " -v=" + str(reconIBeaconParam.locSkipSelKNN) + \ " -n=" + str(reconIBeaconParam.normApproach)) # remove temporary image folder # removedir(inputImgTmpFolder) # extract centers from all json file and write to a file fileLoc = open(os.path.join(model2.locFolLoc,"center.txt"),"w") countLocFrame = 0 for filename in sorted(os.listdir(model2.locFolLoc)): if filename[-4:]!="json": continue countLocFrame = countLocFrame + 1 with open(os.path.join(model2.locFolLoc,filename)) as locJson: #print os.path.join(sfm_locOut,filename) locJsonDict = json.load(locJson) loc = locJsonDict["t"] fileLoc.write(str(loc[0]) + " " + str(loc[1]) + " " +str(loc[2]) + " 255 0 0\n" ) fileLoc.close() # get inlier matches FileUtils.makedir(sfmOutPath) resultSfMDataFile = os.path.join(sfmOutPath,"sfm_data.json") # below also checks if the ratio between first and last svd of M[0:3,0:3] # is good or not. If not then reject # TODO : revisit ransacRound parameter, use number of reconstruction frame to determine structure points transform seems small nMatchPointsTmp, nInlierTmp, M = mergeSfM.mergeModel(model1.sfm_dataLoc, model2.sfm_dataLoc, model2.locFolLoc, resultSfMDataFile, ransacThres=model1.ransacStructureThres, mergePointThres=model1.mergeStructureThres, ransacRoundMul=reconParam.ransacRoundMul, inputImgDir=self.mInputImgPath, minLimit=reconParam.min3DnInliers) ratioInlierMatchPoints = 0.0 if nMatchPointsTmp>0: ratioInlierMatchPoints = float(nInlierTmp)/nMatchPointsTmp # 3. perform test whether merge is good sfm_merge_generated = True countFileAgree = 0 countFileLoc = 1 if os.path.isfile(resultSfMDataFile): os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) countFileLoc, countFileAgree = mergeSfM.modelMergeCheckLocal(resultSfMDataFile, model2.locFolLoc, model1.validMergeRansacThres) else: sfm_merge_generated = False ratioAgreeFrameReconFrame = 0.0 if (len(model2.reconFrame)>0): ratioAgreeFrameReconFrame = float(countFileAgree)/len(model2.reconFrame) ratioAgreeFrameLocFrame = 0.0 if (countFileLoc>0): ratioAgreeFrameLocFrame = float(countFileAgree)/countFileLoc # write log file with open(os.path.join(self.mSfMPath,"global"+str(self.nMergedModel),"log.txt"),"a") as filelog: filelog.write(("M1: " + model1.name + "\n" + \ "M2: " + model2.name + "\n" + \ "nMatchedPoints: " + str(nMatchPointsTmp) + "\n" + \ "nInliers: " + str(nInlierTmp) + "\n" + \ "ratioInlierWithMatchedPoints: " + str(ratioInlierMatchPoints) + "\n" + \ "countLocFrame: " + str(countLocFrame) + "\n" + \ "nReconFrame M2: " + str(len(model2.reconFrame)) + "\n" + \ "countFileAgree: " + str(countFileAgree) + "\n" + \ "countFileLoc: " + str(countFileLoc) + "\n" + \ "not sfm_merge_generated: " + str(not sfm_merge_generated) + "\n" + \ # obsolete condition by T. Ishihara 2015.11.10 #"nInlierTmp > "+str(reconParam.vldMergeRatioInliersFileagree)+"*countFileAgree: " + str(nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree) + "\n" + \ "countFileAgree > "+str(reconParam.vldMergeMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileAgree > "+str(reconParam.vldMergeSmallMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeSmallMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileLoc < countFileAgree*" +str(reconParam.vldMergeShortRatio)+ ": " + str(countFileLoc < countFileAgree*reconParam.vldMergeShortRatio) + "\n" + \ "ratioLocAgreeWithReconFrame: " + str(ratioAgreeFrameReconFrame) + "\n" + \ "ratioLocAgreeWithReconFrame > " + str(reconParam.vldMergeRatioAgrFReconF) + ": " + str(ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) + "\n" + \ "ratioLocAgreeWithLocFrame: " + str(ratioAgreeFrameLocFrame) + "\n" + \ "ratioLocAgreeWithLocFrame > " + str(reconParam.vldMergeRatioAgrFLocF) + ": " + str(ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF) + "\n" + \ str(M) + "\n\n")) # rename the localization folder to save localization result ''' if os.path.isdir(model2.locFolLoc+model1.name): FileUtils.removedir(model2.locFolLoc+model1.name) os.rename(model2.locFolLoc,model2.locFolLoc+model1.name) ''' # obsolete merge condition ''' if not sfm_merge_generated or \ not (nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree and \ ((countFileAgree > reconParam.vldMergeMinCountFileAgree or (countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and countFileLoc < countFileAgree*reconParam.vldMergeShortRatio)) and \ ((nInlierTmp > reconParam.vldMergeNInliers and float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconFNInliers) or float(countFileAgree)/countFileLoc > reconParam.vldMergeRatioAgrFLocF) and (float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconF))): ''' # update merge condition by T. Ishihara 2015.11.10 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and \ countFileLoc < countFileAgree*reconParam.vldMergeShortRatio and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.04.02 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.06.09 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF and \ nInlierTmp > reconParam.min3DnInliers and \ ratioInlierMatchPoints > reconParam.vldMergeRatioInliersMatchPoints): ''' # update merge condition by T. Ishihara 2016.06.20 if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF and \ nInlierTmp > reconParam.min3DnInliers): print "Transformed locations do not agree with localization. Skip merge between " + model1.name + " and " + model2.name + "." ''' if os.path.isfile(os.path.join(sfmOutPath,"sfm_data.json")): os.rename(os.path.join(sfmOutPath,"sfm_data.json"), \ os.path.join(sfmOutPath,"sfm_data_("+model1.name + "," + model2.name+").json")) ''' # move to next video return False, sfmModelIBeacon("","","","","","","",validMergeRansacThres=0,validMergeRansacThresK=0, ransacStructureThres=0, ransacStructureThresK=0, mergeStructureThres=0, mergeStructureThresK=0) # generate colorized before bundle adjustment for comparison os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath,"sfm_data.json") + " -o " + os.path.join(sfmOutPath,"colorized_pre.ply")) # TODO : try computing structure from know pose here # https://github.com/openMVG/openMVG/issues/246 # http://openmvg.readthedocs.io/en/latest/software/SfM/ComputeStructureFromKnownPoses/ # TODO : revisit the order of bundle adjustment # perform bundle adjustment ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rs,rst,rsti" + " -r=" + "1") ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rst,rsti" + " -r=" + "1") os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath,"sfm_data.json") + " -o " + os.path.join(sfmOutPath,"colorized.ply")) # write new beacon file IBeaconUtils.exportBeaconDataForSfmImageFrames(self.mCsvPath, resultSfMDataFile, os.path.join(self.mInputPath,"listbeacon.txt"), os.path.join(sfmOutPath,"beacon.txt"), reconIBeaconParam.normApproach) return True, sfmModelIBeacon("A" + model1.name + "," + model2.name +"Z", self.mInputImgPath, self.mCsvPath, os.path.join(sfmOutPath,"beacon.txt"), self.mMatchesPath, os.path.join(sfmOutPath,"loc"), resultSfMDataFile, validMergeRansacThres=model1.validMergeRansacThres, ransacStructureThres=model1.ransacStructureThres, mergeStructureThres=model1.mergeStructureThres)
def mergeOneModel(self, model1, model2, reconParam): sfmOutPath = os.path.join(self.mSfMPath, "global" + str(self.nMergedModel)) # create a temporary folder for reconstructed image of model2 inputImgTmpFolder = os.path.join(self.mSfMPath, "inputImgTmp", "inputImgTmp" + model2.name) # copy reconstructed image fom model2 to tmp folder sfm_data2 = FileUtils.loadjson(model2.sfm_dataLoc) if not os.path.isdir(inputImgTmpFolder): listReconFrameName = [ sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"] ["filename"] for x in range(0, len(sfm_data2["views"])) if sfm_data2["views"][x]["value"]["ptr_wrapper"]["data"] ["id_view"] in model2.reconFrame ] FileUtils.makedir(inputImgTmpFolder) for reconFrameName in listReconFrameName: os.system("cp -s " + os.path.join(model2.imgFolLoc, reconFrameName) + " " + inputImgTmpFolder) # remove all old localization result FileUtils.removedir(model2.locFolLoc) FileUtils.makedir(model2.locFolLoc) # localize the images from model2 on model1 os.system(reconParam.LOCALIZE_PROJECT_PATH + \ " " + inputImgTmpFolder + \ " " + os.path.dirname(model1.sfm_dataLoc) + \ " " + self.mMatchesPath + \ " " + model2.locFolLoc + \ " -f=" + str(reconParam.locFeatDistRatio) + \ " -r=" + str(reconParam.locRansacRound) + \ " -e=" + model2.csvFolLoc + \ " -i=" + str(reconParam.locSkipFrame)) # remove temporary image folder # removedir(inputImgTmpFolder) # extract centers from all json file and write to a file fileLoc = open(os.path.join(model2.locFolLoc, "center.txt"), "w") countLocFrame = 0 for filename in sorted(os.listdir(model2.locFolLoc)): if filename[-4:] != "json": continue countLocFrame = countLocFrame + 1 with open(os.path.join(model2.locFolLoc, filename)) as locJson: #print os.path.join(sfm_locOut,filename) locJsonDict = json.load(locJson) loc = locJsonDict["t"] fileLoc.write( str(loc[0]) + " " + str(loc[1]) + " " + str(loc[2]) + " 255 0 0\n") fileLoc.close() # get inlier matches FileUtils.makedir(sfmOutPath) resultSfMDataFile = os.path.join(sfmOutPath, "sfm_data.json") # below also checks if the ratio between first and last svd of M[0:3,0:3] # is good or not. If not then reject nInlierTmp, M = mergeSfM.mergeModel( model1.sfm_dataLoc, model2.sfm_dataLoc, model2.locFolLoc, resultSfMDataFile, ransacK=reconParam.ransacStructureThresMul, ransacRound=reconParam.ransacRoundMul * len(model1.reconFrame), inputImgDir=self.mInputImgPath, minLimit=reconParam.min3DnInliers) # 3. perform test whether merge is good sfm_merge_generated = True countFileAgree = 0 countFileLoc = 1 if os.path.isfile(resultSfMDataFile): os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + resultSfMDataFile + " " + resultSfMDataFile) countFileLoc, countFileAgree = mergeSfM.modelMergeCheckLocal( resultSfMDataFile, model2.locFolLoc, reconParam.vldMergeAgrFrameThresK) else: sfm_merge_generated = False ratioAgreeFrameReconFrame = 0.0 if (len(model2.reconFrame) > 0): ratioAgreeFrameReconFrame = float(countFileAgree) / len( model2.reconFrame) ratioAgreeFrameLocFrame = 0.0 if (countFileLoc > 0): ratioAgreeFrameLocFrame = float(countFileAgree) / countFileLoc # write log file with open( os.path.join(self.mSfMPath, "global" + str(self.nMergedModel), "log.txt"), "a") as filelog: filelog.write(("M1: " + model1.name + "\n" + \ "M2: " + model2.name + "\n" + \ "nInliers: " + str(nInlierTmp) + "\n" + \ "countLocFrame: " + str(countLocFrame) + "\n" + \ "nReconFrame M2: " + str(len(model2.reconFrame)) + "\n" + \ "countFileAgree: " + str(countFileAgree) + "\n" + \ "countFileLoc: " + str(countFileLoc) + "\n" + \ "not sfm_merge_generated: " + str(not sfm_merge_generated) + "\n" + \ # obsolete condition by T. Ishihara 2015.11.10 #"nInlierTmp > "+str(reconParam.vldMergeRatioInliersFileagree)+"*countFileAgree: " + str(nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree) + "\n" + \ "countFileAgree > "+str(reconParam.vldMergeMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileAgree > "+str(reconParam.vldMergeSmallMinCountFileAgree)+": " + str(countFileAgree > reconParam.vldMergeSmallMinCountFileAgree) + "\n" + \ # obsolete condition by T. Ishihara 2016.04.02 #"countFileLoc < countFileAgree*" +str(reconParam.vldMergeShortRatio)+ ": " + str(countFileLoc < countFileAgree*reconParam.vldMergeShortRatio) + "\n" + \ "ratioLocAgreeWithReconFrame: " + str(ratioAgreeFrameReconFrame) + "\n" + \ "ratioLocAgreeWithReconFrame > " + str(reconParam.vldMergeRatioAgrFReconF) + ": " + str(ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) + "\n" + \ "ratioLocAgreeWithLocFrame: " + str(ratioAgreeFrameLocFrame) + "\n" + \ "ratioLocAgreeWithLocFrame > " + str(reconParam.vldMergeRatioAgrFLocF) + ": " + str(ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF) + "\n" + \ str(M) + "\n\n")) # rename the localization folder to save localization result if os.path.isdir(model2.locFolLoc + model1.name): FileUtils.removedir(model2.locFolLoc + model1.name) os.rename(model2.locFolLoc, model2.locFolLoc + model1.name) # obsolete merge condition ''' if not sfm_merge_generated or \ not (nInlierTmp > reconParam.vldMergeRatioInliersFileagree*countFileAgree and \ ((countFileAgree > reconParam.vldMergeMinCountFileAgree or (countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and countFileLoc < countFileAgree*reconParam.vldMergeShortRatio)) and \ ((nInlierTmp > reconParam.vldMergeNInliers and float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconFNInliers) or float(countFileAgree)/countFileLoc > reconParam.vldMergeRatioAgrFLocF) and (float(countFileAgree)/len(model2.reconFrame) > reconParam.vldMergeRatioAgrFReconF))): ''' # update merge condition by T. Ishihara 2015.11.10 ''' if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ countFileAgree > reconParam.vldMergeSmallMinCountFileAgree and \ countFileLoc < countFileAgree*reconParam.vldMergeShortRatio and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): ''' # update merge condition by T. Ishihara 2016.04.02 if not sfm_merge_generated or \ not (countFileAgree > reconParam.vldMergeMinCountFileAgree and \ ((nInlierTmp > reconParam.vldMergeNInliers and ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconFNInliers) or \ ratioAgreeFrameReconFrame > reconParam.vldMergeRatioAgrFReconF) and \ ratioAgreeFrameLocFrame > reconParam.vldMergeRatioAgrFLocF): print "Transformed locations do not agree with localization. Skip merge between " + model1.name + " and " + model2.name + "." if os.path.isfile(os.path.join(sfmOutPath, "sfm_data.json")): os.rename(os.path.join(sfmOutPath,"sfm_data.json"), \ os.path.join(sfmOutPath,"sfm_data_("+model1.name + "," + model2.name+").json")) # move to next video return False, sfmModel("", "", "", "", "", "") # generate colorized before bundle adjustment for comparison os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath, "sfm_data.json") + " -o " + os.path.join(sfmOutPath, "colorized_pre.ply")) # perform bundle adjustment # modified by T.Ishihara 2016.04.08 # fix only translation at first ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "rs,rst,rsti" + " -r=" + "1") ''' os.system(reconParam.BUNDLE_ADJUSTMENT_PROJECT_PATH + " " + os.path.join(sfmOutPath,"sfm_data.json") + " " + os.path.join(sfmOutPath,"sfm_data.json") + \ " -c=" + "st,rst,rsti" + " -r=" + "1") os.system("openMVG_main_ComputeSfM_DataColor " + " -i " + os.path.join(sfmOutPath, "sfm_data.json") + " -o " + os.path.join(sfmOutPath, "colorized.ply")) return True, sfmModel("A" + model1.name + "," + model2.name + "Z", self.mInputImgPath, self.mCsvPath, self.mMatchesPath, os.path.join(sfmOutPath, "loc"), resultSfMDataFile)