0

I am trying to write a code that calculates the area occupied by the tracks on a microscope image, as this:

Image with tracks

As the tracks aren't uniform (I mean, they don't have a unique grey level as they are darker in the edge and lighter in the centre), I can't do this just by comparing their grey level with the grey level of the background because in some parts of the tracks it is the same.

Therefore, what I tried is to compare the image with an image of the background:

Background image

I do this in order to extract the differences between these two images (which correspond to the tracks themselves). In order to do this, I have used the compare_ssim function from skimage. The code I've used is the following:

from skimage.measure import compare_ssim 
import imutils
import cv2
import numpy as np

# load the two input images
imageA = cv2.imread("./b.jpg")
imageB = cv2.imread("./a.jpg")
# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
    
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
# show the diff image
cv2.imshow("Diff", diff)

The diff image I obtain is the following:

Diff image

This is quite good, because now the grey level in the tracks is well-differentiated from the grey level of the background, and I can calculate the area occupied by the tracks (there are some points in the track that are lighter, but they are few and it's okay for my purpose).

Nevertheless, the problem is that in the diff image not only the tracks appear in black, but also a thick border surrounding the tracks:

Thick border

This edge makes my area estimation incorrect. So I would like to know how I can eliminate that edge, or at least make it thinner.

If this is not possible, it would be really helpful if you can show me another Python function that can achieve my purpose of calculating the area occupied by the tracks.

Bilal
  • 3,191
  • 4
  • 21
  • 49
Lidia
  • 1
  • 1

1 Answers1

1

There is always a better way to do the same thing, but I used here a simple approach, which you can improve or tune later according to your needs:


Algorithm:

  1. Firstly, proper thresholding will keep only the edges
  2. Secondly, Morphology (dilation, or erosion depending on your thresholding approach) will thin your Edges.
  3. At the end, to get rid of everything, except your tracks, you can use Flood_Fill algorithm, then count the white pixels to get your area(in pixels).

Results:

In the Final result: The count of the white of pixels is: 52219

Results


Code:

#========================
# Import Libraries
#========================
import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage.morphology import flood_fill

#========================
# Read images
#========================
img = cv2.imread('1.png',0)
bck = cv2.imread('2.png',0)

#========================
# Gaussian Blur
#========================
gauss = cv2.GaussianBlur(img, (5,5), 1)
bck_gauss = cv2.GaussianBlur(bck, (5,5), 1)
#========================
# Thresholding
#========================
_,thresh1 = cv2.threshold(gauss,127,255,cv2.THRESH_BINARY)
_,bck_th = cv2.threshold(bck_gauss,127,255,cv2.THRESH_BINARY_INV)

# Get rid of black borders
thresh1 = thresh1 + bck_th

#========================
# Morphology
#========================
kernel = np.zeros((7,7),np.uint8)
kernel[2,:] = 1
kernel[:,2] = 1
dilation = cv2.dilate(thresh1,kernel,iterations = 1)

#========================
# Flood Fill 
#========================

res = flood_fill(dilation,(1,1), 0)
print("The count of the white of pixels is: ", int(np.sum(res)/np.max(res)))
#========================
# Visualize Results
#========================
plt.figure(num='Blobs')

plt.subplot(221)
plt.imshow(img, cmap='gray')
plt.title('Original')
plt.axis('off')

plt.subplot(222)
plt.imshow(thresh1, cmap='gray')
plt.title('Thresholded')
plt.axis('off')

plt.subplot(223)
plt.imshow(dilation, cmap='gray')
plt.title('Morphology')
plt.axis('off')

plt.subplot(224)
plt.imshow(res, cmap='gray')
plt.title('Final Result')
plt.axis('off')

plt.show()
Bilal
  • 3,191
  • 4
  • 21
  • 49