How can I draw a rectangle with rounded corners in OpenCV? I know that the functions ellipse() and line() can be simply put together to draw it. I just wonder if someone has done it before and has put it in a proper function so I can use it? Ideally the corner radius is to calibrate in a parameter.
I searched a lot for that, but it seems no one had that problem before. If no one has such I function I will probably post my own solution here in a few days.
We can use the drawRoundRect() method that accepts x-coordinate, y-coordinate, width, height, arcWidth, and arc height to draw a rounded rectangle.
A rounded rectangle is the shape obtained by taking the convex hull of four equal circles of radius and placing their centers at the four corners of a rectangle with side lengths and . A filled rounded rectangle with (or. ) is called a stadium. The rounded rectangle has perimeter.
I realized, this is much easier that I thought. Here is my function. I hope it is helpful for someone.
/**
* Draws a rectangle with rounded corners, the parameters are the same as in the OpenCV function @see rectangle();
* @param cornerRadius A positive int value defining the radius of the round corners.
* @author K
*/
void rounded_rectangle( Mat& src, Point topLeft, Point bottomRight, const Scalar lineColor, const int thickness, const int lineType , const int cornerRadius)
{
/* corners:
* p1 - p2
* | |
* p4 - p3
*/
Point p1 = topLeft;
Point p2 = Point (bottomRight.x, topLeft.y);
Point p3 = bottomRight;
Point p4 = Point (topLeft.x, bottomRight.y);
// draw straight lines
line(src, Point (p1.x+cornerRadius,p1.y), Point (p2.x-cornerRadius,p2.y), lineColor, thickness, lineType);
line(src, Point (p2.x,p2.y+cornerRadius), Point (p3.x,p3.y-cornerRadius), lineColor, thickness, lineType);
line(src, Point (p4.x+cornerRadius,p4.y), Point (p3.x-cornerRadius,p3.y), lineColor, thickness, lineType);
line(src, Point (p1.x,p1.y+cornerRadius), Point (p4.x,p4.y-cornerRadius), lineColor, thickness, lineType);
// draw arcs
ellipse( src, p1+Point(cornerRadius, cornerRadius), Size( cornerRadius, cornerRadius ), 180.0, 0, 90, lineColor, thickness, lineType );
ellipse( src, p2+Point(-cornerRadius, cornerRadius), Size( cornerRadius, cornerRadius ), 270.0, 0, 90, lineColor, thickness, lineType );
ellipse( src, p3+Point(-cornerRadius, -cornerRadius), Size( cornerRadius, cornerRadius ), 0.0, 0, 90, lineColor, thickness, lineType );
ellipse( src, p4+Point(cornerRadius, -cornerRadius), Size( cornerRadius, cornerRadius ), 90.0, 0, 90, lineColor, thickness, lineType );
}
Here is the python version with filled/not filled feature and corner_radius automatically calculated based on the image's height.
import cv2
import numpy as np
def rounded_rectangle(src, top_left, bottom_right, radius=1, color=255, thickness=1, line_type=cv2.LINE_AA):
# corners:
# p1 - p2
# | |
# p4 - p3
p1 = top_left
p2 = (bottom_right[1], top_left[1])
p3 = (bottom_right[1], bottom_right[0])
p4 = (top_left[0], bottom_right[0])
height = abs(bottom_right[0] - top_left[1])
if radius > 1:
radius = 1
corner_radius = int(radius * (height/2))
if thickness < 0:
#big rect
top_left_main_rect = (int(p1[0] + corner_radius), int(p1[1]))
bottom_right_main_rect = (int(p3[0] - corner_radius), int(p3[1]))
top_left_rect_left = (p1[0], p1[1] + corner_radius)
bottom_right_rect_left = (p4[0] + corner_radius, p4[1] - corner_radius)
top_left_rect_right = (p2[0] - corner_radius, p2[1] + corner_radius)
bottom_right_rect_right = (p3[0], p3[1] - corner_radius)
all_rects = [
[top_left_main_rect, bottom_right_main_rect],
[top_left_rect_left, bottom_right_rect_left],
[top_left_rect_right, bottom_right_rect_right]]
[cv2.rectangle(src, rect[0], rect[1], color, thickness) for rect in all_rects]
# draw straight lines
cv2.line(src, (p1[0] + corner_radius, p1[1]), (p2[0] - corner_radius, p2[1]), color, abs(thickness), line_type)
cv2.line(src, (p2[0], p2[1] + corner_radius), (p3[0], p3[1] - corner_radius), color, abs(thickness), line_type)
cv2.line(src, (p3[0] - corner_radius, p4[1]), (p4[0] + corner_radius, p3[1]), color, abs(thickness), line_type)
cv2.line(src, (p4[0], p4[1] - corner_radius), (p1[0], p1[1] + corner_radius), color, abs(thickness), line_type)
# draw arcs
cv2.ellipse(src, (p1[0] + corner_radius, p1[1] + corner_radius), (corner_radius, corner_radius), 180.0, 0, 90, color ,thickness, line_type)
cv2.ellipse(src, (p2[0] - corner_radius, p2[1] + corner_radius), (corner_radius, corner_radius), 270.0, 0, 90, color , thickness, line_type)
cv2.ellipse(src, (p3[0] - corner_radius, p3[1] - corner_radius), (corner_radius, corner_radius), 0.0, 0, 90, color , thickness, line_type)
cv2.ellipse(src, (p4[0] + corner_radius, p4[1] - corner_radius), (corner_radius, corner_radius), 90.0, 0, 90, color , thickness, line_type)
return src
Usage:
top_left = (0, 0)
bottom_right = (500, 800)
color = (255, 255, 255)
image_size = (500, 800, 3)
img = np.zeros(image_size)
img = rounded_rectangle(img, top_left, bottom_right, color=color, radius=0.5, thickness=-1)
cv2.imshow('rounded_rect', img)
cv2.waitKey(0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With