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:
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:
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!