def solveLabels_temp(self): points, pointLabels, pointNormals, E, x2d_labels = Recon.solve_x3ds_normals( self.x2ds, self.splits, self.labels_temp, self.Ps, self.rays) print "solveLabels:", len(points), np.min(pointLabels), np.max( pointLabels), "(#points | min label | max label)" return points, pointLabels, pointNormals
def cleanAndLabelX3ds(labellingData, x3ds, N, allowStealing=True, pts=np.array([]), visibility=None): global cameraContributions, rayInfo labels = labellingData.labels_temp labelPositions = labellingData.labelPositions x3d_threshold = labellingData.x3d_threshold x2ds = labellingData.x2ds splits = labellingData.splits reconstructionData = labellingData.reconstructionData rays = labellingData.rays cameraPositions = labellingData.cameraPositions # We want to get only the points that have N neighbours within 1cm # TODO: Cache this as we'll be using it multiple times #cloud = ISCV.HashCloud3D(x3ds, x3d_threshold) #scores, matches, matches_splits = cloud.score(x3ds) scores, matches, matches_splits = labellingData.getClusterData(x3ds) #clusterMeanPoints = [] registry = [] x3ds_means = [] x3ds_normals = [] cameraContributions = [] # clusterCameraContributions = [] rawData = None rayInfo = [] labelsAdded = [] #x2ds, splits = data1 #Ps = np.array([m[2] / (np.sum(m[2][0, :3] ** 2) ** 0.5) for m in mats], dtype=np.float32) Ps = labellingData.Ps volatileLabels = [] goldStandardLabels = [] for n in N: #print ">> Min Rays:", n whichMatches = np.where( matches_splits[1:] - matches_splits[:-1] >= n)[0] clusterSplitPairs = np.array( zip(matches_splits[:-1], matches_splits[1:]))[whichMatches] if n == N: rawData = x3ds[whichMatches] clusterCounter = 0 x3ds_clusters = [] x3ds_clusterColours = [] x3ds_clusterMeans = [] x3ds_clusterMeansColours = [] x3ds_clusterLabels = [] for matchFrom, matchTo in clusterSplitPairs: # Find the points for this cluster and calculate the mean position pointIndices = matches[matchFrom:matchTo] numPoints = len(pointIndices) assert (numPoints >= n) clusterMean = np.mean(x3ds[pointIndices], axis=0) if len( np.where( np.linalg.norm(clusterMean - cameraPositions, axis=1) < x3d_threshold * 6.0)[0]) > 0: continue if pts.any(): if len(pts.shape) == 1: dists = np.linalg.norm(clusterMean - pts) else: dists = np.linalg.norm(clusterMean - pts, axis=1) if len(np.where(dists > x3d_threshold * 10.0)[0]) > 0: continue cluster = x3ds[pointIndices] x3ds_clusters.extend(cluster) randomColour = np.concatenate( (np.random.rand(3), np.array([0.5], dtype=np.float32))) x3ds_clusterColours.extend( np.tile(randomColour, (cluster.shape[0], 1))) x3ds_clusterMeans.append(clusterMean) x3ds_clusterMeansColours.append(randomColour) x3ds_clusterLabels.append(clusterCounter) # Get all the rays used to make the points in this cluster. This will be a Nx3 matrix rayIndices = np.unique( [reconstructionData[pi]['pair'] for pi in pointIndices]) pointRays = rays[rayIndices] # Calculate the dot product for each combination of rays. This will be a NxN matrix raysDps = np.dot(pointRays, pointRays.T) # Find the ray which has the highest agreement with the others (sum of dot products) bestRay = np.sum(raysDps > 0, axis=0).argmax() # Find which other rays are in agreement with the best ray (dp > 0) goodRays = np.where(raysDps[bestRay] > 0.05)[0] # As all the (good) rays in the cluster should be contributing to creating a single point, we will # give them a new label that identifies them with the detection/reconstruction for that point #currentLabel = len(clusterMeanPoints) currentLabel = len(labelPositions) labelForPointReconstruction = currentLabel # Only continue with rays from a unique set of cameras camerasForRays = [ findCameraIdFromRayId(rayId, splits) for rayId in rayIndices[goodRays] ] uniqueRayCams, uniqueRayCamsIdx = np.unique(camerasForRays, return_index=True) goodRays = goodRays[uniqueRayCamsIdx] rayInfo.append(raysDps[goodRays]) # TODO: Fix.. nonsense existingLabelsForRays = labels[rayIndices[goodRays]] knownLabelIndices = np.where(existingLabelsForRays != -1)[0] rayIdsForKnownLabels = rayIndices[knownLabelIndices] camerasForKnownLabels = [ findCameraIdFromRayId(rayId, splits) for rayId in rayIdsForKnownLabels ] uniqueCams, uniqueCamsIdx = np.unique(camerasForKnownLabels, return_index=True) knownLabelIndices = knownLabelIndices[uniqueCamsIdx] knownLabels = existingLabelsForRays[knownLabelIndices] clusterCounter += 1 # We check if any of the rays have been assigned a label before (i.e. they will contribute to # reconstructing a 3D point). If that is the case then we have to make decision whether we # want to our rays in this cluster to contribute to the existing label (reconstruction), or # if we want to steal the labelled rays so that they now contribute to creating a new label # for this cluster threshold = x3d_threshold**2 for label in np.unique(knownLabels): # The ray has been labelled to create a 3D point. If that point is within threshold distance # of the current cluster we give this cluster the same label. In essence we are merging the # rays in this cluster with the rays that are already contributing to the label. # However, if the reconstructed label and the cluster mean are further away from each other # we will relabel it with the new label for this cluster which equates to stealing it. #dist = np.linalg.norm(clusterMeanPoints[label] - clusterMean) dist = np.linalg.norm(labelPositions[label] - clusterMean) if dist < threshold: labelForPointReconstruction = label break # threshold = dist _clusterId, _clusterX3dId = len(labelPositions) - 1, len( x3ds_clusterMeans) - 1 # Label the rays with the new or existing (merged) label useNewLabel = False unknownLabels = np.where(existingLabelsForRays == -1)[0] if labelForPointReconstruction == currentLabel: # No merging is going on if len(unknownLabels) > 0: labels[rayIndices[goodRays][unknownLabels]] = currentLabel useNewLabel = True if allowStealing: for knownLabel in knownLabelIndices: rayIdsWithLabel = np.where( labels == existingLabelsForRays[knownLabel])[0] numRaysForLabel = len(rayIdsWithLabel) # if existingLabelsForRays[knownLabel] not in volatileLabels and numRaysForLabel < 3: # if existingLabelsForRays[knownLabel] not in goldStandardLabels and numRaysForLabel < 3: # if existingLabelsForRays[knownLabel] not in goldStandardLabels: agreement = np.where( np.sum(np.dot(bestRay, rays[rayIdsWithLabel]) > 0, axis=1) > 1)[0] if True: labels[rayIndices[goodRays] [knownLabel]] = currentLabel useNewLabel = True else: # Employ merging strategy if allowStealing: rayIdsWithLabel = np.where( labels == labelForPointReconstruction)[0] agreement = np.where( np.sum(np.dot(bestRay, rays[rayIdsWithLabel]) > 0, axis=1) > 1)[0] labels[rayIndices[goodRays] [unknownLabels]] = labelForPointReconstruction for knownLabel in knownLabelIndices: numRaysForLabel = len( np.where(labels == existingLabelsForRays[knownLabel])[0]) # if existingLabelsForRays[knownLabel] not in goldStandardLabels and numRaysForLabel < 3: if existingLabelsForRays[ knownLabel] not in goldStandardLabels: labels[rayIndices[goodRays] [knownLabel]] = currentLabel useNewLabel = True else: labels[rayIndices[goodRays]] = labelForPointReconstruction if useNewLabel: labelPositions[currentLabel] = clusterMean labelsAdded.append(currentLabel) goldStandardLabels = np.where(labels != -1)[0] if len(np.where(labels != -1)[0]) == 0: return np.array([]), np.array([]), np.array([]), rawData, labelsAdded # x3ds_means, x3ds_labels, _, _ = Recon.solve_x3ds(x2ds, splits, labels, Ps) x3ds_means, x3ds_labels, x3ds_normals, _, _ = Recon.solve_x3ds_normals( x2ds, splits, labels, Ps, rays) # x2d_threshold = 30. / 2000. # clouds = ISCV.HashCloud2DList(x2ds, splits, x2d_threshold) # _, labels, _ = clouds.project_assign_visibility(x3ds_means, None, Ps, x2d_threshold, visibility) labellingData.labels = labels usedLabels = np.array(np.where(labels != -1)[0], dtype=np.int32) return x3ds_means, x3ds_labels, x3ds_normals, rawData, labelsAdded