Esempio n. 1
0
    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
Esempio n. 2
0
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