I wrote a OpenCV python script to identify the contour of an object in a microscope image.
Selected contour image example:
I need to meassure the width of the object at N intervals, where width is the distance between the right side to the left side of the contour in that interval, the line meassured is always horisontal.
this will later be repeated on about 30000 images.
Thsi is my latest attempt but it obviously not working
# Find contours in the inverse binary image
contours, _ = cv2.findContours(255 - binary_opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Choose the largest contour (assumes the blob is the largest connected component)
largest_contour = max(contours, key=cv2.contourArea)
# Divide the contour into 10 equal horizontal intervals
num_intervals = 10
interval_height = len(largest_contour) // num_intervals
# Create evenly spaced intervals along the y-axis
intervals_y = np.linspace(0, len(largest_contour), num_intervals + 1, dtype=int)
# Draw and display each interval on the original image
for i in range(num_intervals):
start_idx = intervals_y[i]
end_idx = intervals_y[i + 1]
# Get points in the interval
interval_points = largest_contour[start_idx:end_idx]
# Draw the contour of the interval on the original image
cv2.drawContours(image, [interval_points], -1, (0, 0, 255), 2)
I am new to openCV so any tip would be appreciated
I had a little attempt at this as follows:
#!/usr/bin/env python3
import cv2 as cv
import numpy as np
# Load image and extract width and height
im = cv.imread('osjKP.jpg')
h, w = im.shape[:2]
# Convert to HSV to find all the green pixels
HSV = cv.cvtColor(im, cv.COLOR_BGR2HSV)
lo = np.array([50,200, 100]) # lower limit for green in HSV space
hi = np.array([70,255, 255]) # upper limit for green in HSV space
greens = cv.inRange(HSV, lo, hi)
cv.imwrite('DEBUG-greens.png', greens)
# Floodfill with white from the centre
_, result, _, _ = cv.floodFill(greens, None, (int(w/2), int(h/2)), 255)
cv.imwrite('DEBUG-floodfilled.png', result)
# Count the non-zero pixels in each row, i.e. widths[0] is the width of the top row
widths = np.count_nonzero(result, axis=1)
print(widths)
My assumption that it is safe to flood fill from the centre may not be correct for your other images (e.g. if the item you are measuring is narrow) so you may want to fill from the top-left and top-right corner and then invert, for example.
If you only want the widths of every 20th row, change the last couple of lines to:
# Count the non-zero pixels in each row
N = 20
widths = np.count_nonzero(result[::N,:], axis=1)
print(widths)
Output
[ 918 902 907 899 896 904 911 894 912 913 897 884 912 916
895 910 892 878 869 871 888 881 870 846 856 860 866 896
876 873 878 880 881 889 892 898 900 917 931 954 966 976
982 990 992 1030]