Search code examples
pythonimage-processingcluster-analysisdetectionarea

Identify region of image python


I have a microscopy image and need to calculate the area shown in red. The idea is to build a function that returns the area inside the red line on the right photo (float value, X mm²).

Since I have almost no experience in image processing, I don't know how to approach this (maybe silly) problem and so I'm looking for help. Other image examples are pretty similar with just 1 aglomerated "interest area" close to the center.

I'm comfortable coding in python and have used the software ImageJ for some time.

Any python package, software, bibliography, etc. should help.

Thanks!

EDIT: The example in red I made manually just to make people understand what I want. Detecting the "interest area" must be done inside the code.


Solution

  • Canny, morphological transformation and contours can provide a decent result.

    Although it might need some fine-tuning depending on the input images.

    import numpy as np
    import cv2 
    
    
    # Change this with your filename
    image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)
    
    # You can fine-tune this, or try with simple threshold
    canny = cv2.Canny(image, 50, 580)  
    
    # Morphological Transformations
    se = np.ones((7,7), dtype='uint8')
    image_close = cv2.morphologyEx(canny, cv2.MORPH_CLOSE, se)
    
    contours, _ = cv2.findContours(image_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    
    # Create black canvas to draw area on
    mask = np.zeros(image.shape[:2], np.uint8)
    
    biggest_contour = max(contours, key = cv2.contourArea)
    cv2.drawContours(mask, biggest_contour, -1, 255, -1)
    
    area = cv2.contourArea(biggest_contour)
    
    print(f"Total area image: {image.shape[0] * image.shape[1]} pixels")
    print(f"Total area contour: {area} pixels")
    
    cv2.imwrite('mask.png', mask)
    cv2.imshow('img', mask)
    cv2.waitKey(0)
    
    # Draw the contour on the original image for demonstration purposes
    original = cv2.imread('test.png')
    cv2.drawContours(original, biggest_contour, -1, (0, 0, 255), -1)
    cv2.imwrite('result.png', original)
    cv2.imshow('result', original)
    cv2.waitKey(0)
    

    The code produces the following output:

    Total area image: 332628 pixels
    Total area contour: 85894.5 pixels
    

    Only thing left to do is convert the pixels to your preferred measurement.

    Two images for demonstration below.

    Result

    Mask