0

I am trying to measure the feret diameter of microscopic particles deposited onto glass using Python OpenCV2. Presently, I have close to 150 images for which, this process needs to be automated. For measuring, I have written a Python script which is given below:

import cv2
import numpy as np
import matplotlib.pyplot as plt
from skimage import io, color, measure

##step-1 reading the image
img = cv2.imread('1.tif', 0)
pixel_2_micron = 1.75 #1 pixel is equal too 1.75 microns
#img = color.rgb2gray(io.imread('1.tif', 0))

##step-2 selecting required region if necessary
cropped_img = img[0:1422,:]
#plt.hist(img.flat, bins=100, range=(0,255))
ret, thresh = cv2.threshold(cropped_img, 162, 217, cv2.THRESH_BINARY)

#Step-3
kernel = np.ones((3,3),np.uint8)
eroded = cv2.erode(thresh, kernel, iterations = 1)
dilated = cv2.dilate(eroded, kernel, iterations = 1)
#cv2.imshow("Original Image", img)
#cv2.imshow("Threshold Image", thresh)
#cv2.imshow("Eroded Image", eroded)
#cv2.imshow("Dilated Image", dilated)
#cv2.waitKey(0)

#step-4

mask = thresh == 217
io.imshow(mask) #show the masked image 

Please assist me in measuring the dimensions of the masked regions. Especially the feret diameter for all the masked regions.

I have attached the image having masked the particles.Binary image consisting of particles that have been masked

Claudio
  • 7,474
  • 3
  • 18
  • 48
  • 1
    You can use scikit-image for this. See this example https://scikit-image.org/docs/stable/auto_examples/segmentation/plot_regionprops.html – jkr Sep 19 '20 at 21:08
  • Convert the image so that your spots are white on a black background. Get rid of the borders. Find contours and get their bounding boxes. Use the average of the width and height of the bounding box for the dimension is the simplest method. Alternately fit ellipses to each contour and get the major and minor dimensions. – fmw42 Sep 19 '20 at 21:48
  • @fmw42, Dear Sir/Ma'am, thank you very much for your suggestion. I have inverted my image using the following code:```inv_img = cv2.bitwise_not(thresh) ```. However, while finding the contours, I am getting the following error: ValueError: not enough values to unpack (expected 3, got 2). Please suggest – Srikrishnarka Pillalamarri Sep 19 '20 at 22:15
  • Different versions of OpenCV findContours returns different number of arguments. Use the following: `contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours = contours[0] if len(contours) == 2 else contours[1]`, which is version independent – fmw42 Sep 19 '20 at 22:32
  • Dear Sir, I have modified the code based on your suggestion. But when I measured the numbers of contours, I am getting only 1. – Srikrishnarka Pillalamarri Sep 20 '20 at 00:27
  • You're trying to find contours using `cv2.RETR_EXTERNAL` on a white image with black features? Yes, it's going to return the perimeter of the image as the only contour. I would try thresholding with `cv.THRESH_BINARY_INV` to invert the image. – beaker Sep 20 '20 at 22:32

1 Answers1

1

I have just released a python module to calculate the feret diameter of binary images which would solve your problem.

https://pypi.org/project/feret/

At the moment it can’t handle images with more than one region but as described above your can use this skimage module to find connecting regions and then just take the maximum and minimum of those regions to cutout the region of the image. If you need help, tell me.