Cropping Multiple Contours using OpenCV

We have seen in our Previous Tutorials how we can threshold an image and apply the findContour Algorithm to find only the bounding edge of an object.

Now let's say that we have multiple object that we would to:

  • Detect All objects in an image
  • Extract all objects and save each of them into an image seperatly.

Getting back to our bottle labeling machine, we would have this image of three bottles:

opencv-bottles-three

let's first use our Threhold Script:

  
    import cv2
    # Read image
    src= cv2.imread ("threebottles.jpg")

    # Set the threshold and maxValue
    thresh= 245
    maxValue = 255

    # Basic threshold example
    th, dst= cv2.threshold(src, thresh, maxValue, cv2. THRESH_BINARY)

    cv2.imwrite ("pic_threshold.jpg",dst)

  

And the thresholding result would be as follows:

three-bottle-thresh

boundingRect() Funciton:


In order to crop the obejct out of the image, we need to use an OpenCV function that does the following:


  • Gets the contour as an argument
  • Calculate the smallest bounding box that could enclose this object.

Now if we crop this box and store it, then we would have our image.

This OpenCV function is called boundingRect.

  
     x,y,w,h= cv2.boundingRect(contours[i])
  

This function simply takes any contour from our contour list returns, the first x and y coordinates, in addition to the height and width of the bounding box!

Let's see the whole oc

Cropping


Cropping this bounding box we have is done using python slicing.

  
    cropped_img=original_image[y:y+h, x:x+w]
  

What we are doing here, is simply taking our original, non-modified image, and cropping only the bounding box coordinates of every bottle

Multiple Contours cropping code


    
  import cv2
  #Store the threshold image generated by the previous script
  image = cv2.imread('pic_threshold.jpg')

  #Store the original image
  original_image = cv2.imread('threebottles.jpg')

  #Convert the thrsholded image to binary
  img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

  #threshold one more time for better results.
  ret, thresh = cv2.threshold(img_gray, 150, 255, cv2.THRESH_BINARY)

  #find the contours
  contours, hierarchy = cv2.findContours(image=thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)

  image_copy = image.copy()

  #loop over every contour, calculate its area and filter the correct area
  #Apply the bounding box on the contours that passes the area criteria
  #Store every object seperately.
  for i in range(0,len(contours)):

          area=cv2.contourArea(contours[i])
          print(area)
          if( area<20000 and area>5000):


                  x,y,w,h= cv2.boundingRect(contours[i])
                  cropped_img=original_image[y:y+h, x:x+w]
                  img_name= str(i)+".jpg"
                  cv2.imwrite(img_name,cropped_img)

    
  

And the result is as expected, three seperated bottle in three seperated images!

opencv-bottle
opencv-bottle
opencv-bottle