Python - OpenCV - Cropping images and isolating specific objects

10,596

I answered the similar question @ OpenCV : Remove background of an image . It works successful for the image you posted in the question.


It fails on the below image. Because, the code is for only two circle detected, or when the inner circle is the the first sorted contour greater than 100.

To make it work, you should make it meet the condition. You can do something to rule out the non-circle ones, the non-center ones, the too-small or too-big ones. Such as:

enter image description here


A sample code:

#!/usr/bin/python3
# 2018.01.20 20:58:12 CST
# 2018.01.20 21:24:29 CST
# 2018.01.22 23:30:22 CST

import cv2
import numpy as np

## (1) Read
img = cv2.imread("img04.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

## (2) Threshold
th, threshed = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)

## (3) Find the first contour that greate than 100, locate in centeral region
## Adjust the parameter when necessary
cnts = cv2.findContours(threshed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2]
cnts = sorted(cnts, key=cv2.contourArea)
H,W = img.shape[:2]
for cnt in cnts:
    x,y,w,h = cv2.boundingRect(cnt)
    if cv2.contourArea(cnt) > 100 and (0.7 < w/h < 1.3) and (W/4 < x + w//2 < W*3/4) and (H/4 < y + h//2 < H*3/4):
        break

## (4) Create mask and do bitwise-op
mask = np.zeros(img.shape[:2],np.uint8)
cv2.drawContours(mask, [cnt],-1, 255, -1)
dst = cv2.bitwise_and(img, img, mask=mask)

## Display it
cv2.imwrite("dst.png", dst)
cv2.imshow("dst.png", dst)
cv2.waitKey()

The result:

enter image description here

Share:
10,596
Admin
Author by

Admin

Updated on June 06, 2022

Comments

  • Admin
    Admin almost 2 years

    Using python - OpenCV I have succeeded to read the following image, detect the rectangles , crop them and save every rectangle as an image.

    Main Image

    and this is a sample of the rectangles that I have succeeded to crop and save as an image. (So there will be 12 of them)

    Rectanle Image

    Then working on every rectangle image, in order to isolate the circle and create a new image for every circle - which I have succeeded to do too using cv2.HoughCircles.

    The output of the image A contains the circle looks like :

    Image contains circle and more

    Now: what I need to do is to remove everything outside of the green circle and convert everything outside the green circle to black, then get B(only the green circle):

    Isolated Image Circle

    The question is: How to get B from A.

    I take code from OpenCV : Remove background of an image, but it is not work for the image A as excepted, while output such a image instead:


    This is the code taken from OpenCV : Remove background of an image.

    circle_path_test = 'D:\rec.png'
    
    img  = cv2.imread(circle_path_test)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    ## (2) Threshold
    th, threshed = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)
    
    ## (3) Find the min-area contour
    _, cnts, _ = cv2.findContours(threshed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = sorted(cnts, key=cv2.contourArea)
    for cnt in cnts:
        if cv2.contourArea(cnt) > 100:
            break
    
    ## (4) Create mask and do bitwise-op
    mask = np.zeros(img.shape[:2],np.uint8)
    cv2.drawContours(mask, [cnt],-1, 255, -1)
    dst = cv2.bitwise_and(img, img, mask=mask)
    
    ## Save it
    # cv2.imshow("dst.png", dst);cv2.waitKey()       
    #rec_img_name_without_extension ,img_ext = os.path.splitext(circle_path_test)                
    cv2.imwrite(os.path.join(os.getcwd(), 'dst_circle_gray - Copy.png') , dst)