def test_morphsnakes_incorrect_ndim():
    img = np.zeros((4, 4, 4, 4))
    ls = np.zeros((4, 4, 4, 4))

    with testing.raises(ValueError):
        morphological_chan_vese(img, iterations=1, init_level_set=ls)
    with testing.raises(ValueError):
        morphological_geodesic_active_contour(img, iterations=1,
                                              init_level_set=ls)
def test_morphsnakes_simple_shape_chan_vese():
    img = gaussian_blob()
    ls1 = circle_level_set(img.shape, (5, 5), 3)
    ls2 = circle_level_set(img.shape, (5, 5), 6)

    acwe_ls1 = morphological_chan_vese(img, iterations=10, init_level_set=ls1)
    acwe_ls2 = morphological_chan_vese(img, iterations=10, init_level_set=ls2)

    assert_array_equal(acwe_ls1, acwe_ls2)

    assert acwe_ls1.dtype == acwe_ls2.dtype == np.int8
Beispiel #3
0
def test_init_level_sets():
    image = np.zeros((6, 6))
    checkerboard_ls = morphological_chan_vese(image, 0, 'checkerboard')
    checkerboard_ref = np.array([[0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [1, 1, 1, 1, 1, 0]], dtype=np.int8)

    disk_ls = morphological_geodesic_active_contour(image, 0, 'disk')
    disk_ref = np.array([[0, 0, 0, 0, 0, 0],
                         [0, 0, 1, 1, 1, 0],
                         [0, 1, 1, 1, 1, 1],
                         [0, 1, 1, 1, 1, 1],
                         [0, 1, 1, 1, 1, 1],
                         [0, 0, 1, 1, 1, 0]], dtype=np.int8)

    assert_array_equal(checkerboard_ls, checkerboard_ref)
    assert_array_equal(disk_ls, disk_ref)
def test_init_level_sets():
    image = np.zeros((6, 6))
    checkerboard_ls = morphological_chan_vese(image, 0, 'checkerboard')
    checkerboard_ref = np.array([[0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [0, 0, 0, 0, 0, 1],
                                 [1, 1, 1, 1, 1, 0]], dtype=np.int8)

    circle_ls = morphological_geodesic_active_contour(image, 0, 'circle')
    circle_ref = np.array([[0, 0, 0, 0, 0, 0],
                           [0, 0, 1, 1, 1, 0],
                           [0, 1, 1, 1, 1, 1],
                           [0, 1, 1, 1, 1, 1],
                           [0, 1, 1, 1, 1, 1],
                           [0, 0, 1, 1, 1, 0]], dtype=np.int8)

    assert_array_equal(checkerboard_ls, checkerboard_ref)
    assert_array_equal(circle_ls, circle_ref)
def test_morphsnakes_3d():
    image = np.zeros((7, 7, 7))

    evolution = []

    def callback(x):
        evolution.append(x.sum())

    ls = morphological_chan_vese(image, 5, 'circle',
                                 iter_callback=callback)

    # Check that the initial circle level set is correct
    assert evolution[0] == 81

    # Check that the final level set is correct
    assert ls.sum() == 0

    # Check that the contour is shrinking at every iteration
    for v1, v2 in zip(evolution[:-1], evolution[1:]):
        assert v1 >= v2
def test_morphsnakes_3d():

    image = np.zeros((7, 7, 7))

    evolution = []

    def callback(x):
        evolution.append(x.sum())

    ls = morphological_chan_vese(image, 5, 'circle', iter_callback=callback)

    # Check that the initial circle level set is correct
    assert evolution[0] == 81

    # Check that the final level set is correct
    assert ls.sum() == 0

    # Check that the contour is shrinking at every iteration
    for v1, v2 in zip(evolution[:-1], evolution[1:]):
        assert v1 >= v2
def morphChaneVese(image, itr=120, p=3):
    """
        calculate the segmentation mask of the image using morphological_chan_vese built in function.
        Args:
            img: RGB image to calculate the segmentation mask over it.
            itr: number of iterations used to get the segmentation mask, default = 120.
            p: square width of the initial segmentation mask, default = 3.
        Returns:
            Binary image represents the filled object.
    """
    image = copy.deepcopy(image)
    #turn RGB image to gray scaled one.
    image = rgb2gray(image)
    #apply hestogram equalization to enhance the image.
    image = equalize_hist(image)
    #set the initial segmentation mask base on p value.
    init_ls = checkerboard_level_set(image.shape, p)
    #calculate the mask using morphological_chan_vese algorithm.
    mask = morphological_chan_vese(image, iterations=itr, init_level_set=init_ls, smoothing=2)
    #return the calculated mask
    return mask
def test_morphsnakes_black():
    img = np.zeros((11, 11))
    ls = circle_level_set(img.shape, (5, 5), 3)

    ref_zeros = np.zeros(img.shape, dtype=np.int8)
    ref_ones = np.ones(img.shape, dtype=np.int8)

    acwe_ls = morphological_chan_vese(img, iterations=6, init_level_set=ls)
    assert_array_equal(acwe_ls, ref_zeros)

    gac_ls = morphological_geodesic_active_contour(img, iterations=6,
                                                   init_level_set=ls)
    assert_array_equal(gac_ls, ref_zeros)

    gac_ls2 = morphological_geodesic_active_contour(img, iterations=6,
                                                    init_level_set=ls,
                                                    balloon=1, threshold=-1,
                                                    smoothing=0)
    assert_array_equal(gac_ls2, ref_ones)

    assert acwe_ls.dtype == gac_ls.dtype == gac_ls2.dtype == np.int8
Beispiel #9
0
def test_morphsnakes_black():
    img = np.zeros((11, 11))
    ls = disk_level_set(img.shape, center=(5, 5), radius=3)

    ref_zeros = np.zeros(img.shape, dtype=np.int8)
    ref_ones = np.ones(img.shape, dtype=np.int8)

    acwe_ls = morphological_chan_vese(img, num_iter=6, init_level_set=ls)
    assert_array_equal(acwe_ls, ref_zeros)

    gac_ls = morphological_geodesic_active_contour(img, num_iter=6,
                                                   init_level_set=ls)
    assert_array_equal(gac_ls, ref_zeros)

    gac_ls2 = morphological_geodesic_active_contour(img, num_iter=6,
                                                    init_level_set=ls,
                                                    balloon=1, threshold=-1,
                                                    smoothing=0)
    assert_array_equal(gac_ls2, ref_ones)

    assert acwe_ls.dtype == gac_ls.dtype == gac_ls2.dtype == np.int8
Beispiel #10
0
def segment_with_level_sets(img):
    """ Function to perform segmentation with level sets. img_gray should not contain hairs nor black zones

    Parameters
    ----------
    binary          Binary mask with result of level sets

    Returns
    -------
    output_image    Binary image with segmentation result

    """
    #First, find out if it is necessary to appy inpainting to remove black zones

    img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    r1 = img_gray[:5, :5]
    r2 = img_gray[:5, -5:]
    r3 = img_gray[-5:, :5]
    r4 = img_gray[-5:, -5:]

    if (np.mean(r1) < 50 or np.mean(r2) < 50 or np.mean(r3) < 50
            or np.mean(r4) < 50
        ):  #If zones of the corners are too dark, apply ellipse inpainting
        elliptical_mask = 1 - mask_eliptical(img_gray)
        to_process = cv.inpaint(img_gray, elliptical_mask, 21, cv.INPAINT_NS)
    else:
        to_process = img_gray

    init_ls = checkerboard_level_set(img_gray.shape, 6)

    ls = morphological_chan_vese(to_process,
                                 35,
                                 init_level_set=init_ls,
                                 smoothing=3)

    segmented = find_segmented(ls)

    return segmented
 def supercluster(self, clustered_data):
     #print ("clu data = ",clustered_data)
     gimage = inverse_gaussian_gradient(clustered_data, 10, 1.5)
     print("Fatto")
     # Initial level set
     # this makes alternate squares active at the first iteration of 10 macro-pixels
     #init_ls = checkerboard_level_set(clustered_data.shape, 10)
     init_ls = np.zeros(clustered_data.shape, dtype=np.int8)
     init_ls[10:-10, 10:-10] = 1
     # List with intermediate results for plotting the evolution
     #evolution = []
     #callback = self.store_evolution_in(evolution)
     #ls = morphological_geodesic_active_contour(gimage, 400, init_ls,
     #                                          smoothing=1, balloon=-1,
     #                                         threshold=0.6)
     #iter_callback=callback)
     ls = morphological_chan_vese(gimage,
                                  400,
                                  init_ls,
                                  smoothing=1,
                                  lambda1=8.,
                                  lambda2=10.)
     print("Bene!")
     return ls
def get_snake(file, plot=False):
    def store_evolution_in(lst):
        def _store(x):
            lst.append(np.copy(x))

        return _store

    evolution = []
    callback = store_evolution_in(evolution)
    raster_filepath = os.path.dirname(file) + "/"
    raster_filename = os.path.basename(file)
    with rasterio.open(file, driver='GTiff') as src:
        kwargs = src.meta
        kwargs.update(count=1, dtype=rasterio.uint8)
        input = src.read(1).astype(rasterio.uint8)
    if plot:
        plt.imshow(input, cmap='gray')
        plt.show()
    init_lvl_set = checkerboard_level_set(input.shape)
    lvl_set = morphological_chan_vese(input,
                                      100,
                                      init_level_set=init_lvl_set,
                                      iter_callback=callback,
                                      smoothing=1)
    if plot:
        plt.imshow(lvl_set, cmap='gray')
        plt.show()
    noise_reduced = morph_transform(lvl_set.astype(rasterio.uint8), 9, 9)
    if plot:
        plt.imshow(noise_reduced)
        plt.show()
    out_filename = raster_filepath + raster_filename.split(
        sep=".")[0] + "_chan_vese.tif"
    with rasterio.open(out_filename, 'w', **kwargs) as dst:
        dst.write_band(1, noise_reduced.astype(rasterio.uint8))
    return lvl_set
Beispiel #13
0
def create(imgg, Buffer, Buffer_images):
    img2 = cv2.cvtColor(imgg, cv2.COLOR_BGR2GRAY)
    # img2 = cv2.equalizeHist(img2)
    kp2, des2 = orb.detectAndCompute(img2, None)

    points = np.array([[[1, 1]]])
    for i in range(13):
        img1 = Buffer_images[i]
        ii = i

        kp1, des1 = orb.detectAndCompute(img1, None)
        matches1 = bf.match(des1, des2)
        matches1 = sorted(matches1, key=lambda x: x.distance)

        matches = matches1[:50]

        good_new = np.array([[[1, 1]]])
        good_old = np.array([[[1, 1]]])

        for i in range(0, len(matches)):
            # print('VLEZE VO TOCKI')
            x = np.float32(kp1[matches[i].queryIdx].pt[0])
            y = np.float32(kp1[matches[i].queryIdx].pt[1])
            good_new = np.append(good_new, [[[x, y]]], axis=0)

            x = np.float32(kp2[matches[i].trainIdx].pt[0])
            y = np.float32(kp2[matches[i].trainIdx].pt[1])
            good_old = np.append(good_old, [[[x, y]]], axis=0)

        good_new = np.delete(good_new, 0, 0)
        good_old = np.delete(good_old, 0, 0)
        try:
            M, mask = cv2.findHomography(good_old,
                                         good_new,
                                         cv2.RANSAC,
                                         ransacReprojThreshold=25)  # 15

            mask = np.array(mask, dtype=bool)
            mask = np.invert(mask)

            newX = np.ma.array(good_old, mask=np.column_stack((mask, mask)))

            newX = newX[~newX.mask]
            newX1 = newX.reshape(-1, 1, 2)
        except:
            print(ii)

        points = np.append(points, newX1, axis=0)
    points, index = np.unique(points, axis=0, return_index=True)

    new1 = points.reshape(-1, 2)

    dbscan = cluster.DBSCAN(eps=50, min_samples=20)

    X = new1

    dbscan.fit(X)

    if hasattr(dbscan, 'labels_'):
        y_pred = dbscan.labels_.astype(np.int)
    else:
        y_pred = dbscan.predict(X)

    # l1 = X[y_pred == 0, 0]
    l1 = np.asarray(X[y_pred == 0, 0], dtype=np.uint32)
    # l2 = X[y_pred == 0, 1]
    l2 = np.asarray(X[y_pred == 0, 1], dtype=np.uint32)

    ll1 = len(l1)
    ll2 = len(l2)
    if ll1 > 5 and ll1 > 5:

        points1 = np.asarray([l1, l2]).transpose()
        hull = ConvexHull(points1, incremental=True)

        polygon = []
        for x, y in points1[hull.vertices]:
            polygon.append((x, y))

        img = Image.new('L', (imgg.shape[1], imgg.shape[0]), 0)
        ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
        maskSNAKE = np.array(img)

        frame = imgg.copy()
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)  # YCR_CB)

        a = hsv[:, :, 0]
        image = img_as_float(a)

        init_ls = maskSNAKE
        ker = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
        init_ls = cv2.dilate(init_ls, ker, iterations=1)

        evolution = []
        callback = store_evolution_in(evolution)

        ls1 = morphological_chan_vese(image,
                                      20,
                                      init_level_set=init_ls,
                                      lambda1=2,
                                      lambda2=0.4,
                                      smoothing=0,
                                      iter_callback=callback)

        # ls1 = ls
        ls = ls1.astype(np.uint8)
        kernel = np.ones((16, 16), np.uint8)
        kernel1 = np.ones((8, 8), np.uint8)
        erosion = cv2.morphologyEx(ls, cv2.MORPH_OPEN, kernel)
        erosion = cv2.erode(erosion, kernel1, iterations=1)

        # img1 = Image.fromarray(imgg, 'RGB')

        _, contours, hierarchy = cv2.findContours(
            erosion, cv2.RETR_EXTERNAL,
            cv2.CHAIN_APPROX_TC89_L1)  # contours, hierarchy

        su1 = 0
        su2 = 0

        # needs to be restructured from here
        if len(contours) > 0:
            img_true = np.array(ls1).ravel()
            img_pred = np.array(erosion).ravel()
            iou = jaccard_similarity_score(
                img_true, img_pred)  # jaccard_score(img_true, img_pred)
            print('ENTERED CONTOURS')
            a = sorted(contours,
                       key=lambda contour: cv2.contourArea(contour),
                       reverse=True)
            # print(a)
            # print(cv2.contourArea(a[0]))
            maxContour = cv2.contourArea(a[0])
            maxContourData = a[0]
            mask = np.zeros_like(erosion)
            if maxContour > 1:
                cv2.fillPoly(mask, [maxContourData], 1)
                su1 = sum(mask[(l2, l1)])
        else:
            iou = None

        if len(contours) > 1:
            maxContour1 = cv2.contourArea(a[1])
            maxContourData1 = a[1]
            mask1 = np.zeros_like(erosion)

            if maxContour1 > 1:
                cv2.fillPoly(mask1, [maxContourData1], 1)
                su2 = sum(mask1[(l2, l1)])

        if su1 >= su2 and su1 > 20:
            c = maxContourData
            c = c.astype(np.float32)
        elif su2 >= su1 and su2 > 20:
            c = maxContourData1
            c = c.astype(np.float32)
        else:
            c = None
        # to here

        # template = img2

        if c is not None:
            maxx = np.int0(np.amax(c[:, 0, 0]))
            minx = np.int0(np.amin(c[:, 0, 0]))
            maxy = np.int0(np.amax(c[:, 0, 1]))
            miny = np.int0(np.amin(c[:, 0, 1]))

            template = img2 * maskSNAKE
            template = template[miny:maxy, minx:maxx]

            clusterSize = ll1

            kp3, des3 = orb.detectAndCompute(template, None)
            # Sum of strongest 20
            pp = sorted(kp3, key=operator.attrgetter('response'), reverse=True)
            sum3 = sum(node.response for node in pp[:20])
            if len(kp3) > 20:
                pp = sorted(kp3,
                            key=operator.attrgetter('response'),
                            reverse=True)
                sum3 = sum(node.response for node in pp[:20])
                if ll1 > 0.9 * Buffer["7"][2]:
                    n = 7
                    name = 'b' + str(n) + '.jpg'
                    cv2.imwrite(name, template)
                    Buffer_images[n] = template
                    Buffer[str(n)] = [len(kp3), sum3, clusterSize]

                elif ll1 > 0.8 * Buffer["8"][2]:
                    n = 8
                    name = 'b' + str(n) + '.jpg'
                    cv2.imwrite(name, template)
                    Buffer_images[n] = template
                    Buffer[str(n)] = [len(kp3), sum3, clusterSize]

                elif ll1 > 0.7 * Buffer["9"][2]:
                    n = 9
                    name = 'b' + str(n) + '.jpg'
                    cv2.imwrite(name, template)
                    Buffer_images[n] = template
                    Buffer[str(n)] = [len(kp3), sum3, clusterSize]

        else:
            clusterSize = 0

        return c, iou, Buffer, Buffer_images
    else:
        c = None
        iou = None
        return c, iou, Buffer, Buffer_images
Beispiel #14
0
def coreSegmenterOutput(I, probMap, initialmask, preBlur, findCenter):
    hsize = int((float(I.shape[0]) * float(0.1)))
    vsize = int((float(I.shape[1]) * float(0.1)))
    nucGF = cv2.resize(I, (vsize, hsize), cv2.INTER_CUBIC)
    #	Irs = cv2.resize(I,(vsize,hsize),cv2.INTER_CUBIC)
    #	I=I.astype(np.float)
    #	r,c = I.shape
    #	I+=np.random.rand(r,c)*1e-6
    #	c1 = uniform_filter(I, 3, mode='reflect')
    #	c2 = uniform_filter(I*I, 3, mode='reflect')
    #	nucGF = np.sqrt(c2 - c1*c1)*np.sqrt(9./8)
    #	nucGF[np.isnan(nucGF)]=0
    #active contours
    hsize = int(float(nucGF.shape[0]))
    vsize = int(float(nucGF.shape[1]))
    initialmask = cv2.resize(initialmask, (vsize, hsize), cv2.INTER_NEAREST)
    initialmask = dilation(initialmask, disk(15)) > 0

    #	init=np.argwhere(eroded>0)
    nucGF = gaussian(nucGF, 0.7)
    nucGF = nucGF / np.amax(nucGF)

    #	initialmask = nucGF>0
    nuclearMask = morphological_chan_vese(nucGF,
                                          100,
                                          init_level_set=initialmask,
                                          smoothing=10,
                                          lambda1=1.001,
                                          lambda2=1)

    #	nuclearMask = chan_vese(nucGF, mu=1.5, lambda1=6, lambda2=1, tol=0.0005, max_iter=2000, dt=15, init_level_set=initialmask, extended_output=True)
    #	nuclearMask = nuclearMask[0]

    TMAmask = nuclearMask
    #	nMaskDist =distance_transform_edt(nuclearMask)
    #	fgm = peak_local_max(h_maxima(nMaskDist, 2*preBlur),indices =False)
    #	markers= np.logical_or(erosion(1-nuclearMask,disk(3)),fgm)
    #	TMAmask=watershed(-nMaskDist,label(markers),watershed_line=True)
    #	TMAmask = nuclearMask*(TMAmask>0)
    TMAmask = remove_small_objects(
        TMAmask > 0,
        round(TMAmask.shape[0]) * round(TMAmask.shape[1]) * 0.005)
    TMAlabel = label(TMAmask)
    # find object closest to center
    if findCenter == True:

        stats = regionprops(TMAlabel)
        counter = 1
        minDistance = -1
        index = []
        for props in stats:
            centroid = props.centroid
            distanceFromCenter = np.sqrt((centroid[0] -
                                          nucGF.shape[0] / 2)**2 +
                                         (centroid[1] - nucGF.shape[1] / 2)**2)
            #		if distanceFromCenter<0.6/2*np.sqrt(TMAlabel.shape[0]*TMAlabel.shape[1]):
            if distanceFromCenter < minDistance or minDistance == -1:
                minDistance = distanceFromCenter
                index = counter
            counter = counter + 1
    #		dist = 0.6/2*np.sqrt(TMAlabel.shape[0]*TMAlabel.shape[1])
        TMAmask = morphology.binary_closing(TMAlabel == index, disk(3))

    return TMAmask
Beispiel #15
0
# Morphological ACWE
#image = img_as_float(data.camera())
from skimage import io
file_name = 'test3.dcm'
image = io.imread(file_name)

# Initial level set
init_ls = checkerboard_level_set(image.shape, 6)
# List with intermediate results for plotting the evolution
evolution = []
callback = store_evolution_in(evolution)
iteracoes = 35
ls = morphological_chan_vese(image,
                             iteracoes,
                             init_level_set=init_ls,
                             smoothing=1,
                             iter_callback=callback)

fig, axes = plt.subplots(2, 2, figsize=(8, 8))
ax = axes.flatten()

ax[0].imshow(image, cmap="gray")
ax[0].set_axis_off()
ax[0].contour(ls, [0.5], colors='r')
ax[0].set_title("Morphological ACWE segmentation", fontsize=12)

ax[1].imshow(ls, cmap="gray")
ax[1].set_axis_off()
contour = ax[1].contour(evolution[2], [0.5], colors='g')
contour.collections[0].set_label("Iteration 2")
Beispiel #16
0
def active_contour(image):
    def store_evolution_in(lst):
        
        def _store(x):
            lst.append(np.copy(x))
    
        return _store
    
    image = img_as_float(data.camera())
    
    init_ls = checkerboard_level_set(image.shape, 6)
    
    evolution = []
    callback = store_evolution_in(evolution)
    ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=3,
                                 iter_callback=callback)
    
    fig, axes = plt.subplots(2, 2, figsize=(8, 8))
    ax = axes.flatten()
    
    ax[0].imshow(image, cmap="gray")
    ax[0].set_axis_off()
    ax[0].contour(ls, [0.5], colors='r')
    ax[0].set_title("Morphological ACWE segmentation", fontsize=12)
    
    ax[1].imshow(ls, cmap="gray")
    ax[1].set_axis_off()
    contour = ax[1].contour(evolution[2], [0.5], colors='g')
    contour.collections[0].set_label("Iteration 2")
    contour = ax[1].contour(evolution[7], [0.5], colors='y')
    contour.collections[0].set_label("Iteration 7")
    contour = ax[1].contour(evolution[-1], [0.5], colors='r')
    contour.collections[0].set_label("Iteration 35")
    ax[1].legend(loc="upper right")
    title = "Morphological ACWE evolution"
    ax[1].set_title(title, fontsize=12)
    
    
    
    image = img_as_float(data.coins())
    gimage = inverse_gaussian_gradient(image)
    
    
    init_ls = np.zeros(image.shape, dtype=np.int8)
    init_ls[10:-10, 10:-10] = 1
    
    evolution = []
    callback = store_evolution_in(evolution)
    ls = morphological_geodesic_active_contour(gimage, 230, init_ls,
                                               smoothing=1, balloon=-1,
                                               threshold=0.69,
                                               iter_callback=callback)
    
    ax[2].imshow(image, cmap="gray")
    ax[2].set_axis_off()
    ax[2].contour(ls, [0.5], colors='r')
    ax[2].set_title("Morphological GAC segmentation", fontsize=12)
    
    ax[3].imshow(ls, cmap="gray")
    ax[3].set_axis_off()
    contour = ax[3].contour(evolution[0], [0.5], colors='g')
    contour.collections[0].set_label("Iteration 0")
    contour = ax[3].contour(evolution[100], [0.5], colors='y')
    contour.collections[0].set_label("Iteration 100")
    contour = ax[3].contour(evolution[-1], [0.5], colors='r')
    contour.collections[0].set_label("Iteration 230")
    ax[3].legend(loc="upper right")
    title = "Morphological GAC evolution"
    ax[3].set_title(title, fontsize=12)
    
    fig.tight_layout()
    plt.show()
Beispiel #17
0
def morphological(image):

    # Morphological ACWE
    img = img_as_float(skimage.color.rgb2gray(image))
    # Initial level set
    init_ls = checkerboard_level_set(img.shape, 6)
    # List with intermediate results for plotting the evolution
    evolution = []
    callback = store_evolution_in(evolution)
    ls = morphological_chan_vese(img,
                                 200,
                                 init_level_set=init_ls,
                                 smoothing=4,
                                 iter_callback=callback)

    fig, axes = plt.subplots(2, 2, figsize=(8, 8))
    ax = axes.flatten()

    ax[0].imshow(img, cmap="gray")
    ax[0].set_axis_off()
    ax[0].contour(ls, [0.5], colors='r')
    ax[0].set_title("Morphological ACWE segmentation", fontsize=12)

    ax[1].imshow(ls, cmap="gray")
    ax[1].set_axis_off()
    contour = ax[1].contour(evolution[2], [0.5], colors='g')
    contour.collections[0].set_label("Iteration 2")
    contour = ax[1].contour(evolution[7], [0.5], colors='y')
    contour.collections[0].set_label("Iteration 7")
    contour = ax[1].contour(evolution[-1], [0.5], colors='r')
    contour.collections[0].set_label("Iteration 35")
    ax[1].legend(loc="upper right")
    title = "Morphological ACWE evolution"
    ax[1].set_title(title, fontsize=12)

    # Morphological GAC
    img = img_as_float(skimage.color.rgb2gray(image))
    gimage = inverse_gaussian_gradient(img)

    # Initial level set
    init_ls = np.zeros(img.shape, dtype=np.int8)
    init_ls[10:-10, 10:-10] = 1
    # List with intermediate results for plotting the evolution
    evolution = []
    callback = store_evolution_in(evolution)
    ls = morphological_geodesic_active_contour(gimage,
                                               230,
                                               init_ls,
                                               smoothing=5,
                                               balloon=-1,
                                               threshold=0.5,
                                               iter_callback=callback)

    ax[2].imshow(img, cmap="gray")
    ax[2].set_axis_off()
    ax[2].contour(ls, [0.5], colors='r')
    ax[2].set_title("Morphological GAC segmentation", fontsize=12)

    ax[3].imshow(ls, cmap="gray")
    ax[3].set_axis_off()
    contour = ax[3].contour(evolution[0], [0.5], colors='g')
    contour.collections[0].set_label("Iteration 0")
    contour = ax[3].contour(evolution[100], [0.5], colors='y')
    contour.collections[0].set_label("Iteration 100")
    contour = ax[3].contour(evolution[-1], [0.5], colors='r')
    contour.collections[0].set_label("Iteration 230")
    ax[3].legend(loc="upper right")
    title = "Morphological GAC evolution"
    ax[3].set_title(img, fontsize=12)

    fig.tight_layout()
    plt.show()
Beispiel #18
0
    def run(self):
        self.beginTaskRun()

        # Get input 0 :
        input = self.getInput(0)

        # Get output :
        output = self.getOutput(0)

        # Get parameters :
        param = self.getParam()

        # Get image from input/output (numpy array):
        srcImage = input.getImage()

        # Convert to grey Image if RGB
        if len(srcImage.shape) == 3:
            image = cv2.cvtColor(srcImage, cv2.COLOR_RGB2GRAY)
        else:
            image = srcImage

        # Convert to float
        imagef = img_as_float(image)

        # enhances borders
        if param.mgac_amplification_contour == "Inverse gaussian gradient":
            gimage = inverse_gaussian_gradient(imagef)
        else:
            gimage = imagef

        # initial level set
        initlevelSetInput = self.getInput(2)
        if initlevelSetInput.isDataAvailable():
            initlevelSetBinary = initlevelSetInput.getImage()
            if param.method == "mgac":
                proc_img = morphological_geodesic_active_contour(
                    gimage,
                    param.mgac_iterations,
                    init_level_set=initlevelSetBinary,
                    smoothing=param.mgac_smoothing,
                    threshold=param.mgac_threshold,
                    balloon=param.mgac_balloon,
                    iter_callback=(lambda callback: self.emitStepProgress()
                                   )).astype(np.uint8) * 255
            else:
                proc_img = morphological_chan_vese(
                    gimage,
                    param.mcv_iterations,
                    init_level_set=initlevelSetBinary,
                    smoothing=param.mcv_smoothing,
                    lambda1=param.mcv_lambda1,
                    lambda2=param.mcv_lambda2,
                    iter_callback=(lambda callback: self.emitStepProgress()
                                   )).astype(np.uint8) * 255
        else:
            # input graph -> by user / by previous aoperation in worflow
            graphInput = self.getInput(1)
            if graphInput.isDataAvailable():
                self.createGraphicsMask(imagef.shape[1], imagef.shape[0],
                                        graphInput)
                binImg = self.getGraphicsMask(0)
                if param.method == "mgac":
                    proc_img = morphological_geodesic_active_contour(
                        gimage,
                        param.mgac_iterations,
                        init_level_set=binImg,
                        smoothing=param.mgac_smoothing,
                        threshold=param.mgac_threshold,
                        balloon=param.mgac_balloon,
                        iter_callback=(
                            lambda callback: self.emitStepProgress())).astype(
                                np.uint8) * 255
                else:
                    proc_img = morphological_chan_vese(
                        gimage,
                        param.mcv_iterations,
                        init_level_set=binImg,
                        smoothing=param.mcv_smoothing,
                        lambda1=param.mcv_lambda1,
                        lambda2=param.mcv_lambda2,
                        iter_callback=(
                            lambda callback: self.emitStepProgress())).astype(
                                np.uint8) * 255
            else:
                raise Exception(
                    "No initial level-set given: it must be graphics input or binary image."
                )

        # set output mask binary image
        output.setImage(proc_img)

        # add foward input image
        self.forwardInputImage(0, 1)

        # Call endTaskRun to finalize process
        self.endTaskRun()
Beispiel #19
0

I = pydicom.dcmread('000001.dcm')
I = I.pixel_array
x = I.copy()
y = x.resize((256, 256))
max = np.amax(I)
sigma = 0.08
sigma_est = np.mean(estimate_sigma(I, multichannel=False))
patch_kw = dict(patch_size=5, patch_distance=6, multichannel=False)
I = denoise_nl_means(I, h=1.15 * sigma_est, fast_mode=False, **patch_kw)
image = np.copy(I)
print(image[10, 10])
print(image[100, 150])
print(np.amax(image[50, 190:210]))
print(np.amax(image))
max = np.amax(image)
eimage = (image * 255 / max)**5
#eimage = image ** (3)
init_ls = checkerboard_level_set(image.shape, 6)
evolution = []
callback = store_evolution_in(evolution)
ls = morphological_chan_vese(eimage,
                             35,
                             init_level_set=init_ls,
                             smoothing=3,
                             iter_callback=callback)

plt.imshow(image, cmap=plt.cm.bone)
plt.contour(ls, [0.5], colors='r')
plt.show()
Beispiel #20
0
    def execute(self, arg, trans):
        # Number of Chan-Vese iterations
        nIter = 20
        std = 1.5  # [mm], original
        squareSize = 1.5  # [mm]

        saveMetaImage = False
        savePNGImage = False
        # Actual work - now done using SciPy

        # Gaussian smoothing
        dx, dy, dz = arg.GetSpacing()
        sx, sy = std / dx, std / dy
        smoother = vtk.vtkImageGaussianSmooth()
        smoother.SetStandardDeviations(sx, sy)
        smoother.SetDimensionality(2)
        smoother.SetInputData(arg)
        smoother.Update()

        if savePNGImage:
            writer = vtk.vtkPNGWriter()
            writer.SetFileName('./output.png')
            writer.SetInputConnection(smoother.GetOutputPort())
            writer.Write()

        if saveMetaImage:
            # Save to disk
            writer = vtk.vtkMetaImageWriter()
            writer.SetFileName('./output.mhd')
            writer.SetInputConnection(smoother.GetOutputPort())
            writer.Write()

        smoothedData = smoother.GetOutput()

        # Convert VTK to NumPy image
        dims = arg.GetDimensions()
        vtk_array = smoothedData.GetPointData().GetScalars()
        nComponents = vtk_array.GetNumberOfComponents()
        npData = vtk_to_numpy(vtk_array).reshape(
            dims[2], dims[1], dims[0],
            nComponents)[:, :, :, 0].reshape(dims[1], dims[0])

        # Seed for active contours
        iSquareSize = int(squareSize / dx)
        init_ls = checkerboard_level_set(npData.shape, iSquareSize)

        contours = morphological_chan_vese(npData,
                                           nIter,
                                           init_level_set=init_ls,
                                           smoothing=2)
        # Add singleton to get 3-dimensional data
        data = contours[None, :]

        # Convert Numpy to VTK data
        importer = vtk.vtkImageImport()
        importer.SetDataScalarType(vtk.VTK_SIGNED_CHAR)
        importer.SetDataExtent(0, data.shape[2] - 1, 0, data.shape[1] - 1, 0,
                               data.shape[0] - 1)
        importer.SetWholeExtent(0, data.shape[2] - 1, 0, data.shape[1] - 1, 0,
                                data.shape[0] - 1)
        importer.SetImportVoidPointer(data.data)
        importer.Update()
        vtkData = importer.GetOutput()
        vtkData.SetSpacing(smoothedData.GetSpacing())
        vtkData.SetOrigin(0, 0, 0)

        # Contour filter
        contourFilter = vtk.vtkContourFilter()
        iso_value = 0.5
        contourFilter.SetInputData(vtkData)
        contourFilter.SetValue(0, iso_value)
        contourFilter.Update()
        contourFilter.ReleaseDataFlagOn()

        # Compute normals
        normals = vtk.vtkPolyDataNormals()
        normals.SetInputConnection(contourFilter.GetOutputPort())
        normals.SetFeatureAngle(60.0)
        normals.ReleaseDataFlagOn()

        # Join line segments
        stripper = vtk.vtkStripper()
        stripper.SetInputConnection(normals.GetOutputPort())
        stripper.ReleaseDataFlagOn()
        stripper.Update()

        # Transform data from scaled screen to world coordinates
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetInputConnection(stripper.GetOutputPort())
        transformFilter.SetTransform(trans)
        transformFilter.Update()
        result = transformFilter.GetOutput()

        # Emit done with output
        self.done.emit(result)
Beispiel #21
0
def segment_lesion(image, mode="KMeans"):
    ## Unsupervised Segmentation
    # K-Means Clustering
    if (mode == "KMeans"):
        # K-Means Clustering
        deim = denoise(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), weight=150)
        kmeans = KMeans(n_clusters=2, random_state=0,
                        n_jobs=-1).fit(deim.reshape(-1, 1))
        mask = (kmeans.labels_).reshape(deim.shape[0],
                                        deim.shape[1]).astype('uint8')

    # Expectation-Maximization Gaussian Mixture Model
    elif (mode == "EM"):
        # K-Means Clustering
        feature_vector = (denoise(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY),
                                  weight=150)).reshape(-1, 1)
        kmeans = KMeans(n_clusters=2, random_state=0,
                        n_jobs=-1).fit(feature_vector)
        KMpredict = kmeans.predict(feature_vector)

        # Expectation Step: Initialization with K-Means
        KM_BG = feature_vector[KMpredict == 0]
        KM_FG = feature_vector[KMpredict == 1]

        # Expectation Step: Mean and Covariance
        mean_BG = np.mean(KM_BG, axis=0)
        mean_FG = np.mean(KM_FG, axis=0)
        covar_BG = np.cov(KM_BG, rowvar=False)
        covar_FG = np.cov(KM_FG, rowvar=False)

        # Expectation Step: Prior Probabilities
        prob_BG = KM_BG.shape[0] / feature_vector.shape[0]
        prob_FG = KM_FG.shape[0] / feature_vector.shape[0]

        # Iterative Update
        min_change = 0.01
        max_steps = 5

        for i in range(max_steps):
            # Expectation Step: Probability Density Function
            PDF_BG = multivariate_normal.pdf(feature_vector,
                                             mean=mean_BG,
                                             cov=covar_BG)
            PDF_FG = multivariate_normal.pdf(feature_vector,
                                             mean=mean_FG,
                                             cov=covar_FG)
            weights_BG = (prob_BG * PDF_BG) / ((prob_FG * PDF_FG) +
                                               (prob_BG * PDF_BG))
            weights_FG = (prob_FG * PDF_FG) / ((prob_FG * PDF_FG) +
                                               (prob_BG * PDF_BG))
            weights = np.concatenate(
                (weights_BG.reshape(-1, 1), weights_FG.reshape(-1, 1)), axis=1)
            log_B = sum((np.log(sum(weights))))

            # Maximization Step: New Probabilities
            _, counts = np.unique(np.argmax(weights, axis=1),
                                  return_counts=True)
            prob_BG = counts[0] / feature_vector.shape[0]
            prob_FG = counts[1] / feature_vector.shape[0]

            # Maximization Step: New Mean and Covariance
            mean_BG = (1 / counts[0]) * (weights[:, 0] @ feature_vector)
            mean_FG = (1 / counts[1]) * (weights[:, 1] @ feature_vector)
            covar_BG = (1 / counts[0]) * (
                weights[:, 0] * np.transpose(feature_vector - mean_BG)) @ (
                    feature_vector - mean_BG)
            covar_FG = (1 / counts[1]) * (
                weights[:, 1] * np.transpose(feature_vector - mean_FG)) @ (
                    feature_vector - mean_FG)

            # Maximization Step: Probability Density Function
            PDF_BG = multivariate_normal.pdf(feature_vector,
                                             mean=mean_BG,
                                             cov=covar_BG)
            PDF_FG = multivariate_normal.pdf(feature_vector,
                                             mean=mean_FG,
                                             cov=covar_FG)
            weights_BG = (prob_BG * PDF_BG) / ((prob_FG * PDF_FG) +
                                               (prob_BG * PDF_BG))
            weights_FG = (prob_FG * PDF_FG) / ((prob_FG * PDF_FG) +
                                               (prob_BG * PDF_BG))
            weights = np.concatenate(
                (weights_BG.reshape(-1, 1), weights_FG.reshape(-1, 1)), axis=1)
            log_N = sum((np.log(sum(weights))))

            # Update Trackers, Verify Conditions
            change_log = np.linalg.norm(log_N - log_B)
            if (change_log <= min_change):
                continue
            else:
                break

        # Output Image Reconstruction
        mask = (np.argmax(weights, axis=1)).reshape(-1, 1)
        mask = np.reshape(mask,
                          (image.shape[0], image.shape[1])).astype('uint8')

    # Chan-Vese Active Contours
    elif (mode == "active_contours"):
        # Morphological ACWE
        image = img_as_float(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY))

        # Initial level Set
        init_ls = checkerboard_level_set(image.shape, 6)

        # List with Intermediate Results for Plotting the Evolution
        evolution = []
        callback = store_evolution_in(evolution)
        mask = morphological_chan_vese(image,
                                       5,
                                       init_level_set=init_ls,
                                       smoothing=10,
                                       iter_callback=callback).astype(np.uint8)

    # Watershed
    elif (mode == "mod_watershed"):

        ret, thresh = cv2.threshold(cv2.cvtColor(image,
                                                 cv2.COLOR_RGB2GRAY), 0, 255,
                                    cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
        kernel = np.ones((3, 3), np.uint8)
        opening = cv2.morphologyEx(thresh,
                                   cv2.MORPH_OPEN,
                                   kernel,
                                   iterations=2)

        sure_bg = cv2.dilate(opening, kernel, iterations=3)
        dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
        ret, sure_fg = cv2.threshold(dist_transform,
                                     0.01 * dist_transform.max(), 255, 0)

        ls = np.uint8(sure_fg) / 255
        circle_mask = create_circular_mask(image.shape[0],
                                           image.shape[1],
                                           radius=220)
        ls = ls * circle_mask

        # Discard Edge-to-Edge Connected Component
        large = getLargestCC(ls).astype(np.uint8)
        if (corner_mean(large) > 1):
            large = getLargestCC(ls - large).astype(np.uint8)

        # Post-Process Masks
        post = ndimage.binary_fill_holes(large, structure=np.ones(
            (5, 5))).astype(bool)

    else:
        print("ERROR: Undefined Segmentation Mode")

    ## Segmentation Label Selection
    # Define Target Scope
    candidate_mask_1 = mask.copy() * create_circular_mask(
        image.shape[0], image.shape[1], radius=230)
    candidate_mask_2 = (np.invert(mask.copy()) + 2) * create_circular_mask(
        image.shape[0], image.shape[1], radius=230)

    # Compute Area of Convex Hulls
    convex_hull_1 = convex_hull_image(candidate_mask_1)
    convex_hull_2 = convex_hull_image(candidate_mask_2)

    # Set Segmentation Component Labels
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
    if (np.sum(convex_hull_1) < np.sum(convex_hull_2)):
        dilation = cv2.dilate(candidate_mask_1, kernel, iterations=1)
        mask = ndimage.binary_fill_holes(dilation, structure=np.ones((5, 5)))
    else:
        dilation = cv2.dilate(candidate_mask_2, kernel, iterations=1)
        mask = ndimage.binary_fill_holes(dilation, structure=np.ones((5, 5)))
    if (np.sum(mask) < 5000):
        mask = create_circular_mask(image.shape[0], image.shape[1], radius=230)
    return mask
    def _store(x):
        lst.append(np.copy(x))

    return _store


# Morphological ACWE
image = img_as_float(data.camera())

# Initial level set
init_ls = checkerboard_level_set(image.shape, 6)
# List with intermediate results for plotting the evolution
evolution = []
callback = store_evolution_in(evolution)
ls = morphological_chan_vese(image, 35, init_level_set=init_ls, smoothing=3,
                             iter_callback=callback)

fig, axes = plt.subplots(2, 2, figsize=(8, 8))
ax = axes.flatten()

ax[0].imshow(image, cmap="gray")
ax[0].set_axis_off()
ax[0].contour(ls, [0.5], colors='r')
ax[0].set_title("Morphological ACWE segmentation", fontsize=12)

ax[1].imshow(ls, cmap="gray")
ax[1].set_axis_off()
contour = ax[1].contour(evolution[2], [0.5], colors='g')
contour.collections[0].set_label("Iteration 2")
contour = ax[1].contour(evolution[7], [0.5], colors='y')
contour.collections[0].set_label("Iteration 7")
Beispiel #23
0
    def action_active_contour(self, label, min_pixels=20, iterations=100):
        label_img = np.copy(self.frame[..., self.feature])

        # get centroid of selected label
        props = regionprops(np.where(label_img == label, label, 0))[0]

        # make bounding box size to encompass some background
        box_height = props['bbox'][2] - props['bbox'][0]
        y1 = max(0, props['bbox'][0] - box_height // 2)
        y2 = min(self.project.height, props['bbox'][2] + box_height // 2)

        box_width = props['bbox'][3] - props['bbox'][1]
        x1 = max(0, props['bbox'][1] - box_width // 2)
        x2 = min(self.project.width, props['bbox'][3] + box_width // 2)

        # relevant region of label image to work on
        label_img = label_img[y1:y2, x1:x2]

        # use existing label as initial level set for contour calculations
        level_set = np.where(label_img == label, 1, 0)

        # normalize input 2D frame data values to range [0.0, 1.0]
        adjusted_raw_frame = Normalize()(self.raw_frame[..., self.channel])
        predict_area = adjusted_raw_frame[y1:y2, x1:x2]

        # returns 1 where label is predicted to be based on contouring, 0 background
        contoured = morphological_chan_vese(
            predict_area, iterations, init_level_set=level_set
        )

        # contoured area should get original label value
        contoured_label = contoured * label
        # contours tend to fit very tightly, a small expansion here works well
        contoured_label = dilation(contoured_label, disk(3))

        # don't want to leave the original (un-contoured) label in the image
        # never overwrite other labels with new contoured label
        cond = np.logical_or(label_img == label, label_img == 0)
        safe_overlay = np.where(cond, contoured_label, label_img)

        # label must be present in safe_overlay for this to be a valid contour result
        # very few pixels of contoured label indicate contour prediction not worth keeping
        pixel_count = np.count_nonzero(safe_overlay == label)
        if pixel_count < min_pixels:
            safe_overlay = np.copy(self.frame[y1:y2, x1:x2, self.feature])

        # put it back in the full image so can use centroid coords for post-contour cleanup
        full_frame = np.copy(self.frame[..., self.feature])
        full_frame[y1:y2, x1:x2] = safe_overlay

        # avoid automated label cleanup if centroid (flood seed point) is not the right label
        if full_frame[int(props['centroid'][0]), int(props['centroid'][1])] != label:
            img_trimmed = full_frame
        else:
            # morphology and logic used by pixel-trimming action, with object centroid as seed
            contig_cell = flood(
                image=full_frame,
                seed_point=(int(props['centroid'][0]), int(props['centroid'][1])),
            )

            # any pixels in img_ann that have value 'label' and are NOT connected to
            # hole_fill_seed get changed to 0, all other pixels retain their original value
            img_trimmed = np.where(
                np.logical_and(np.invert(contig_cell), full_frame == label),
                0,
                full_frame,
            )

        # update image; cell_info should never change as a result of this
        self.frame[y1:y2, x1:x2, self.feature] = img_trimmed[y1:y2, x1:x2]
        self.y_changed = True
#init = np.array([r, c]).T

smoothed_img = gaussian(img_gray, 4)
snake = active_contour(smoothed_img,
                       biggest_contour,
                       alpha=0.001,
                       beta=20,
                       gamma=0.001,
                       w_edge=0)

gimage = inverse_gaussian_gradient(img)
evolution = []
#callback = store_evolution_in(evolution)
ls = morphological_chan_vese(gimage,
                             230,
                             'circle',
                             smoothing=3,
                             lambda1=1,
                             lambda2=1)

for i in ls:
    #   print(i)
    img[i[0]][i[1]] = 255

fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(img, cmap=plt.cm.gray)
ax.plot(snake[:, 1], snake[:, 0], '-r', lw=2)
ax.contour(ls, [0.5], colors='b')
ax.set_xticks([]), ax.set_yticks([])
ax.axis([0, img.shape[1], img.shape[0], 0])

plt.show()
Beispiel #25
0
    def process(self, args, sigma=0.8, iterations=25, writeback=False):
        """
        use expansive active contours to transform point geometries into best-fit boundary polygons demarking object footprints
        """

        # open centroid shape file
        centroid = self.openCentroidFile(args.centroid_pathname)

        # open image file
        image = self.openImageFile(args.image_pathname)

        # create footprint shape file
        footprint = self.createOutputFile(args.out_pathname, image)

        # check validity of files
        if centroid is not None and image is not None and footprint is not None:

            # convert centroid locations to pixel coordinates
            coords = self.getCentroidImageCoordinates(centroid, image)
            # random.shuffle( coords )

            # for each x, y centroid location
            for idx, coord in enumerate(coords):

                # check valid sub-image
                if coord[0] + self._object_size < image[
                        'ds'].RasterXSize and coord[
                            1] + self._object_size < image['ds'].RasterYSize:

                    # extract sub-image - check for error
                    sub_image = image['band'].ReadAsArray(
                        coord[0], coord[1], self._object_size,
                        self._object_size)
                    sub_image = gaussian_filter(sub_image, sigma=sigma)
                    sub_image = sub_image / (2 ^ 16 - 1)

                    # define initial state of active contour
                    init_ls = circle_level_set(
                        sub_image.shape,
                        (self._object_halfsize, self._object_halfsize), 5)

                    if writeback is True:

                        # callback for animation
                        ls = morphological_chan_vese(
                            sub_image,
                            iterations=iterations,
                            init_level_set=init_ls,
                            smoothing=1,
                            lambda1=1,
                            lambda2=1,
                            iter_callback=self.visualCallback(sub_image))

                    else:

                        # callback for animation
                        ls = morphological_chan_vese(sub_image,
                                                     iterations=iterations,
                                                     init_level_set=init_ls,
                                                     smoothing=1,
                                                     lambda1=1,
                                                     lambda2=1)

                    # compute simplified polygon
                    polyline = self.getPolyline(ls)

                    # convert polyline to geometry
                    wkt = self.getGeometry(polyline, coord, image['transform'])

                    # create new polygon feature
                    feature = ogr.Feature(footprint['defn'])
                    feature.SetField('id', idx)
                    feature.SetGeometry(ogr.CreateGeometryFromWkt(wkt))

                    # add feature
                    footprint['layer'].CreateFeature(feature)
                    feature = None

                    # create animated gif
                    if idx == 5 and writeback:
                        imageio.mimsave(
                            'C:\\Users\\Chris.Williams\\Desktop\\animate.gif',
                            self._images,
                            fps=5,
                            palettesize=64,
                            subrectangles=True)
                        break

            # delete variables to force write
            footprint['layer'] = None
            footprint['ds'] = None

        # buffer up footprint polygons by 3 metres
        self.getBufferedPolygons(args.out_pathname, 3)

        return
def edge_segmentation(img,
                      strength_threshold=8,
                      coherence_threshold=0.5,
                      mode=4,
                      ch_ethreshold=0.8,
                      ws_ethreshold=0.2,
                      ws_mdisk_size=5,
                      ws_mthreshold=20,
                      ws_gdisk_size=2,
                      ws_glevel_threshold=4,
                      cv_ethreshold=0,
                      cv_mu=0.1,
                      cv_lamda_1=0.06,
                      cv_lamda_2=1,
                      cv_tol=1e-3,
                      cv_max_iter=2000,
                      cv_dt=0.52,
                      cv_init_level_set="checkerboard",
                      mcv_init_level_set="edges",
                      mcv_c1=1.0,
                      mcv_c2=1.0,
                      mcv_max_iter=35,
                      mcv_smoothing=1,
                      mcv_sigma=5):
    IM_SIZE = 400
    img = (cv2.resize(img, (IM_SIZE, IM_SIZE))).astype(np.float32)
    root_n = 5
    edges = edge_detection(img,
                           root_n,
                           strength_threshold=strength_threshold,
                           coherence_threshold=coherence_threshold
                           )  # root_n should be odd number #8-0.5
    final_image = np.zeros((img.shape[0], img.shape[1]))
    if mode == 0:
        # thresholding edges for convex hull with threshold to remove as much noise as possible
        edges[edges >= ch_ethreshold] = 1
        edges[edges < ch_ethreshold] = 0
        chull = convex_hull(edges)
        final_image[:chull.shape[0], :chull.shape[1]] = chull
        return final_image
    elif mode == 1:
        # thresholding edges for watershed on edges with low threshold to include as much edges as possible
        edges[edges >= ws_ethreshold] = 1
        edges[edges < ws_ethreshold] = 0
        watershed_edges_bin = watershed_edges(edges)
        final_image[:watershed_edges_bin.shape[0], :watershed_edges_bin.
                    shape[1]] = watershed_edges_bin
        return final_image
    elif mode == 2:
        edge_chull = edges
        edge_watershed = edge_chull.copy()

        # thresholding edges for convex hull with threshold to remove as much noise as possible
        edge_chull[edge_chull >= ch_ethreshold] = 1
        edge_chull[edge_chull < ch_ethreshold] = 0
        # thresholding edges for watershed on edges with low threshold to include as much edges as possible
        edge_watershed[edge_watershed >= ws_ethreshold] = 1
        edge_watershed[edge_watershed < ws_ethreshold] = 0

        chull = convex_hull(edge_chull)
        watershed_edges_bin = watershed_edges(edge_watershed, ws_mdisk_size,
                                              ws_mthreshold, ws_gdisk_size,
                                              ws_glevel_threshold)
        watershed_cull = chull * watershed_edges_bin[:chull.shape[0], :chull.
                                                     shape[1]]
        final_image[:watershed_cull.shape[0], :watershed_cull.
                    shape[1]] = watershed_cull
        return final_image
    elif mode == 3:
        # Feel free to play around with the parameters to see how they impact the result
        edges[edges != cv_ethreshold] = 1

        cv_init_level_set = cv_init_level_set.split(',')
        cv_init_level = cv_init_level_set[0]
        if cv_init_level_set[0] == "edges":
            cv_init_level = edges
        elif cv_init_level_set[0] == "original gray":
            cv_init_level = rgb2gray(img)
            cv_init_level = cv_init_level[:edges.shape[0], :edges.shape[1]]
        elif cv_init_level_set[0] == "path":
            cv_init_level = io.imread(cv_init_level_set[1])
            cv_init_level = (cv2.resize(cv_init_level,
                                        (IM_SIZE, IM_SIZE))).astype(np.float32)
            cv_init_level = rgb2gray(cv_init_level)
            cv_init_level = cv_init_level[:edges.shape[0], :edges.shape[1]]

        cv = chan_vese(edges,
                       mu=cv_mu,
                       lambda1=cv_lamda_1,
                       lambda2=cv_lamda_2,
                       tol=cv_tol,
                       max_iter=cv_max_iter,
                       dt=cv_dt,
                       init_level_set=cv_init_level)

        mask = cv
        final_image[:mask.shape[0], :mask.shape[1]] = mask
        return final_image
    else:
        E = np.zeros((img.shape[0], img.shape[1]))
        E[:edges.shape[0], :edges.shape[1]] = edges

        mcv_init_level_set = mcv_init_level_set.split(',')
        mcv_init_level = mcv_init_level_set[0]
        if mcv_init_level_set[0] == "edges":
            mcv_init_level = E
        elif mcv_init_level_set[0] == "original gray":
            mcv_init_level = rgb2gray(img)
        elif mcv_init_level_set[0] == "path":
            mcv_init_level = io.imread(mcv_init_level_set[1])
            mcv_init_level = (cv2.resize(
                mcv_init_level, (IM_SIZE, IM_SIZE))).astype(np.float32)
            mcv_init_level = rgb2gray(mcv_init_level)

        mask = mcv_c1 * (gaussian(
            mcv_c2 * E + morphological_chan_vese(rgb2gray(img),
                                                 iterations=mcv_max_iter,
                                                 init_level_set=mcv_init_level,
                                                 smoothing=mcv_smoothing),
            sigma=mcv_sigma))
        return mask
Beispiel #27
0
 def morphological_cv(self, image):
     image = rgb2gray(image)
     mask = seg.morphological_chan_vese(image,
                                        iterations=1000,
                                        init_level_set='circle')
     return mask
Beispiel #28
0
# -*- coding: utf-8 -*-
"""
Created on Thu Jan  9 11:32:08 2020

@author: wjswan524
"""

import numpy as np
from skimage import segmentation as seg

segs = seg.morphological_chan_vese(volred,
                                   iterations=3,
                                   init_level_set='checkerboard',
                                   smoothing=1)

segred = np.zeros((713, 642, 924))
for i in range(713):
    for j in range(642):
        for k in range(924):
            segred[i, j, k] = segs[i, j, (k + 20)]

pores = 0.
solid = 0.

for i in range(713):
    for j in range(642):
        for k in range(924):
            if segred[i, j, k] == 0:
                pores += 1.
            elif segred[i, j, k] == 1:
                solid += 1.
Beispiel #29
0
        resolution[0] *=2
        data = data[::2]
#        if resolution[0] < 2.:
#            downfac = np.floor(2. / resolution[0]).astype(np.int)
#            resolution[0] *= downfac
#            data = data[::downfac]
        data = median_filter(data, size=1, footprint=get_footprint(3, 2))
        data = median_filter(data, size=1, footprint=get_footprint(3, 2))
        data = gaussian_filter(data, sigma=[.25, .75,.75])
        data = gaussian_filter(data, sigma=[.25, .75,.75])
        data = gaussian_filter(data, sigma=[.25, .75,.75])

        mask = data > mh.otsu(data, True)
        factor = .5
        contour = morphological_chan_vese(data, iterations=10,
                                          init_level_set=mask,
                                  smoothing=1, lambda1=1, lambda2=1)
        contour = dilate(contour)
        for ii in xrange(len(contour)):
            contour[ii] = binary_fill_holes(contour[ii])

        data = np.invert(data)
        lab_img = steepest_ascent(data, resolution=resolution, mask=mask, connectivity=2)

        def merge_labels_euclidean_path_threshold(lab_img, int_img, threshold, upper_distance_limit):

            # Get coordinates
            # Get neighbours within radius

            ''' Single attempt '''
            z0, y0, x0 = 33, 323, 93
Beispiel #30
0
def level_set3D(data,
                seed3D,
                resol,
                lambda1=1,
                lambda2=4,
                smoothing=0,
                iterations=100,
                rad=3,
                method='ACWE',
                alpha=100,
                sigma=2,
                balloon=1):

    ## init
    res_fac = resol[1] / resol[
        0]  # resolution factor to scale chunk to real dimensions
    N = 60  # approximately the chunk size (in mm) around nodule
    num_slices = int(round(N / res_fac))  # number of slices before
    reg = 30  # window of interest centered around seed point
    s = seed3D[1:]  # 2D seed point for (x,y)-plane
    num = seed3D[0]  # slice number seed point is selected from

    # apply lungmask on each slice of interest around seed point
    tmp_data = np.zeros((num_slices, data.shape[1], data.shape[2]))
    ii = 0
    for i in range(data.shape[0]):
        if (i >= num - int(round(num_slices / 2))
                and i <= num + int(round(num_slices / 2)) - 1):
            mask = lungmask_pro(data[i, :, :].copy())
            tmp = data[i, :, :].copy()
            tmp[mask == 0] = np.amin(
                tmp
            )  # OBS: -1024 maybe not far away enough from lung intensities
            tmp_data[ii, :, :] = tmp.copy()
            ii += 1

    # only apply level set on small volume around seed point -> increases speed and accuracy for fixed number of iterations
    tmp = tmp_data.copy()
    tmp = tmp[:, s[0] - reg:s[0] + reg, s[1] - reg:s[1] + reg]

    # transform chunk to true size (in mm) by stretching the slice-axis relevant to a resolution factor
    tmp = zoom(tmp.copy(), zoom=[res_fac, 1, 1], order=1)

    # apply 3D level set from single seed point from initial 3D blob around current seed point
    inits = circle_level_set(tmp.shape,
                             center=(int(num_slices / 2 * res_fac), reg, reg),
                             radius=rad)

    # choose between two types of level set methods
    if method == 'ACWE':
        tmp = morphological_chan_vese(tmp.copy(),
                                      iterations=iterations,
                                      init_level_set=inits,
                                      smoothing=smoothing,
                                      lambda1=lambda1,
                                      lambda2=lambda2).astype(int)
    elif method == 'GAC':
        tmp = tmp.astype(np.float32)
        tmp = inverse_gaussian_gradient(tmp, alpha=alpha, sigma=alpha)
        tmp = morphological_geodesic_active_contour(tmp,
                                                    iterations=iterations,
                                                    init_level_set=inits,
                                                    smoothing=smoothing,
                                                    threshold='auto',
                                                    balloon=1)
    else:
        print('Please choose a valid method!')
        return None

    # if no nodule was segmented, break
    if (len(np.unique(tmp)) == 1):
        #print('No nodule was segmented. Try changing parameters...')
        return None

    # check if leakage has occured
    #if ((tmp[0,0,0] > 0) or (tmp[0,0,-1] > 0) or (tmp[0,-1,0] > 0) or (tmp[0,-1,-1] > 0) or (tmp[-1,0,0] > 0) or (tmp[-1,-1,0] > 0) or (tmp[-1,0,-1] > 0) or (tmp[-1,-1,-1] > 0)):
    # if ((len(np.unique(tmp[0,:,:])) > 1) or (len(np.unique(tmp[:,0,:])) > 1) or (len(np.unique(tmp[:,:,0])) > 1) or
    #  (len(np.unique(tmp[-1,:,:])) > 1) or (len(np.unique(tmp[:,-1,:])) > 1) or (len(np.unique(tmp[:,:,-1])) > 1)):
    # 	print("Leakage problems? Growing reached boundaries... Discards segmentation")
    # 	return None

    # only keep segments connected to seed point (blood vessels will hopefully not be connected with nodule after level set, if leakage has occured)
    labels_tmp = label(tmp.copy())
    res = np.zeros(tmp.shape)
    if (labels_tmp[int(num_slices / 2 * res_fac), reg, reg] > 0):
        res[labels_tmp == labels_tmp[int(num_slices / 2 * res_fac), reg,
                                     reg]] = 1

    # need to transform chunk back to original size
    res = zoom(res.copy(), zoom=[1 / res_fac, 1, 1], order=1)

    # # just in case some parts are not connected anymore after interpolation -> remove not connected components
    # labels_tmp = label(res.copy())
    # res = np.zeros(res.shape)
    # if (labels_tmp[int(num_slices/2), reg, reg] > 0):
    # 	res[labels_tmp == labels_tmp[int(num_slices/2), reg, reg]] = 1

    # get the final nodule mask to the original image stack shape
    # but handle cases where seed point is selected at ends of image stack, and window is outside of range
    new_res = np.zeros(data.shape)
    if (num + int(num_slices / 2) > new_res.shape[0]):
        new_res[num - int(num_slices / 2):num + int(num_slices / 2),
                s[0] - reg:s[0] + reg, s[1] - reg:s[1] +
                reg] = res[:num + int(num_slices / 2) - new_res.shape[0]]
    elif (num - int(num_slices / 2) < 0):
        new_res[0:num + int(num_slices / 2), s[0] - reg:s[0] + reg,
                s[1] - reg:s[1] + reg] = res[:num + int(num_slices / 2)]
    else:
        new_res[num - int(np.floor(num_slices / 2)):num +
                int(np.ceil(num_slices / 2)), s[0] - reg:s[0] + reg,
                s[1] - reg:s[1] + reg] = res

    return new_res