예제 #1
0
def refineSegmentation(image,
                       allSegmentations,
                       allDepths,
                       boundaries,
                       numOutputPlanes=20,
                       numIterations=20,
                       numProposals=5):
    height = allSegmentations.shape[0]
    width = allSegmentations.shape[1]

    #allSegmentations = np.concatenate([planeSegmentations, nonPlaneSegmentation], axis=2)
    #allDepths = np.concatenate([planeDepths, nonPlaneDepth], axis=2)
    proposals = findProposals(allSegmentations, numProposals=numProposals)
    #proposals = np.sort(proposals, axis=-1)
    proposalSegmentations = readProposalInfo(allSegmentations, proposals)
    proposalDepths = readProposalInfo(allDepths, proposals)

    # print(allDepths[80][75])
    # print(proposals[80][75])
    # print(proposalDepths[80][75])
    # exit(1)
    proposals = proposals.reshape((-1, numProposals))
    proposalDepths = proposalDepths.reshape((-1, numProposals))
    smoothBoundaries = boundaries[:, :, 0].reshape(-1)
    occlusionBoundaries = boundaries[:, :, 1].reshape(-1)

    maxDepthDiff = 0.1
    unaries = proposalSegmentations.reshape((-1, numProposals))
    nodes = np.arange(height * width).reshape((height, width))
    #deltas = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]

    deltas = [(0, 1), (1, 0), (-1, 1), (1, 1)]
    edges = []
    edges_features = []
    colors = image.reshape((-1, 3)).astype(np.float32)

    intensityDifferenceSum = 0.0
    intensityDifferenceCount = 0
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height),
                              max(-deltaX, 0):min(width -
                                                  deltaX, width)].reshape(-1)
        intensityDifferenceSum += np.sum(
            pow(
                colors[partial_nodes] - colors[partial_nodes +
                                               (deltaY * width + deltaX)], 2))
        intensityDifferenceCount += partial_nodes.shape[0]
        continue
    intensityDifference = intensityDifferenceSum / intensityDifferenceCount

    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height),
                              max(-deltaX, 0):min(width -
                                                  deltaX, width)].reshape(-1)
        neighbor_nodes = partial_nodes + (deltaY * width + deltaX)
        edges.append(np.stack([partial_nodes, neighbor_nodes], axis=1))

        #depth_1_1 = proposalDepths[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape((-1, numProposals))
        #depth_2_2 = proposalDepths[max(deltaY, 0):min(height + deltaY, height), max(deltaX, 0):min(width + deltaX, width)].reshape((-1, numProposals))

        #label_1 = proposals[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape((-1, numProposals))
        #label_2 = proposals[max(deltaY, 0):min(height + deltaY, height), max(deltaX, 0):min(width + deltaX, width)].reshape((-1, numProposals))

        #smooth_boundary = np.maximum(boundaries[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width), 0].reshape(-1), boundaries[max(deltaY, 0):min(height + deltaY, height), max(deltaX, 0):min(width + deltaX, width), 0].reshape((-1)))
        #occlusion_boundary = np.maximum(boundaries[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width), 1].reshape(-1), boundaries[max(deltaY, 0):min(height + deltaY, height), max(deltaX, 0):min(width + deltaX, width), 1].reshape((-1)))

        depth_1_1 = proposalDepths[partial_nodes]
        depth_2_2 = proposalDepths[neighbor_nodes]
        depth_diff = np.abs(
            np.expand_dims(depth_1_1, -1) - np.expand_dims(depth_2_2, 1))
        depth_diff = np.clip(np.abs(depth_diff) / maxDepthDiff, 0, 1)

        label_1 = proposals[partial_nodes]
        label_2 = proposals[neighbor_nodes]
        label_diff = (np.expand_dims(label_1, -1) != np.expand_dims(
            label_2, 1)).astype(np.float32)
        #label_diff = np.clip(np.abs(label_diff), 0, 1)

        color_1 = colors[partial_nodes]
        color_2 = colors[neighbor_nodes]
        color_diff = pow(color_1 - color_2, 2).sum(1).reshape((-1, 1, 1))
        smooth_boundary = np.maximum(smoothBoundaries[partial_nodes],
                                     smoothBoundaries[neighbor_nodes])
        occlusion_boundary = np.maximum(occlusionBoundaries[partial_nodes],
                                        occlusionBoundaries[neighbor_nodes])

        #pairwise_cost = label_diff * depth_diff * smooth_boundary.reshape((-1, 1, 1)) + label_diff * np.clip(1 - smooth_boundary - occlusion_boundary, 0.1, 1).reshape((-1, 1, 1))

        pairwise_cost = label_diff * (
            1 + 50 * depth_diff +
            20 * np.exp(-color_diff / intensityDifference))

        x = 75
        y = 88
        print((y - deltaY, x - deltaX))
        print((proposals[(y - deltaY) * width + (x - deltaX)]))
        print((proposals[y * width + x]))
        #index = neighbor_nodes == y * width + x
        index = partial_nodes == y * width + x
        print((pairwise_cost[index]))
        print((depth_diff[index]))
        print((depth_1_1[index]))
        print((depth_2_2[index]))
        print((color_diff[index]))

        #print(intensityDifference)
        #exit(1)
        edges_features.append(pairwise_cost)
        #print((edges[-1][partial_nodes == y * width + x][0][1] % width, edges[-1][partial_nodes == y * width + x][0][1] / width))
        #print(edges_features[-1][partial_nodes == y * width + x])
        #mask = edges[-1][:, 1] == y * width + x
        #print((edges[-1][mask][0][0] % width, edges[-1][mask][0][0] / width))
        #print(edges_features[-1][mask])
        continue

    edges = np.concatenate(edges, axis=0)
    edges_features = np.concatenate(edges_features, axis=0)
    refined_segmentation = inference_ogm(unaries * 10,
                                         edges_features,
                                         edges,
                                         return_energy=False,
                                         alg='trw')
    #refined_segmentation = inference_dispatch(unaries, edges_features * 0, edges, ('unary'))
    #refined_segmentation = np.argmin(unaries, axis=1)

    refined_segmentation = refined_segmentation.reshape([height, width, 1])
    refined_segmentation = readProposalInfo(proposals, refined_segmentation)
    refined_segmentation = refined_segmentation.reshape([height, width])

    # print((x, y))
    # print(proposals[y][x])
    # print((x + 1, y))
    # print(proposals[y][x + 1])
    # print((x - 1, y + 1))
    # print(proposals[y + 1][x - 1])
    # print((x, y + 1))
    # print(proposals[y + 1][x])
    # print((x + 1, y + 1))
    # print(proposals[y + 1][x + 1])
    # print(unaries[y * width + x])
    # print(refined_segmentation[y][x])
    return refined_segmentation
예제 #2
0
def getSegmentationsTRWS(planes, image, depth, normal, segmentation, semantics,
                         info, numPlanes):
    numOutputPlanes = planes.shape[0]
    height = depth.shape[0]
    width = depth.shape[1]
    numProposals = 3

    camera = getCameraFromInfo(info)
    urange = (np.arange(width, dtype=np.float32) / (width) *
              (camera['width']) - camera['cx']) / camera['fx']
    urange = urange.reshape(1, -1).repeat(height, 0)
    vrange = (np.arange(height, dtype=np.float32) / (height) *
              (camera['height']) - camera['cy']) / camera['fy']
    vrange = vrange.reshape(-1, 1).repeat(width, 1)

    X = depth * urange
    Y = depth
    Z = -depth * vrange
    points = np.stack([X, Y, Z], axis=2)

    planes = planes[:numPlanes]
    planesD = np.linalg.norm(planes, axis=1, keepdims=True)
    planeNormals = planes / np.maximum(planesD, 1e-4)

    distanceCostThreshold = 0.05
    distanceCost = np.abs(
        np.tensordot(points, planeNormals, axes=([2, 1])) -
        np.reshape(planesD, [1, 1, -1])) / distanceCostThreshold

    normalCost = 0
    if info[19] <= 1:
        normalCostThreshold = 1 - np.cos(20)
        normalCost = (1 - np.tensordot(normal, planeNormals,
                                       axes=([2, 1]))) / normalCostThreshold
        pass

    planeMasks = []
    for planeIndex in range(numPlanes):
        #print(np.bincount(semantics[segmentation == planeIndex]))
        planeMaskOri = segmentation == planeIndex
        semantic = np.bincount(semantics[planeMaskOri]).argmax()
        #print(semantic)
        planeMask = cv2.dilate(
            (np.logical_and(np.logical_or(semantics == semantic, planeMaskOri),
                            distanceCost[:, :, planeIndex])).astype(np.uint8),
            np.ones((3, 3), dtype=np.uint8)).astype(np.float32)
        planeMasks.append(planeMask)
        #cv2.imwrite('test/mask_' + str(planeIndex) + '.png', drawMaskImage(segmentation == planeIndex))
        #cv2.imwrite('test/mask_2.png', drawMaskImage(semantics == semantic))
        continue

    planeMasks = np.stack(planeMasks, 2)

    unaryCost = distanceCost + (1 - planeMasks) * 10000
    unaryCost = np.concatenate(
        [unaryCost, np.ones((height, width, 1))], axis=2)

    proposals = np.argpartition(unaryCost, numProposals)[:, :, :numProposals]
    unaries = -readProposalInfo(unaryCost, proposals).reshape(
        (-1, numProposals))

    # refined_segmentation = np.argmax(unaries, axis=1)
    # refined_segmentation = refined_segmentation.reshape([height, width, 1])
    # refined_segmentation = readProposalInfo(proposals, refined_segmentation)
    # refined_segmentation = refined_segmentation.reshape([height, width])
    # refined_segmentation[refined_segmentation == numPlanes] = numOutputPlanes

    proposals = proposals.reshape((-1, numProposals))
    #cv2.imwrite('test/segmentation.png', drawSegmentationImage(unaries.reshape((height, width, -1)), blackIndex=numOutputPlanes))

    nodes = np.arange(height * width).reshape((height, width))

    image = image.astype(np.float32)
    colors = image.reshape((-1, 3))
    deltas = [(0, 1), (1, 0), (-1, 1), (1, 1)]
    intensityDifferenceSum = 0.0
    intensityDifferenceCount = 0
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height),
                              max(-deltaX, 0):min(width -
                                                  deltaX, width)].reshape(-1)
        intensityDifferenceSum += np.sum(
            pow(
                colors[partial_nodes] - colors[partial_nodes +
                                               (deltaY * width + deltaX)], 2))
        intensityDifferenceCount += partial_nodes.shape[0]
        continue
    intensityDifference = intensityDifferenceSum / intensityDifferenceCount

    edges = []
    edges_features = []

    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height),
                              max(-deltaX, 0):min(width -
                                                  deltaX, width)].reshape(-1)
        edges.append(
            np.stack(
                [partial_nodes, partial_nodes + (deltaY * width + deltaX)],
                axis=1))

        labelDiff = (np.expand_dims(
            proposals[partial_nodes], -1) != np.expand_dims(
                proposals[partial_nodes +
                          (deltaY * width + deltaX)], 1)).astype(np.float32)
        colorDiff = np.sum(pow(
            colors[partial_nodes] - colors[partial_nodes +
                                           (deltaY * width + deltaX)], 2),
                           axis=1)
        pairwise_cost = labelDiff * np.reshape(
            1 + 45 * np.exp(-colorDiff / intensityDifference), [-1, 1, 1])
        #pairwise_cost = np.expand_dims(pairwise_matrix, 0) * np.ones(np.reshape(1 + 45 * np.exp(-colorDiff / np.maximum(intensityDifference[partial_nodes], 1e-4)), [-1, 1, 1]).shape)
        edges_features.append(-pairwise_cost)
        continue

    edges = np.concatenate(edges, axis=0)
    edges_features = np.concatenate(edges_features, axis=0)

    refined_segmentation = inference_ogm(unaries * 10,
                                         edges_features,
                                         edges,
                                         return_energy=False,
                                         alg='trw')
    #print(pairwise_matrix)
    #refined_segmentation = inference_ogm(unaries * 5, -pairwise_matrix, edges, return_energy=False, alg='alphaexp')
    refined_segmentation = refined_segmentation.reshape([height, width, 1])
    refined_segmentation = readProposalInfo(proposals, refined_segmentation)
    refined_segmentation = refined_segmentation.reshape([height, width])
    refined_segmentation[refined_segmentation == numPlanes] = numOutputPlanes
    return refined_segmentation
예제 #3
0
def getSegmentationsGraphCut(planes, image, depth, normal, semantics, info, parameters={}):
    
    height = depth.shape[0]
    width = depth.shape[1]

    numPlanes = planes.shape[0]

    camera = getCameraFromInfo(info)
    urange = (np.arange(width, dtype=np.float32) / (width) * (camera['width']) - camera['cx']) / camera['fx']
    urange = urange.reshape(1, -1).repeat(height, 0)
    vrange = (np.arange(height, dtype=np.float32) / (height) * (camera['height']) - camera['cy']) / camera['fy']
    vrange = vrange.reshape(-1, 1).repeat(width, 1)
    
    X = depth * urange
    Y = depth
    Z = -depth * vrange

    points = np.stack([X, Y, Z], axis=2)
    planes = planes[:numPlanes]
    planesD = np.linalg.norm(planes, axis=1, keepdims=True)
    planeNormals = planes / np.maximum(planesD, 1e-4)

    if 'distanceCostThreshold' in parameters:
        distanceCostThreshold = parameters['distanceCostThreshold']
    else:
        distanceCostThreshold = 0.05
        pass

    distanceCost = np.abs(np.tensordot(points, planeNormals, axes=([2, 1])) - np.reshape(planesD, [1, 1, -1])) / distanceCostThreshold
    distanceCost = np.concatenate([distanceCost, np.ones((height, width, 1))], axis=2)

    normalCostThreshold = 1 - np.cos(np.deg2rad(30))
    normalCost = (1 - np.abs(np.tensordot(normal, planeNormals, axes=([2, 1])))) / normalCostThreshold
    normalCost = np.concatenate([normalCost, np.ones((height, width, 1))], axis=2)


    unaryCost = distanceCost + normalCost
    unaryCost *= np.expand_dims((depth > 1e-4).astype(np.float32), -1)
    unaries = -unaryCost.reshape((-1, numPlanes + 1))

    cv2.imwrite('test/distance_cost.png', drawSegmentationImage(-distanceCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))
    cv2.imwrite('test/normal_cost.png', drawSegmentationImage(-normalCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))
    cv2.imwrite('test/unary_cost.png', drawSegmentationImage(-unaryCost.reshape((height, width, -1)), blackIndex=unaryCost.shape[-1] - 1))    
    cv2.imwrite('test/segmentation.png', drawSegmentationImage(unaries.reshape((height, width, -1)), blackIndex=numPlanes))


    nodes = np.arange(height * width).reshape((height, width))

    image = image.astype(np.float32)
    colors = image.reshape((-1, 3))    

    deltas = [(0, 1), (1, 0), (-1, 1), (1, 1)]    
    
    intensityDifferenceSum = 0.0
    intensityDifferenceCount = 0
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
        intensityDifferenceSum += np.sum(pow(colors[partial_nodes] - colors[partial_nodes + (deltaY * width + deltaX)], 2))
        intensityDifferenceCount += partial_nodes.shape[0]
        continue
    intensityDifference = intensityDifferenceSum / intensityDifferenceCount

    
    edges = []
    edges_features = []
    pairwise_matrix = 1 - np.diag(np.ones(numPlanes + 1))

    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
        edges.append(np.stack([partial_nodes, partial_nodes + (deltaY * width + deltaX)], axis=1))

        colorDiff = np.sum(pow(colors[partial_nodes] - colors[partial_nodes + (deltaY * width + deltaX)], 2), axis=1)
        
        pairwise_cost = np.expand_dims(pairwise_matrix, 0) * np.reshape(1 + 45 * np.exp(-colorDiff / intensityDifference), [-1, 1, 1])
        edges_features.append(pairwise_cost)
        continue

    edges = np.concatenate(edges, axis=0)
    edges_features = np.concatenate(edges_features, axis=0)

    if 'smoothnessWeight' in parameters:
        smoothnessWeight = parameters['smoothnessWeight']
    else:
        smoothnessWeight = 0.02
        pass

    print('start')
    refined_segmentation = inference_ogm(unaries, -edges_features * smoothnessWeight, edges, return_energy=False, alg='alphaexp')
    print('done')
    refined_segmentation = refined_segmentation.reshape([height, width])

    if 'semantics' in parameters and parameters['semantics']:
        for semanticIndex in np.unique(semantics):
            mask = semantics == semanticIndex
            segmentInds = refined_segmentation[mask]
            uniqueSegments, counts = np.unique(segmentInds, return_counts=True)
            for index, count in enumerate(counts):
                if count > segmentInds.shape[0] * 0.9:
                    refined_segmentation[mask] = uniqueSegments[index]
                    pass
                continue
            continue
        pass
    
    return refined_segmentation
예제 #4
0
def fitPlanesPiecewise(image, depth, normal, info, numOutputPlanes=20, imageIndex=1, parameters={}):
    if 'meanshift' in parameters and parameters['meanshift'] > 0:
        import sklearn.cluster
        meanshift = sklearn.cluster.MeanShift(parameters['meanshift'])
        pass
    
    from pylsd import lsd
    
    height = depth.shape[0]
    width = depth.shape[1]

    camera = getCameraFromInfo(info)
    urange = (np.arange(width, dtype=np.float32) / (width) * (camera['width']) - camera['cx']) / camera['fx']
    urange = urange.reshape(1, -1).repeat(height, 0)
    vrange = (np.arange(height, dtype=np.float32) / (height) * (camera['height']) - camera['cy']) / camera['fy']
    vrange = vrange.reshape(-1, 1).repeat(width, 1)
    
    X = depth * urange
    Y = depth
    Z = -depth * vrange


    normals = normal.reshape((-1, 3))
    normals = normals / np.maximum(np.linalg.norm(normals, axis=-1, keepdims=True), 1e-4)
    validMask = np.logical_and(np.linalg.norm(normals, axis=-1) > 1e-4, depth.reshape(-1) > 1e-4)
    
    points = np.stack([X, Y, Z], axis=2).reshape(-1, 3)
    valid_points = points[validMask]
    
    lines = lsd(image.mean(2))

    lineImage = image.copy()
    for line in lines:
        cv2.line(lineImage, (int(line[0]), int(line[1])), (int(line[2]), int(line[3])), (0, 0, 255), int(np.ceil(line[4] / 2)))
        continue
    cv2.imwrite('test/lines.png', lineImage)

    numVPs = 3
    VPs, VPLines, remainingLines = calcVanishingPoints(lines, numVPs=numVPs)

    lineImage = image.copy()    
    for VPIndex, lines in enumerate(VPLines):
        for line in lines:
            cv2.line(lineImage, (int(line[0]), int(line[1])), (int(line[2]), int(line[3])), ((VPIndex == 0) * 255, (VPIndex == 1) * 255, (VPIndex == 2) * 255), int(np.ceil(line[4] / 2)))
            continue
        continue
    cv2.imwrite('test/lines_vp.png', lineImage)    

    dominantNormals = np.stack([(VPs[:, 0] * info[16] / width - info[2]) / info[0], np.ones(numVPs), -(VPs[:, 1] * info[17] / height - info[6]) / info[5]], axis=1)
    dominantNormals /= np.maximum(np.linalg.norm(dominantNormals, axis=1, keepdims=True), 1e-4)

    dotThreshold = np.cos(np.deg2rad(20))
    for normalIndex, crossNormals in enumerate([[1, 2], [2, 0], [0, 1]]):
        normal = np.cross(dominantNormals[crossNormals[0]], dominantNormals[crossNormals[1]])
        normal = normalize(normal)
        if np.dot(normal, dominantNormals[normalIndex]) < dotThreshold:
            dominantNormals = np.concatenate([dominantNormals, np.expand_dims(normal, 0)], axis=0)
            pass
        continue

    print(VPs)
    print(dominantNormals)
    
    dominantNormalImage = np.abs(np.matmul(normal, dominantNormals.transpose()))
    cv2.imwrite('test/dominant_normal.png', drawMaskImage(dominantNormalImage))
    
    planeHypothesisAreaThreshold = width * height * 0.01
    
    planes = []
    vpPlaneIndices = []
    if 'offsetGap' in parameters:
        offsetGap = parameters['offsetGap']
    else:
        offsetGap = 0.1
        pass
    planeIndexOffset = 0

    for dominantNormal in dominantNormals:
        if np.linalg.norm(dominantNormal) < 1e-4:
            continue
        offsets = np.tensordot(valid_points, dominantNormal, axes=([1], [0]))

        if 'meanshift' in parameters and parameters['meanshift'] > 0:
            sampleInds = np.arange(offsets.shape[0])
            np.random.shuffle(sampleInds)
            meanshift.fit(np.expand_dims(offsets[sampleInds[:int(offsets.shape[0] * 0.02)]], -1))
            for offset in meanshift.cluster_centers_:
                planes.append(dominantNormal * offset)
                continue
        else:
            offset = offsets.min()
            maxOffset = offsets.max()
            while offset < maxOffset:
                planeMask = np.logical_and(offsets >= offset, offsets < offset + offsetGap)
                segmentOffsets = offsets[np.logical_and(offsets >= offset, offsets < offset + offsetGap)]
                if segmentOffsets.shape[0] < planeHypothesisAreaThreshold:
                    offset += offsetGap
                    continue
                planeD = segmentOffsets.mean()
                planes.append(dominantNormal * planeD)
                offset = planeD + offsetGap

                continue
            pass
        

        vpPlaneIndices.append(np.arange(planeIndexOffset, len(planes)))
        planeIndexOffset = len(planes)
        continue

    if len(planes) == 0:
        return np.array([]), np.zeros(segmentation.shape).astype(np.int32)    
    planes = np.array(planes)

    
    
    planesD = np.linalg.norm(planes, axis=1, keepdims=True)
    planeNormals = planes / np.maximum(planesD, 1e-4)

    if 'distanceCostThreshold' in parameters:
        distanceCostThreshold = parameters['distanceCostThreshold']
    else:
        distanceCostThreshold = 0.05
        pass


    distanceCost = np.abs(np.tensordot(points, planeNormals, axes=([1, 1])) - np.reshape(planesD, [1, -1])) / distanceCostThreshold

    normalCostThreshold = 1 - np.cos(np.deg2rad(30))        
    normalCost = (1 - np.abs(np.tensordot(normals, planeNormals, axes=([1, 1])))) / normalCostThreshold

    if 'normalWeight' in parameters:
        normalWeight = parameters['normalWeight']
    else:
        normalWeight = 1
        pass
    
    unaryCost = distanceCost + normalCost * normalWeight
    unaryCost *= np.expand_dims(validMask.astype(np.float32), -1)    
    unaries = unaryCost.reshape((width * height, -1))
    
    
    print('number of planes ', planes.shape[0])
    cv2.imwrite('test/distance_cost.png', drawSegmentationImage(-distanceCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))

    cv2.imwrite('test/normal_cost.png', drawSegmentationImage(-normalCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))

    cv2.imwrite('test/unary_cost.png', drawSegmentationImage(-unaryCost.reshape((height, width, -1)), blackIndex=unaryCost.shape[-1] - 1))

    cv2.imwrite('test/segmentation.png', drawSegmentationImage(-unaries.reshape((height, width, -1)), blackIndex=unaries.shape[-1]))
    

    if 'numProposals' in parameters:
        numProposals = parameters['numProposals']
    else:
        numProposals = 3
        pass

    numProposals = min(numProposals, unaries.shape[-1] - 1)
    
    proposals = np.argpartition(unaries, numProposals)[:, :numProposals]
    unaries = -readProposalInfo(unaries, proposals).reshape((-1, numProposals))
    
    nodes = np.arange(height * width).reshape((height, width))

    deltas = [(0, 1), (1, 0)]
    
    edges = []
    edges_features = []
            
                
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
        edges.append(np.stack([partial_nodes, partial_nodes + (deltaY * width + deltaX)], axis=1))

        labelDiff = (np.expand_dims(proposals[partial_nodes], -1) != np.expand_dims(proposals[partial_nodes + (deltaY * width + deltaX)], 1)).astype(np.float32)

        
        edges_features.append(labelDiff)
        continue

    edges = np.concatenate(edges, axis=0)
    edges_features = np.concatenate(edges_features, axis=0)


    if 'edgeWeights' in parameters:
        edgeWeights = parameters['edgeWeights']
    else:
        edgeWeights = [0.5, 0.6, 0.6]
        pass    
    
    lineSets = np.zeros((height * width, 3))
    creaseLines = np.expand_dims(np.stack([planeNormals[:, 0] / info[0], planeNormals[:, 1], -planeNormals[:, 2] / info[5]], axis=1), 1) * planesD.reshape((1, -1, 1))
    creaseLines = creaseLines - np.transpose(creaseLines, [1, 0, 2])    
    for planeIndex_1 in xrange(planes.shape[0]):
        for planeIndex_2 in xrange(planeIndex_1 + 1, planes.shape[0]):
            creaseLine = creaseLines[planeIndex_1, planeIndex_2]
            if abs(creaseLine[0]) > abs(creaseLine[2]):
                vs = np.arange(height)
                us = -(creaseLine[1] + (vs - info[6]) * creaseLine[2]) / creaseLine[0] + info[2]
                minUs = np.floor(us).astype(np.int32)
                maxUs = minUs + 1
                validIndicesMask = np.logical_and(minUs >= 0, maxUs < width)
                if validIndicesMask.sum() == 0:
                    continue
                vs = vs[validIndicesMask]
                minUs = minUs[validIndicesMask]
                maxUs = maxUs[validIndicesMask]
                edgeIndices = (height - 1) * width + (vs * (width - 1) + minUs)
                for index, edgeIndex in enumerate(edgeIndices):
                    pixel_1 = vs[index] * width + minUs[index]
                    pixel_2 = vs[index] * width + maxUs[index]
                    proposals_1 = proposals[pixel_1]
                    proposals_2 = proposals[pixel_2]                    
                    if planeIndex_1 in proposals_1 and planeIndex_2 in proposals_2:
                        proposalIndex_1 = np.where(proposals_1 == planeIndex_1)[0][0]
                        proposalIndex_2 = np.where(proposals_2 == planeIndex_2)[0][0]
                        edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[0]
                        pass
                    if planeIndex_2 in proposals_1 and planeIndex_1 in proposals_2:
                        proposalIndex_1 = np.where(proposals_1 == planeIndex_2)[0][0]
                        proposalIndex_2 = np.where(proposals_2 == planeIndex_1)[0][0]
                        edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[0]
                        pass
                    continue

                lineSets[vs * width + minUs, 0] = 1
                lineSets[vs * width + maxUs, 0] = 1
            else:
                us = np.arange(width)
                vs = -(creaseLine[1] + (us - info[2]) * creaseLine[0]) / creaseLine[2] + info[6]
                minVs = np.floor(vs).astype(np.int32)
                maxVs = minVs + 1
                validIndicesMask = np.logical_and(minVs >= 0, maxVs < height)
                if validIndicesMask.sum() == 0:
                    continue                
                us = us[validIndicesMask]
                minVs = minVs[validIndicesMask]
                maxVs = maxVs[validIndicesMask]                
                edgeIndices = (minVs * width + us)
                for index, edgeIndex in enumerate(edgeIndices):
                    pixel_1 = minVs[index] * width + us[index]
                    pixel_2 = maxVs[index] * width + us[index]
                    proposals_1 = proposals[pixel_1]
                    proposals_2 = proposals[pixel_2]                    
                    if planeIndex_1 in proposals_1 and planeIndex_2 in proposals_2:
                        proposalIndex_1 = np.where(proposals_1 == planeIndex_1)[0][0]
                        proposalIndex_2 = np.where(proposals_2 == planeIndex_2)[0][0]
                        edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[0]
                        pass
                    if planeIndex_2 in proposals_1 and planeIndex_1 in proposals_2:
                        proposalIndex_1 = np.where(proposals_1 == planeIndex_2)[0][0]
                        proposalIndex_2 = np.where(proposals_2 == planeIndex_1)[0][0]
                        edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[0]
                        pass
                    continue
                lineSets[minVs * width + us, 0] = 1
                lineSets[maxVs * width + us, 0] = 1                
                pass
            continue
        continue

    planeDepths = calcPlaneDepths(planes, width, height, np.array([info[0], info[5], info[2], info[6], info[16], info[17], 0, 0, 0, 0])).reshape((height * width, -1))
    planeDepths = readProposalInfo(planeDepths, proposals).reshape((-1, numProposals))

    planeHorizontalVPMask = np.ones((planes.shape[0], 3), dtype=np.bool)
    for VPIndex, planeIndices in enumerate(vpPlaneIndices):
        planeHorizontalVPMask[planeIndices] = False
        continue

    
    for VPIndex, lines in enumerate(VPLines):
        lp = lines[:, :2]
        ln = lines[:, 2:4] - lines[:, :2]
        ln /= np.maximum(np.linalg.norm(ln, axis=-1, keepdims=True), 1e-4)
        ln = np.stack([ln[:, 1], -ln[:, 0]], axis=1)
        lnp = (ln * lp).sum(1, keepdims=True)
        occlusionLines = np.concatenate([ln, lnp], axis=1)
        for occlusionLine in occlusionLines:
            if abs(occlusionLine[0]) > abs(occlusionLine[1]):
                vs = np.arange(height)
                us = (occlusionLine[2] - vs * occlusionLine[1]) / occlusionLine[0]
                minUs = np.floor(us).astype(np.int32)
                maxUs = minUs + 1
                validIndicesMask = np.logical_and(minUs >= 0, maxUs < width)
                vs = vs[validIndicesMask]
                minUs = minUs[validIndicesMask]
                maxUs = maxUs[validIndicesMask]                
                edgeIndices = (height - 1) * width + (vs * (width - 1) + minUs)
                for index, edgeIndex in enumerate(edgeIndices):
                    pixel_1 = vs[index] * width + minUs[index]
                    pixel_2 = vs[index] * width + maxUs[index]
                    proposals_1 = proposals[pixel_1]
                    proposals_2 = proposals[pixel_2]                    
                    for proposalIndex_1, planeIndex_1 in enumerate(proposals_1):
                        if not planeHorizontalVPMask[planeIndex_1][VPIndex]:
                            continue
                        planeDepth_1 = planeDepths[pixel_1][proposalIndex_1]
                        for proposalIndex_2, planeIndex_2 in enumerate(proposals_2):
                            if planeDepths[pixel_2][proposalIndex_2] > planeDepth_1:
                                edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[1]
                                pass
                            continue
                        continue
                    continue
                lineSets[vs * width + minUs, 1] = 1
                lineSets[vs * width + maxUs, 1] = 1
            else:
                us = np.arange(width)
                vs = (occlusionLine[2] - us * occlusionLine[0]) / occlusionLine[1]
                
                minVs = np.floor(vs).astype(np.int32)
                maxVs = minVs + 1
                validIndicesMask = np.logical_and(minVs >= 0, maxVs < height)
                us = us[validIndicesMask]
                minVs = minVs[validIndicesMask]
                maxVs = maxVs[validIndicesMask]                
                edgeIndices = (minVs * width + us)
                for index, edgeIndex in enumerate(edgeIndices):
                    pixel_1 = minVs[index] * width + us[index]
                    pixel_2 = maxVs[index] * width + us[index]
                    proposals_1 = proposals[pixel_1]
                    proposals_2 = proposals[pixel_2]                    
                    for proposalIndex_1, planeIndex_1 in enumerate(proposals_1):
                        if not planeHorizontalVPMask[planeIndex_1][VPIndex]:
                            continue
                        planeDepth_1 = planeDepths[pixel_1][proposalIndex_1]
                        for proposalIndex_2, planeIndex_2 in enumerate(proposals_2):
                            if planeDepths[pixel_2][proposalIndex_2] > planeDepth_1:
                                edges_features[edgeIndex, proposalIndex_1, proposalIndex_2] *= edgeWeights[1]
                                pass
                            continue
                        continue
                    continue
                lineSets[minVs * width + us, 1] = 1
                lineSets[maxVs * width + us, 1] = 1                
                pass
            continue
        continue

    for line in remainingLines:
        if abs(line[3] - line[1]) > abs(line[2] - line[0]):
            if line[3] < line[1]:
                line = np.array([line[2], line[3], line[0], line[1]])
                pass
            vs = np.arange(line[1], line[3] + 1, dtype=np.int32)
            us = line[0] + (vs - line[1]) / (line[3] - line[1]) * (line[2] - line[0])
            minUs = np.floor(us).astype(np.int32)
            maxUs = minUs + 1
            validIndicesMask = np.logical_and(minUs >= 0, maxUs < width)
            vs = vs[validIndicesMask]
            minUs = minUs[validIndicesMask]
            maxUs = maxUs[validIndicesMask]                
            edgeIndices = (height - 1) * width + (vs * (width - 1) + minUs)
            for edgeIndex in edgeIndices:
                edges_features[edgeIndex] *= edgeWeights[2]
                continue
            lineSets[(vs * width + minUs), 2] = 1
            lineSets[(vs * width + maxUs), 2] = 1            
        else:
            if line[2] < line[0]:
                line = np.array([line[2], line[3], line[0], line[1]])
                pass
            us = np.arange(line[0], line[2] + 1, dtype=np.int32)
            vs = line[1] + (us - line[0]) / (line[2] - line[0]) * (line[3] - line[1])
            
            minVs = np.floor(vs).astype(np.int32)
            maxVs = minVs + 1
            validIndicesMask = np.logical_and(minVs >= 0, maxVs < height)
            us = us[validIndicesMask]
            minVs = minVs[validIndicesMask]
            maxVs = maxVs[validIndicesMask]
            edgeIndices = (minVs * width + us)
            for edgeIndex in edgeIndices:
                edges_features[edgeIndex] *= edgeWeights[2]
                continue
            lineSets[minVs * width + us, 2] = 1
            lineSets[maxVs * width + us, 2] = 1
            continue
        continue
    cv2.imwrite('test/line_sets.png', drawMaskImage(lineSets.reshape((height, width, 3))))
    

    if 'smoothnessWeight' in parameters:
        smoothnessWeight = parameters['smoothnessWeight']
    else:
        smoothnessWeight = 4
        pass

    print('start')
    refined_segmentation = inference_ogm(unaries, -edges_features * smoothnessWeight, edges, return_energy=False, alg='trw')
    print('done')
    refined_segmentation = refined_segmentation.reshape([height, width, 1])    
    refined_segmentation = readProposalInfo(proposals, refined_segmentation)
    planeSegmentation = refined_segmentation.reshape([height, width])

    planeSegmentation[np.logical_not(validMask.reshape((height, width)))] = planes.shape[0]    
    cv2.imwrite('test/segmentation_refined.png', drawSegmentationImage(planeSegmentation))
    
    return planes, planeSegmentation
예제 #5
0
def fitPlanesManhattan(image, depth, normal, info, numOutputPlanes=20, imageIndex=-1, parameters={}):
    if 'meanshift' in parameters and parameters['meanshift'] > 0:
        import sklearn.cluster
        meanshift = sklearn.cluster.MeanShift(parameters['meanshift'])
        pass

    
    height = depth.shape[0]
    width = depth.shape[1]

    camera = getCameraFromInfo(info)
    urange = (np.arange(width, dtype=np.float32) / (width) * (camera['width']) - camera['cx']) / camera['fx']
    urange = urange.reshape(1, -1).repeat(height, 0)
    vrange = (np.arange(height, dtype=np.float32) / (height) * (camera['height']) - camera['cy']) / camera['fy']
    vrange = vrange.reshape(-1, 1).repeat(width, 1)
    
    X = depth * urange
    Y = depth
    Z = -depth * vrange


    normals = normal.reshape((-1, 3))
    normals = normals / np.maximum(np.linalg.norm(normals, axis=-1, keepdims=True), 1e-4)

    validMask = np.logical_and(np.linalg.norm(normals, axis=-1) > 1e-4, depth.reshape(-1) > 1e-4)
    
    valid_normals = normals[validMask]

    
    points = np.stack([X, Y, Z], axis=2).reshape(-1, 3)
    valid_points = points[validMask]

    polarAngles = np.arange(16) * np.pi / 2 / 16
    azimuthalAngles = np.arange(64) * np.pi * 2 / 64
    polarAngles = np.expand_dims(polarAngles, -1)
    azimuthalAngles = np.expand_dims(azimuthalAngles, 0)

    normalBins = np.stack([np.sin(polarAngles) * np.cos(azimuthalAngles), np.tile(np.cos(polarAngles), [1, azimuthalAngles.shape[1]]), -np.sin(polarAngles) * np.sin(azimuthalAngles)], axis=2)
    normalBins = np.reshape(normalBins, [-1, 3])
    numBins = normalBins.shape[0]
    
    
    normalDiff = np.tensordot(valid_normals, normalBins, axes=([1], [1]))
    normalDiffSign = np.sign(normalDiff)
    normalDiff = np.maximum(normalDiff, -normalDiff)
    normalMask = one_hot(np.argmax(normalDiff, axis=-1), numBins)
    bins = normalMask.sum(0)
    np.expand_dims(valid_normals, 1) * np.expand_dims(normalMask, -1)

    maxNormals = np.expand_dims(valid_normals, 1) * np.expand_dims(normalMask, -1)
    maxNormals *= np.expand_dims(normalDiffSign, -1)
    averageNormals = maxNormals.sum(0) / np.maximum(np.expand_dims(bins, -1), 1e-4)
    averageNormals /= np.maximum(np.linalg.norm(averageNormals, axis=-1, keepdims=True), 1e-4)
    dominantNormal_1 = averageNormals[np.argmax(bins)]

    dotThreshold_1 = np.cos(np.deg2rad(100))
    dotThreshold_2 = np.cos(np.deg2rad(80))
    
    dot_1 = np.tensordot(normalBins, dominantNormal_1, axes=([1], [0]))
    bins[np.logical_or(dot_1 < dotThreshold_1, dot_1 > dotThreshold_2)] = 0
    dominantNormal_2 = averageNormals[np.argmax(bins)]
    dot_2 = np.tensordot(normalBins, dominantNormal_2, axes=([1], [0]))
    bins[np.logical_or(dot_2 < dotThreshold_1, dot_2 > dotThreshold_2)] = 0
    
    dominantNormal_3 = averageNormals[np.argmax(bins)]


    dominantNormals = np.stack([dominantNormal_1, dominantNormal_2, dominantNormal_3], axis=0)

    dominantNormalImage = np.abs(np.matmul(normal, dominantNormals.transpose()))
    
    planeHypothesisAreaThreshold = width * height * 0.01

    
    planes = []
    
    if 'offsetGap' in parameters:
        offsetGap = parameters['offsetGap']
    else:
        offsetGap = 0.1
        pass
    for dominantNormal in dominantNormals:
        offsets = np.tensordot(valid_points, dominantNormal, axes=([1], [0]))

        if 'meanshift' in parameters and parameters['meanshift'] > 0:
            sampleInds = np.arange(offsets.shape[0])
            np.random.shuffle(sampleInds)
            meanshift.fit(np.expand_dims(offsets[sampleInds[:int(offsets.shape[0] * 0.02)]], -1))
            for offset in meanshift.cluster_centers_:
                planes.append(dominantNormal * offset)
                continue
            
        offset = offsets.min()
        maxOffset = offsets.max()
        while offset < maxOffset:
            planeMask = np.logical_and(offsets >= offset, offsets < offset + offsetGap)
            segmentOffsets = offsets[np.logical_and(offsets >= offset, offsets < offset + offsetGap)]
            if segmentOffsets.shape[0] < planeHypothesisAreaThreshold:
                offset += offsetGap
                continue
            planeD = segmentOffsets.mean()
            planes.append(dominantNormal * planeD)
            offset = planeD + offsetGap
            continue
        continue
    
    if len(planes) == 0:
        return np.array([]), np.zeros(segmentation.shape).astype(np.int32)
    
    planes = np.array(planes)
    print('number of planes ', planes.shape[0])

    vanishingPoints = np.stack([dominantNormals[:, 0] / np.maximum(dominantNormals[:, 1], 1e-4) * info[0] + info[2], -dominantNormals[:, 2] / np.maximum(dominantNormals[:, 1], 1e-4) * info[5] + info[6]], axis=1)
    vanishingPoints[:, 0] *= width / info[16]
    vanishingPoints[:, 1] *= height / info[17]

    indices = np.arange(width * height, dtype=np.int32)
    uv = np.stack([indices % width, indices // width], axis=1)
    colors = image.reshape((-1, 3))
    windowW = 9
    windowH = 3
    dominantLineMaps = []
    for vanishingPointIndex, vanishingPoint in enumerate(vanishingPoints):
        horizontalDirection = uv - np.expand_dims(vanishingPoint, 0)
        horizontalDirection = horizontalDirection / np.maximum(np.linalg.norm(horizontalDirection, axis=1, keepdims=True), 1e-4)
        verticalDirection = np.stack([horizontalDirection[:, 1], -horizontalDirection[:, 0]], axis=1)

        colorDiffs = []
        for directionIndex, direction in enumerate([horizontalDirection, verticalDirection]):
            neighbors = uv + direction
            neighborsX = neighbors[:, 0]
            neighborsY = neighbors[:, 1]
            neighborsMinX = np.maximum(np.minimum(np.floor(neighborsX).astype(np.int32), width - 1), 0)
            neighborsMaxX = np.maximum(np.minimum(np.ceil(neighborsX).astype(np.int32), width - 1), 0)
            neighborsMinY = np.maximum(np.minimum(np.floor(neighborsY).astype(np.int32), height - 1), 0)
            neighborsMaxY = np.maximum(np.minimum(np.ceil(neighborsY).astype(np.int32), height - 1), 0)
            indices_1 = neighborsMinY * width + neighborsMinX
            indices_2 = neighborsMaxY * width + neighborsMinX
            indices_3 = neighborsMinY * width + neighborsMaxX            
            indices_4 = neighborsMaxY * width + neighborsMaxX
            areas_1 = (neighborsMaxX - neighborsX) * (neighborsMaxY - neighborsY)
            areas_2 = (neighborsMaxX - neighborsX) * (neighborsY - neighborsMinY)
            areas_3 = (neighborsX - neighborsMinX) * (neighborsMaxY - neighborsY)
            areas_4 = (neighborsX - neighborsMinX) * (neighborsY - neighborsMinY)

            neighborsColor = colors[indices_1] * np.expand_dims(areas_1, -1) + colors[indices_2] * np.expand_dims(areas_2, -1) + colors[indices_3] * np.expand_dims(areas_3, -1) + colors[indices_4] * np.expand_dims(areas_4, -1)
            colorDiff = np.linalg.norm(neighborsColor - colors, axis=-1)

            colorDiffs.append(colorDiff)
            continue
        colorDiffs = np.stack(colorDiffs, 1)

        deltaUs, deltaVs = np.meshgrid(np.arange(windowW) - (windowW - 1) / 2, np.arange(windowH) - (windowH - 1) / 2)
        deltas = deltaUs.reshape((1, -1, 1)) * np.expand_dims(horizontalDirection, axis=1) + deltaVs.reshape((1, -1, 1)) * np.expand_dims(verticalDirection, axis=1)
        
        windowIndices = np.expand_dims(uv, 1) - deltas
        windowIndices = (np.minimum(np.maximum(np.round(windowIndices[:, :, 1]), 0), height - 1) * width + np.minimum(np.maximum(np.round(windowIndices[:, :, 0]), 0), width - 1)).astype(np.int32)
        
        dominantLineMap = []

        for pixels in windowIndices:
            gradientSums = colorDiffs[pixels].sum(0)
            dominantLineMap.append(gradientSums[1] / max(gradientSums[0], 1e-4))
            continue
        dominantLineMaps.append(np.array(dominantLineMap).reshape((height, width)))
        continue
    dominantLineMaps = np.stack(dominantLineMaps, axis=2)
    if 'dominantLineThreshold' in parameters:
        dominantLineThreshold = parameters['dominantLineThreshold']
    else:
        dominantLineThreshold = 3
        pass

    smoothnessWeightMask = dominantLineMaps.max(2) > dominantLineThreshold
    
    planesD = np.linalg.norm(planes, axis=1, keepdims=True)
    planeNormals = planes / np.maximum(planesD, 1e-4)


    if 'distanceCostThreshold' in parameters:
        distanceCostThreshold = parameters['distanceCostThreshold']
    else:
        distanceCostThreshold = 0.05
        pass
    
    distanceCost = np.abs(np.tensordot(points, planeNormals, axes=([1, 1])) - np.reshape(planesD, [1, -1])) / distanceCostThreshold

    normalCost = 0
    normalCostThreshold = 1 - np.cos(np.deg2rad(30))        
    normalCost = (1 - np.abs(np.tensordot(normals, planeNormals, axes=([1, 1])))) / normalCostThreshold
    
    unaryCost = distanceCost + normalCost
    unaryCost *= np.expand_dims(validMask.astype(np.float32), -1)
    unaries = unaryCost.reshape((width * height, -1))

    if False:
        cv2.imwrite('test/dominant_normal.png', drawMaskImage(dominantNormalImage))
        
        if imageIndex >= 0:
            cv2.imwrite('test/' + str(imageIndex) + '_dominant_lines.png', drawMaskImage(dominantLineMaps / dominantLineThreshold))
        else:
            cv2.imwrite('test/dominant_lines.png', drawMaskImage(dominantLineMaps / dominantLineThreshold))
            pass
        cv2.imwrite('test/dominant_lines_mask.png', drawMaskImage(smoothnessWeightMask))            
        cv2.imwrite('test/distance_cost.png', drawSegmentationImage(-distanceCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))
        cv2.imwrite('test/normal_cost.png', drawSegmentationImage(-normalCost.reshape((height, width, -1)), unaryCost.shape[-1] - 1))
        cv2.imwrite('test/unary_cost.png', drawSegmentationImage(-unaryCost.reshape((height, width, -1)), blackIndex=unaryCost.shape[-1] - 1))
        cv2.imwrite('test/segmentation.png', drawSegmentationImage(-unaries.reshape((height, width, -1)), blackIndex=unaries.shape[-1]))
        pass

    if 'numProposals' in parameters:
        numProposals = parameters['numProposals']
    else:
        numProposals = 3
        pass
    numProposals = min(numProposals, unaries.shape[-1] - 1)
    proposals = np.argpartition(unaries, numProposals)[:, :numProposals]
    proposals[np.logical_not(validMask)] = 0
    
    unaries = -readProposalInfo(unaries, proposals).reshape((-1, numProposals))
    
    nodes = np.arange(height * width).reshape((height, width))

    deltas = [(0, 1), (1, 0)]
    
    edges = []
    edges_features = []
    smoothnessWeights = 1 - 0.99 * smoothnessWeightMask.astype(np.float32)
    
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
        edges.append(np.stack([partial_nodes, partial_nodes + (deltaY * width + deltaX)], axis=1))

        labelDiff = (np.expand_dims(proposals[partial_nodes], -1) != np.expand_dims(proposals[partial_nodes + (deltaY * width + deltaX)], 1)).astype(np.float32)
        edges_features.append(labelDiff * smoothnessWeights.reshape((width * height, -1))[partial_nodes].reshape(-1, 1, 1))
        continue

    edges = np.concatenate(edges, axis=0)
    edges_features = np.concatenate(edges_features, axis=0)


    if 'smoothnessWeight' in parameters:
        smoothnessWeight = parameters['smoothnessWeight']
    else:
        smoothnessWeight = 40
        pass

    print('start')
    refined_segmentation = inference_ogm(unaries, -edges_features * smoothnessWeight, edges, return_energy=False, alg='trw')
    print('done')
    
    refined_segmentation = refined_segmentation.reshape([height, width, 1])
    refined_segmentation = readProposalInfo(proposals, refined_segmentation)
    planeSegmentation = refined_segmentation.reshape([height, width])

    planeSegmentation[np.logical_not(validMask.reshape((height, width)))] = planes.shape[0]

    cv2.imwrite('test/segmentation_refined.png', drawSegmentationImage(planeSegmentation))
    
    return planes, planeSegmentation
def decompose(image, depth, normal, info, planes, segmentation):
    NUM_PLANES = planes.shape[0]
    #segmentation[segmentation == numPlanes] = 
    NUM_LAYERS = 3
    
    height = depth.shape[0]
    width = depth.shape[1]
    
    segmentations = (np.expand_dims(segmentation, -1) == np.arange(NUM_PLANES).reshape([1, 1, -1])).astype(np.float32)
    
    planeDepths = calcPlaneDepths(planes, width, height, info)

    # for planeIndex in xrange(NUM_PLANES):
    #     cv2.imwrite('test/depth_' + str(planeIndex) + '.png', drawDepthImage(planeDepths[:, :, planeIndex]))
    #     continue
    
    allDepths = np.concatenate([planeDepths, np.zeros((height, width, 1))], axis=2)
    
    camera = getCameraFromInfo(info)
    urange = (np.arange(width, dtype=np.float32) / (width) * (camera['width']) - camera['cx']) / camera['fx']
    urange = urange.reshape(1, -1).repeat(height, 0)
    vrange = (np.arange(height, dtype=np.float32) / (height) * (camera['height']) - camera['cy']) / camera['fy']
    vrange = vrange.reshape(-1, 1).repeat(width, 1)
    
    X = depth * urange
    Y = depth
    Z = -depth * vrange


    normals = normal.reshape((-1, 3))
    normals = normals / np.maximum(np.linalg.norm(normals, axis=-1, keepdims=True), 1e-4)
    validMask = np.logical_and(np.linalg.norm(normals, axis=-1) > 1e-4, depth.reshape(-1) > 1e-4)
    
    points = np.stack([X, Y, Z], axis=2).reshape(-1, 3)
    
    planesD = np.linalg.norm(planes, axis=1, keepdims=True)
    planeNormals = planes / np.maximum(planesD, 1e-4)

    distanceCostThreshold = 0.1
    distanceCost = np.abs(np.tensordot(points, planeNormals, axes=([1, 1])) - np.reshape(planesD, [1, -1])) / distanceCostThreshold

    #valid_normals = normals[validMask]
    normalCostThreshold = 1 - np.cos(np.deg2rad(30))        
    normalCost = (1 - np.abs(np.tensordot(normals, planeNormals, axes=([1, 1])))) / normalCostThreshold

    normalWeight = 1    
    
    unaryCost = distanceCost + normalCost * normalWeight
    unaryCost *= np.expand_dims(validMask.astype(np.float32), -1)
    unaryCost = np.concatenate([unaryCost, np.full((unaryCost.shape[0], 1), 100)], axis=1)
    #unaryCost = unaryCost.reshape((height * width, -1))


    nodes = np.arange(height * width).reshape((height, width))    
    
    image = image.astype(np.float32)
    colors = image.reshape((-1, 3))
    deltas = [(0, 1), (1, 0)]    
    intensityDifferenceSum = 0.0
    intensityDifferenceCount = 0
    for delta in deltas:
        deltaX = delta[0]
        deltaY = delta[1]
        partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
        intensityDifferenceSum += np.sum(pow(colors[partial_nodes] - colors[partial_nodes + (deltaY * width + deltaX)], 2))
        intensityDifferenceCount += partial_nodes.shape[0]
        continue
    intensityDifference = intensityDifferenceSum / intensityDifferenceCount
    maxDepthDiff = 0.3
    depthGap = 0.05
    
    solution = []
    for iteration in range(6):
        if os.path.exists('test/solution_' + str(iteration) + '.npy') and iteration <= 4:
            solution = np.load('test/solution_' + str(iteration) + '.npy')
            continue

        proposals = getProposals(solution, planes, segmentation, segmentations, planeDepths, iteration, NUM_LAYERS=NUM_LAYERS, NUM_PLANES=NUM_PLANES, height=height, width=width)

        numProposals = len(proposals)

        if numProposals == 1:
            solution = proposals[0]
            continue
        
        proposals = [proposals[0]]
        numProposals = len(proposals)
                
        for proposalIndex, proposal in enumerate(proposals):
            drawSolution(proposal, NUM_PLANES, proposalIndex)
            continue

        #if iteration == 2:
        #exit(1)
            
        visibleSegmentations = []
        for proposal in proposals:
            visibleSegmentation = proposal[:, :, 0].copy()
            for layer in range(1, NUM_LAYERS):
                mask = proposal[:, :, layer] < NUM_PLANES
                visibleSegmentation[mask] = proposal[:, :, layer][mask]
                continue
            visibleSegmentations.append(visibleSegmentation)
            continue
        visibleSegmentations = np.stack(visibleSegmentations, axis=-1).reshape((-1, numProposals))

        #cv2.imwrite('test/segmentation_0.png', drawSegmentationImage(visibleSegmentations[:, 0].reshape((height, width)), blackIndex=NUM_PLANES))
        #cv2.imwrite('test/segmentation_1.png', drawSegmentationImage(visibleSegmentations[:, 1].reshape((height, width)), blackIndex=NUM_PLANES))        
        
        unaries = readProposalInfo(unaryCost, visibleSegmentations)

        proposalDepths = []
        for proposal in proposals:
            proposalDepths.append(readProposalInfo(allDepths, proposal))
            continue
        proposalDepths = np.stack(proposalDepths, axis=-1)
        proposalDepths = proposalDepths.reshape((width * height, NUM_LAYERS, numProposals))

        conflictDepthMask = np.zeros((width * height, numProposals), dtype=np.bool)
        for layer in range(1, NUM_LAYERS):
            conflictDepthMask = np.logical_or(conflictDepthMask, np.logical_and(proposalDepths[:, layer, :] > proposalDepths[:, layer - 1, :] + depthGap, proposalDepths[:, layer - 1, :] > 1e-4))
            continue
        unaries += conflictDepthMask.astype(np.float32) * 100
        
        #cv2.imwrite('test/mask_0.png', drawMaskImage((unaries[:, 1] - unaries[:, 0]).reshape((height, width)) / 2 + 0.5))
        #exit(1)
        #print((unaries[:, 1] - unaries[:, 0]).min())        

        
        #print((unaries[:, 1] - unaries[:, 0]).max())
        #print((unaries[:, 1] - unaries[:, 0]).min())        
        
        proposals = np.stack(proposals, axis=-1).reshape((width * height, NUM_LAYERS, numProposals))

        #empty background cost
        unaries += (proposals[:, 0, :] == NUM_PLANES).astype(np.float32) * 100

        #print((unaries[:, 1] - unaries[:, 0]).max())
        #print((unaries[:, 1] - unaries[:, 0]).min())        
        #exit(1)
        #cv2.imwrite('test/segmentation.png', drawSegmentationImage(unaries.reshape((height, width, -1)), blackIndex=numOutputPlanes))
        #cv2.imwrite('test/mask_0.png', drawMaskImage((unaries[:, 1] - unaries[:, 0]).reshape((height, width)) / 2 + 0.5))
        #exit(1)
        
        edges = []
        edges_features = []

        for deltaIndex, delta in enumerate(deltas):
            deltaX = delta[0]
            deltaY = delta[1]
            partial_nodes = nodes[max(-deltaY, 0):min(height - deltaY, height), max(-deltaX, 0):min(width - deltaX, width)].reshape(-1)
            edges.append(np.stack([partial_nodes, partial_nodes + (deltaY * width + deltaX)], axis=1))

            
            #pairwise_cost = np.zeros((partial_nodes.shape[0], numProposals, numProposals))

            labels_1 = np.expand_dims(proposals[partial_nodes], -1)
            labels_2 = np.expand_dims(proposals[partial_nodes + (deltaY * width + deltaX)], -2)
            labelDiff = (labels_1 != labels_2).astype(np.float32)

            depth_1 = np.expand_dims(proposalDepths[partial_nodes], -1)
            depth_2 = np.expand_dims(proposalDepths[partial_nodes + (deltaY * width + deltaX)], -2)

            visibleLabels_1 = np.expand_dims(visibleSegmentations[partial_nodes], -1)
            visibleLabels_2 = np.expand_dims(visibleSegmentations[partial_nodes + (deltaY * width + deltaX)], -2)
            
            
            emptyMask_1 = np.logical_and(depth_1 > 1e-4, depth_2 < 1e-4)
            emptyMask_2 = np.logical_and(depth_1 < 1e-4, depth_2 > 1e-4)
            emptyMask = np.logical_or(emptyMask_1, emptyMask_2)

            cutMask = (labelDiff - (np.expand_dims(labels_1, -3) != np.expand_dims(labels_2, -4)).astype(np.float32).min(-3)) * (labels_1 < NUM_PLANES).astype(np.float32)

            
            visibleEmptyMask = np.logical_or(np.logical_and(emptyMask_1, (labels_1 == np.expand_dims(visibleLabels_1, -3))), np.logical_and(emptyMask_2, (labels_2 == np.expand_dims(visibleLabels_2, -3))))
            invisibleEmptyMask = np.logical_and(emptyMask, np.logical_not(visibleEmptyMask))
            
            depthDiff = np.abs(depth_1 - depth_2) / maxDepthDiff * (1 - emptyMask) + invisibleEmptyMask * (0.05 / maxDepthDiff)


            visibleLabelDiff = (visibleLabels_1 != visibleLabels_2)
            visibleLabelDiff = np.logical_or(visibleEmptyMask.max(1), visibleLabelDiff).astype(np.float32)
            
            colorDiff = np.sum(pow(colors[partial_nodes] - colors[partial_nodes + (deltaY * width + deltaX)], 2), axis=-1)
            #depth_diff = np.clip(np.abs(depth_diff) / maxDepthDiff, 0, 1)
            #depth_2_2 = proposalDepths[max(deltaY, 0):min(height + deltaY, height), max(deltaX, 0):min(width + deltaX, width)].reshape((-1, numProposals))
            
            pairwise_cost = (labelDiff * depthDiff).sum(1) + visibleLabelDiff * np.reshape(0.02 + np.exp(-colorDiff / intensityDifference), [-1, 1, 1])
            np.reshape(1 + 45 * np.exp(-colorDiff / intensityDifference), [-1, 1, 1])
            #pairwise_cost = np.expand_dims(pairwise_matrix, 0) * np.ones(np.reshape(1 + 45 * np.exp(-colorDiff / np.maximum(intensityDifference[partial_nodes], 1e-4)), [-1, 1, 1]).shape)
            edges_features.append(-pairwise_cost)

            #print(pairwise_cost.shape)
            #print(pairwise_cost.max())

            debug = False
            if debug:
                cv2.imwrite('test/cost_diff.png', drawMaskImage((unaries[:, 1] - unaries[:, 0]).reshape((height, width)) / 2 + 0.5))

                #exit(1)
                if deltaIndex == 0:
                    cv2.imwrite('test/cost_color.png', drawMaskImage((visibleLabelDiff * np.reshape(0.02 + np.exp(-colorDiff / intensityDifference), (-1, 1, 1)))[:, 0, 1].reshape((height - 1, width))))

                    #cv2.imwrite('test/segmentation.png', drawSegmentationImage(proposals[partial_nodes, 0, 1].reshape((height - 1, width))))
                    #diff = (labelDiff * depthDiff).reshape((height - 1, width, NUM_LAYERS, numProposals, numProposals))
                    diff = (invisibleEmptyMask).reshape((height - 1, width, NUM_LAYERS, numProposals, numProposals))
                    #diff = (labelDiff).reshape((height - 1, width, NUM_LAYERS, numProposals, numProposals))

                    for proposalIndex_1 in range(numProposals):
                        for proposalIndex_2 in range(numProposals):
                            for layer in range(NUM_LAYERS):
                                cv2.imwrite('test/cost_' + str(proposalIndex_1) + str(proposalIndex_2) + str(layer) + str(deltaIndex) + '.png', drawMaskImage(diff[:, :, layer, proposalIndex_1, proposalIndex_2]))
                                continue
                            continue
                        continue
                if deltaIndex == 1 and True:
                    #cv2.imwrite('test/segmentation.png', drawSegmentationImage(proposals[partial_nodes, 0, 1].reshape((height - 1, width))))
                    
                    #diff = (labelDiff * depthDiff).reshape((height, width - 1, NUM_LAYERS, numProposals, numProposals))
                    diff = (invisibleEmptyMask).reshape((height, width - 1, NUM_LAYERS, numProposals, numProposals))
                    #diff = (labelDiff).reshape((height - 1, width, NUM_LAYERS, numProposals, numProposals))

                    for proposalIndex_1 in range(numProposals):
                        for proposalIndex_2 in range(numProposals):
                            for layer in range(NUM_LAYERS):
                                cv2.imwrite('test/cost_' + str(proposalIndex_1) + str(proposalIndex_2) + str(layer) + str(deltaIndex) + '.png', drawMaskImage(diff[:, :, layer, proposalIndex_1, proposalIndex_2]))
                                continue
                            continue
                        continue
                    #exit(1)
                pass
            continue
        
        edges = np.concatenate(edges, axis=0)
        edges_features = np.concatenate(edges_features, axis=0)


        labelCost = True
        if labelCost and numProposals > 1:
            labelCosts = np.full(NUM_PLANES * NUM_LAYERS, numProposals, 10000)
            labelCosts[:, 0] = 0
            labelCosts[:, 1] = 1000
            unaries = np.concatenate([unaries, labelCosts], axis=0)

        solution, energy = inference_ogm(-unaries * 0.1, edges_features, edges, return_energy=True, alg='trw')
        print(energy)

        cv2.imwrite('test/solution_' + str(iteration) + '.png', drawSegmentationImage(solution.reshape((height, width))))
        
        solution = np.tile(solution.reshape([height * width, 1, 1]), [1, NUM_LAYERS, 1])
        solution = readProposalInfo(proposals, solution).reshape((height, width, NUM_LAYERS))

        np.save('test/solution_' + str(iteration) + '.npy', solution)
        continue
    
    return solution