def matchPairs(self, KNN=True, filter=True): ''' this function will create a matrix self.kpMatrix like the following: [a, b, none, c, none] [d, e, f, g, none] [h, none, j, k, l] [none, none, m, o, p] if these matches exist: image1:a - image2:d image2:d - image3:h image1:b - image2:e ... where a,b,c... are pixel coordinates ''' for i in range(len(self.imageList)-1): if KNN: if filter: points1, points2, matches = CVFuncs.findMatchesKnn(self.imageList[i], self.imageList[i+1],filter=True, ratio=True) else: points1, points2, matches = CVFuncs.findMatchesKnn(self.imageList[i], self.imageList[i+1],filter=False, ratio=True) else: if filter: points1, points2, matches = CVFuncs.findMatches(self.imageList[i], self.imageList[i+1],filter=True) else: points1, points2, matches = CVFuncs.findMatches(self.imageList[i], self.imageList[i+1],filter=False) # for each match... for match in matches: point1 = match.queryIdx #self.imageList[i].kps[match.queryIdx] # find out if the self.imageList[i] point was matched to already # if the point has been matched already, add its corresponding point in self.imageList[i+1] to the matrix at the same index if self.kpMatrix[i].count(point1): idx = self.kpMatrix[i].index(point1) self.kpMatrix[i+1][idx] = match.trainIdx#self.imageList[i+1].kps[match.trainIdx] else: # otherwise, at a new entry to every image's row in the matrix for j in range(len(self.imageList)): #if it's not image i or i+1, then make it empty if j not in [i,i+1]: self.kpMatrix[j].append(None) #otherwise, add the appropriate points elif j == i: self.kpMatrix[i].append(match.queryIdx) #self.imageList[i].kps[match.queryIdx]) else: #j == i+1 self.kpMatrix[i+1].append(match.trainIdx) #self.imageList[i+1].kps[match.trainIdx])
def triangulateWithImagesAndPointFile(filename1, filename2, pointFile, projections_file=None): ''' Read images and detect features ''' current_dir = os.path.dirname(os.path.realpath(__file__)) img1 = Image(os.path.join(current_dir, filename1)) # img1.detect_features() img2 = Image(os.path.join(current_dir, filename2)) # img2.detect_features() # Match keypoints # pts1, pts2, matches = CVFuncs.findMatches(img1, img2, filter=True) pts1, pts2, matches = readPointsFromFile(pointFile) # CREATE KEYPOINTS kp1, kp2 = [], [] for point1, point2 in zip(pts1, pts2): kp1.append(cv2.KeyPoint(point1[0], point1[1], 1)) kp2.append(cv2.KeyPoint(point2[0], point2[1], 1)) img1.kps = kp1 img2.kps = kp2 # CVFuncs.drawMatches(img1, img2, matches, "new.png") # print pts1 # print pts2 ''' Find K ''' K = img1.K ''' Get essential or fundamental matrix ''' # F, mask = CVFuncs.findFundamentalMat(pts1, pts2) # test.testFundamentalMat(F, pts1, pts2) E, mask = CVFuncs.findEssentialMat(pts1, pts2, K) # E = CVFuncs.EFromF(F, K) # test.testEssentialMat(E, K, pts1, pts2) ''' Get R and T (using artificial ones for now) ''' points, r, t, newMask = CVFuncs.recoverPose(E, pts1, pts2, K) ''' Draw image projections using R and T ''' if projections_file: draw.drawProjections(pts1, pts2, K.matrix, r, t, projections_file) # draw.drawProjections(pts1, pts2, K.matrix, r, t, "manualprojections.ply") # draw.drawRandTTransformation(pts1, pts2, K.matrix, r, t, "projections.ply") ''' Triangulate and draw points ''' triangulated = CVFuncs.naiveTriangulate(pts1, pts2, K.matrix, r, t) triangulated = draw.transformPointsToViewingCoordinates(triangulated) return triangulated, r, t
def triangulateImages(self, scene_file=None, projections_file=None, silent=False): ''' Triangulates all image matches and outputs triangulates and projections ''' self.matchPairs(KNN=True, filter=True) lastIdxCorrespondences = [] # find corresponding lists of matched image coordinates in images i and i+1 # also find what indices those coordinates have in their image's keypoint list # recover the pose between those two cameras for i in range(len(self.imageList)-1): if not silent: print "Triangulating " + self.imageList[i].fname + " and " + self.imageList[i+1].fname + "..." points1, points2 = self.getPointCorrespondences(i, i+1) indices1, indices2 = self.getIndexCorrespondences(i, i+1) K = self.imageList[i].K E, mask = CVFuncs.findEssentialMat(points1, points2, K) pts, r, t, newMask = CVFuncs.recoverPose(E, points1, points2, K) if i == 0: # if it's the first image pair, then there's no reprojection error to minimize. Keep these triangulated points self.triangulatedPoints[i].extend(CVFuncs.discreteTriangulate(points1, points2, K.matrix, r, t)) self.RTList.append([r,t]) if projections_file: self.projectedPoints[i].extend(draw.getProjections(points1, points2, K.matrix, r, t)) else: # find a list of (a,b) tuples, overlap, where: # a is the index in self.triangulatedPoints[i-1] of a triangulated point between image i-1 and i # make corresponding lists of triangulated points where oldPoints[j] and newPoints[j] both come from the same feature in image i # find the r and t that minimize reprojection error, and save all the new triangulations in self.triangulatedPoints[i] lastR = self.RTList[i-1][0] lastT = self.RTList[i-1][1] overlap = getOverlapIndices(lastIdxCorrespondences, indices1) oldTriangulatedPoints = [] newImagePoints1, newImagePoints2 = [], [] for pair in overlap: oldTriangulatedPoints.append(self.triangulatedPoints[i-1][pair[0]]) newImagePoints1.append(points1[pair[1]]) newImagePoints2.append(points2[pair[1]]) minimumErrorT = CVFuncs.minimizeError(oldTriangulatedPoints, newImagePoints1, newImagePoints2, K.matrix, lastR, lastT, r, t) newTriangulations = CVFuncs.discreteTriangulateWithTwoRT(points1, points2, K.matrix, lastR, lastT, r, minimumErrorT) self.RTList.append([r, minimumErrorT]) self.triangulatedPoints[i].extend(newTriangulations) if projections_file: self.projectedPoints[i].extend(draw.getProjectionsWithTwoRT(points1, points2, K.matrix, lastR, lastT, r, minimumErrorT)) lastIdxCorrespondences = indices2 if scene_file: for i in range(len(self.imageList)-1): scenePly = PlyFile() scenePly.emitPoints(self.triangulatedPoints[i]) scenePly.save(file(CVFuncs.addPostToPath(scene_file, str(i)+"-"+str(i+1)), "w")) if projections_file: for i in range(len(self.imageList)-1): projPly = PlyFile() projPly.emitPoints(self.projectedPoints[i]) projPly.save(file(CVFuncs.addPostToPath(projections_file, str(i)+"-"+str(i+1)), "w"))