Search code examples
pythonopencvimage-processingpixelcontour

How to calculate diameter at multiple points of an object using image pixels?


I am trying to get diameters on different points of a cylinder over a certain length using computer vision to replace the use of optical micrometer.

Image of a cylinder: enter image description here

How can I calculate the diameter of this object (cylinder) on multiple points (blue lines) along its length as shown in the image using OpenCV python?


Solution

  • An OpenCV solution. The main idea is to:

    1. Detect edges
    2. Find the contours of the edges
    3. Fill in the contour areas
    4. Go through each column in the image and count the nonzero pixels

    1., 2. and 3. could possibly be simplified by a single thresholding step depending on your use case

    import numpy as np 
    import cv2
    
    
    src = cv2.imread('/path/to/src.jpg')
    mask = np.zeros(src.shape, dtype=np.uint8)
    w, h, c = src.shape
    
    # edge detection
    threshold = 100
    gray = cv2.Canny(src, threshold, threshold * 2)
    
    cv2.imshow('', gray)
    cv2.waitKey(0)
    
    # find contours
    cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    threshold_area = 0.5
    
    # fill area withing contours with white color
    for c in cnts:
        area = cv2.contourArea(c)
        if area > threshold_area:
            cv2.drawContours(mask, [c], -1, (255, 255, 255), -1)
    
    cv2.imshow('', mask)
    cv2.waitKey(0)
    
    # get non zero values (height) of each column
    column_pixels = [cv2.countNonZero(mask[:, i]) for i in range(0, w)]
    print(column_pixels)
    

    Src image:

    enter image description here

    Canny result:

    enter image description here

    After filling in contours with white color:

    enter image description here

    countNonZero is applied on this last image for each column