In the previous blog, we discussed image moments and how different contour features such as area, centroid, etc. can be extracted from them. In this blog, we will learn how to draw a minimum area rectangle around the region of interest. This is one of the most common tasks performed when working with contours. So, let’s get started.
Minimum Area Rectangle
As is clear from the name, the bounding rectangle is drawn with a minimum area. Because of this, rotation is also considered. The below image shows 2 rectangles, the green one is the normal bounding rectangle while the red one is the minimum area rectangle. See how the red rectangle is rotated.
OpenCV provides a function cv2.minAreaRect() for finding the minimum area rotated rectangle. This takes as input a 2D point set and returns a Box2D structure which contains the following details – (center(x, y), (width, height), angle of rotation). The syntax is given below.
1 |
(center(x, y), (width, height), angle of rotation) = cv2.minAreaRect(points) |
But to draw a rectangle, we need 4 corners of the rectangle. So, to convert the Box2D structure to 4 corner points, OpenCV provides another function cv2.boxPoints(). This takes as input the Box2D structure and returns the 4 corner points. The 4 corner points are ordered clockwise starting from the point with the highest y. The syntax is given below.
1 |
points = cv2.boxPoints(box) |
Before drawing the rectangle, you need to convert the 4 corners to the integer type. You can use np.int32 or np.int64 (Don’t use np.int8 as it permits value up to 127 and leads to truncation after that). Sometimes, you might see np.int0 used, don’t get confused, this is equivalent to np.int32 or np.int64 depending upon your system architecture. The full code is given below.
1 2 3 4 |
rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) |
Once the 4 coordinates are obtained, you can easily draw the rectangle. Now, let’s discuss about the angle of rotation.
Angle of Rotation
As we already discussed that the 4 corner points are ordered clockwise starting from the point with the highest y as shown below. If 2 points have the same highest y, then the rightmost point is the starting point. The points are numbered as 0,1,2,3 (0-starting, 3-end).
So, the angle of rotation given by OpenCV’s cv2.minAreaRect() is actually the angle between the line (joining the starting and endpoint) and the horizontal as shown below.
Thus the angle value always lies between [-90,0). Why? because if the object is rotated more than 90 degrees, then the next edge is used to calculate the angle from the horizontal. And thus the calculated angle always lies between [-90,0). See the below image where the green line shows the line joining the starting and endpoint that is used to calculate the angle. Also, see how the starting and endpoint change when the object is rotated. The points are numbered as 0,1,2,3 (0-starting, 3-end).
The actual angle is the angle by which the object is rotated and the calculated angle is the angle returned by the cv2.minAreaRect(). I hope you understood how the angle is calculated and why it lies between [-90,0).
In the next blog, we will discuss how to deskew the region of interest using the angle obtained by the cv2.minAreaRect(). Hope you enjoy reading.
If you have any doubts/suggestions please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.
how to calculate actual angle shown in the animation?
The angle is one of the parameters in cv2.RotatedRect class returned from cv2.minAreaRect()