opencvimage-processingroi

OpenCV Annulus region of interest


I defined annulus ROI selection function and i would like to find contours in this area. But contours pixel values are neighbors to the zero and out of masked areas equal to zero. Therefore contours couldn't be catch thresholded image.

How can i define annulus ROI or find the contours if function is ok

    def annulusROI(img, center, innerR, outerR):
        """
        img: Image matrix
        center: ROI center point [px] (x,y tuple)
        innerR: ROI inner radius [px]
        outerR: ROI outer radius [px]
        mode: Mask selection for white (255, 255, 255), for black (0, 0, 0) [BGR tuple]
    
        return roi matrix and left-top start point coordinate
        """
        outRoi, rectC = rectangleROI(img, center, outerR*2, outerR*2)
        mask1 = np.zeros_like(outRoi)
        mask2 = np.zeros_like(outRoi)
        mask1 = cv2.circle(mask1, (round(outerR),round(outerR)), innerR, (255, 255, 255), -1)
        mask2 = cv2.circle(mask2, (round(outerR),round(outerR)), outerR, (255, 255, 255), -1)
        mask = cv2.subtract(mask2, mask1)
        roi = cv2.bitwise_and(outRoi, mask)
    
        return roi, (center[0]-outerR, center[1]-innerR)

contour

thresholded roi returned image


Solution

  • After thresholding and before getting the contours you can separate the region of interest from the outer area. Or even better you can cut your region of interest after thresholding, not before. Finally you can filter out the releavant contours by area size.

    import cv2
    
    
    # get image threshold
    img = cv2.imread("img.png")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 64, 255, 0)
    
    # separate annulus from outer area
    h, w, _ = img.shape
    center = (round(w / 2), round(h / 2))
    innerR = 246
    outerR = 306
    
    cv2.circle(thresh, center, innerR, 255)
    cv2.circle(thresh, center, outerR, 255)
    
    # filter contours by relevant area size
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cc = [c for c in contours if 100 < cv2.contourArea(c) < 5000]
    cv2.drawContours(img, cc, -1, (0, 0, 255))
    
    cv2.imwrite("out.png", img)
    

    Result:

    output