RandomWalker Segmentation algorithm results in a segmentation same as the initial seeds

561 views Asked by At
  • I have a medical Image, and I'm trying to segment a specific zone inside.
  • After several steps of conventional image processing, I was able to locate the region, and managed to get the seeds for the segmentation, but when I try to apply RandomWalker algorithm, I don't get a good segmentation.
  • can you please tell me what is the problem here, and how to correct it?

CT

Output

Code :

# import math
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
from skimage.feature import canny
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.draw import circle_perimeter
from skimage.segmentation import watershed, random_walker, active_contour
import skimage.filters as filters

# Read image
img = cv.imread("CT.png")

# Get image center coordinates
img_center = (img.shape[0]//2, img.shape[1]//2)

# Edge detector
edges = canny(img, sigma=2.0, low_threshold=19, high_threshold=57)

# Hough_circle
hough_radii = np.arange(29, 32, 1)
hough_res = hough_circle(edges, hough_radii)
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,total_num_peaks=4, min_xdistance=70,min_ydistance=200, threshold=0.25)

# Remove false-posite circle
sortX = np.argsort(cx)
cx = cx[sortX[:-1]]
cy = cy[sortX[:-1]]
radii = radii[sortX[:-1]]

#--------------------------------------
# get the closest circle to the centre 
#--------------------------------------
dist = []
for idx in range(len(cx)):
    dist.append(abs(img_center[1]-cx[idx])+abs(img_center[0]-cy[idx]))
sortD = np.argsort(dist)
Cx = cx[sortD[0]]
Cy = cy[sortD[0]]
radius = radii[sortD[0]]

markers = np.ones(img.shape, dtype=np.uint)
markers[img==0] = 0
markers[Cy-radius//2:Cy+radius//2, Cx-radius//2:Cx+radius//2] = 2
# markers[(Cy-radius//2)+1:(Cy+radius//2)-1, (Cx-radius//2)+1:(Cx+radius//2)-1] = 0
#---------------------------------
labels = random_walker(img, markers)

# print(labels.shape)
# Plot results
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 3.2),
                                    sharex=True, sharey=True)
ax1.imshow(img, cmap='gray')
ax1.axis('off')
ax1.set_title('Noisy data')
ax2.imshow(markers, cmap='magma')
ax2.axis('off')
ax2.set_title('Markers')
ax3.imshow(labels, cmap='gray')
ax3.axis('off')
ax3.set_title('Segmentation')

fig.tight_layout()
plt.show()
#======================================
2

There are 2 answers

2
Juan On BEST ANSWER

Random walker only expands labels from markers into the regions having label 0. You end up with an image containing only ones everywhere except for 2 in the original square. That's because the label 2 has nowhere to expand into: it is surrounded by 1s.

I was able to modify the segmentation a little by using:

border = 71
surround = (
    (dilation(markers, np.ones((border, border))) == 2)
    ^ (markers==2)
)
markers[surround] = 0
labels = random_walker(img, markers) * (img != 0)

segmentation figure

It's definitely still not perfect. Beyond this, you will need to play with the border size as well as the beta= and tol= parameters of random_walker.

0
Golden Lion On
 import matplotlib.pyplot as plt
 from PIL import Image
 import numpy as np
 from skimage.feature import canny
 from skimage.transform import hough_circle, hough_circle_peaks
 from skimage.segmentation import watershed, random_walker, active_contour
 from skimage.morphology import erosion, dilation
 from skimage.restoration import denoise_bilateral
 from skimage.color import rgb2gray
 from skimage.filters import threshold_local

 image=plt.imread('medical_image.png')
 plt.imshow(image)
 plt.show()

 canny_edges=canny(image, sigma=1.5 )
 hough_radii = np.arange(29, 32, 1)
 hough_res = hough_circle(canny_edges, hough_radii)
 #Identifies most prominent circles separated by certain distances in a
 #Hough space. 
 accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,total_num_peaks=4, min_xdistance=70,min_ydistance=200, threshold=0.25)

 img_center = (image.shape[0]//2, image.shape[1]//2)

 dist = []
 for idx in range(len(cx)):
     dist.append(abs(img_center[1]-cx[idx])+abs(img_center[0]-cy[idx]))
 sortD = np.argsort(dist)
 Cx = cx[sortD[0]]
 Cy = cy[sortD[0]]
 radius = radii[sortD[0]]

 markers = np.ones(image.shape, dtype=np.uint)
 markers[image==0] = 0
 markers[Cy-radius//2:Cy+radius//2, Cx-radius//2:Cx+radius//2] = 2

 border = 71
 surround = (
   (dilation(markers, np.ones((border, border))) == 2)
  ^ (markers==2)
 )
 markers[surround] = 0

 labels = random_walker(image, markers)

 block_size=35
 grayscale_image=rgb2gray(image)
 denoised_image=denoise_bilateral(grayscale_image,multichannel=False)

 local_thresh= threshold_local(grayscale_image, block_size,offset=.01)
 #apply the thresholding to the image
 binary_global = grayscale_image<local_thresh

 plt.clf()
 fig, (ax1, ax2, ax3,ax4,ax5) = plt.subplots(1, 5, figsize=(8, 3.2),
                                sharex=True, sharey=True)
 ax1.imshow(canny_edges, cmap='gray')
 ax1.axis('off')
 ax2.imshow(markers,cmap='gray')
 ax2.axis('off')
 ax3.imshow(labels,cmap='gray')
 ax3.axis('off')
 ax4.imshow(binary_global,cmap='gray')
 ax4.axis('off')
 ax5.imshow(denoised_image,cmap='gray')
 ax5.axis('off')
 plt.show()