'Cropping rectangles in python OpenCV
I have the following code which successfully finds rectangles in a chessboard and puts each contour in valid_cnts Numpy Array, its size is 64 (8 X 8), and each index in the array includes a different rectangle. I would like to crop each different rectangle and save them as a picture.
# Find contours and find squares with contour area filtering + shape approximation
cnts = cv2.findContours(invert, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
r = 0
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
valid_cnts = []
v = []
for c in cnts:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
if len(approx) == 4 and area > 100 and area < 10000:
x, y, w, h = cv2.boundingRect(c)
cv2.drawContours(original, [c], -1, (36, 255, 12), 2)
cv2.drawContours(mask, [c], -1, (255, 255, 255), -1)
valid_cnts.insert(r,c)
v.insert(r,[x,y,w,h])
r = r + 1
Any help would be appreciated.
Solution 1:[1]
Inside your for loop, after the vertex and area filters you calculate the bounding rectangle of the contour like this: x, y, w, h = cv2.boundingRect(c). Here, you have the dimensions of the region of interest: top left coordinate, width and height . If you want to crop this area, use numpy slicing with the bounding rect dimensions:
if len(approx) == 4 and area > 100 and area < 10000:
# Get the left top corner, width and height of the contour
# bounding rectangle:
x, y, w, h = cv2.boundingRect(c)
# Slice the area of interest from the original image:
croppedImage = originalImage[y:y+h, x:x+w]
# Show the crop:
cv2.imshow("Cropped Iamge", croppedImage)
cv2.waitKey(0)
Just be careful with the order of the slicing indices: you first slice vertically and then horizontally. The first index starts at y and ends at y + h, the second index starts at x and ends at x + w.
Also, if you drew something on your original image, you probably will see the drawn info on the cropped image too. You might need to create a deep copy of the image using the copy method: imageCopy = originalImage.copy(). Create the deep copy before drawing your debugging information and use that exclusively for your slicing: croppedImage = originalImage[y:y+h, x:x+w].
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | stateMachine |
