How to fill a rounded rectangle in openCV c++

opencv fillpoly
floodfill opencv c++
cvline
cvcircle
opencv lines
cv2 fillconvexpoly
opencv get text size
polylines opencv c++

I figure a way to draw a rounded rectangle using OpenCV C++. My function is:

void RoundedRectangle(cv::Mat& src, 
                      cv::Point topLeft, 
                      cv::Size rectSz, 
                      const cv::Scalar lineColor, 
                      const int thickness, 
                      const int lineType, 
                      const float  cornerCurvatureRatio)
{
    // corners:
    // p1 - p2
    // |     |
    // p4 - p3
    //
    cv::Point p1 = topLeft;
    cv::Point p2 = cv::Point (p1.x + rectSz.width, p1.y);
    cv::Point p3 = cv::Point (p1.x + rectSz.width, p1.y + rectSz.height);
    cv::Point p4 = cv::Point (p1.x, p1.y + rectSz.height);
    float cornerRadius = rectSz.height*cornerCurvatureRatio;

    // draw straight lines
    cv::line(src, cv::Point (p1.x + cornerRadius, p1.y), cv::Point (p2.x - cornerRadius, p2.y), lineColor, thickness, lineType);
    cv::line(src, cv::Point (p2.x, p2.y + cornerRadius), cv::Point (p3.x, p3.y - cornerRadius), lineColor, thickness, lineType);
    cv::line(src, cv::Point (p4.x + cornerRadius, p4.y), cv::Point (p3.x - cornerRadius, p3.y), lineColor, thickness, lineType);
    cv::line(src, cv::Point (p1.x, p1.y + cornerRadius), cv::Point (p4.x, p4.y - cornerRadius), lineColor, thickness, lineType);

     // draw arcs
    cv::Size rad = cv::Size(cornerRadius, cornerRadius);
    cv::ellipse(src, p1 + cv::Point(cornerRadius, cornerRadius),   rad, 180.0, 0, 90, lineColor, thickness, lineType);
    cv::ellipse(src, p2 + cv::Point(-cornerRadius, cornerRadius),  rad, 270.0, 0, 90, lineColor, thickness, lineType);
    cv::ellipse(src, p3 + cv::Point(-cornerRadius, -cornerRadius), rad, 0.0, 0, 90, lineColor, thickness, lineType);
    cv::ellipse(src, p4 + cv::Point(cornerRadius, -cornerRadius),  rad, 90.0, 0, 90, lineColor, thickness, lineType);
}

Now I want to fill the rectangle. I found some fill functions such as cv::fillPoly() and cv::fillConvexPoly however, I need a vector with points. How I can get the list of points from my construction?

Nuzhny was correct, floodFill() is the easiest and potentially the fastest way to fill that rounded rectangle. (Tested with CV 4.1.1)

One line of code will do it, but here is the entire example.

void rounded_rectangle( Mat& src, Point topLeft, Point bottomRight, const Scalar lineColor, int thickness, const int lineType , const int cornerRadius)
{
    Point p1 = topLeft;
    Point p2 = Point (bottomRight.x, topLeft.y);
    Point p3 = bottomRight;
    Point p4 = Point (topLeft.x, bottomRight.y);


    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);

    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 );

    // choose arbitrary starting point for fill => Top left plus 10,10
    Point fillFrom(topLeft.x+10, topLeft.y+10);
    Scalar fillColor(199, 120, 0);
    // You may want to use `lineColor` instead of `fillColor`
    floodFill(src, fillFrom, fillColor);
}

Basic Drawing, Scalar( a, b, c ). We would be defining a BGR color such as: Blue = a, Green = b and Red = c And to draw the rook we employed MyLine, rectangle and a MyPolygon: C++ To draw a filled polygon we use the function fillPoly() . We note that  Nuzhny was correct, floodFill()is the easiest and potentially the fastest way to fill that rounded rectangle. (Tested with CV 4.1.1) One line of code will do it, but here is the entire example. void rounded_rectangle(Mat& src, Point topLeft, Point bottomRight, const Scalar lineColor, int thickness, const int lineType, const int cornerRadius)

To get the points from the shape that you constructed with cv::line and cv::ellipse , you could draw the shape on a black background and then find the contours of that image.

Another approach that doesn't use line and ellipse commands is to compute the contour of the shape directly using trig.

import cv2, numpy as np, math

# Define the rectangle parameters
directions, ro, next_corner, radius, increment, angle, leg, corners = [(-1,0),(0,-1),(1,0),(0,1)],[(-1,-1),(1,-1),(1,1),(-1,1)],[3,0,1,2],56, 100, 0, 321, [(500,500)]

# Create list of corners
for side in range(4): corners.append((corners[side][0]+leg*directions[side][0], corners[side][1]+leg*directions[side][1]))

# Distance function
def distance(a,b): return math.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2)

# Compute the contour points for each side and corner
contour_points = []
for i in range(4):
    # Do the corner
    center = corners[i][0] + radius*ro[i][0], corners[i][1] + radius*ro[i][1]
    for angle_increment in range(increment):
        contour_points.append((int(center[0] + math.cos(angle) * radius), int(center[1] + math.sin(angle) * radius)))
        angle += .5*math.pi/increment
    # Do the line
    start = corners[i][0]+radius*directions[i][0], corners[i][1] + radius*directions[i][1]
    while distance(start, (corners[i][0]+radius*directions[i][0], corners[i][1] + radius*directions[i][1])) < leg-2*radius:
        contour_points.append(start)
        start = start[0]+directions[i][0], start[1]+directions[i][1]

# Draw the contour and show the image
img = np.zeros((600,600), np.uint8)
cv2.drawContours(img, [np.array(contour_points, dtype=np.int32)], 0, 255, -1)
cv2.imshow('img',img)
cv2.waitKey(0)

cv2.destroyAllWindows()

Drawing Functions, An example on using variate drawing functions like line, rectangle, can C++: void circle (Mat& img, Point center, int radius, const Scalar& The functions ellipse with less parameters draw an ellipse outline, a filled ellipse,  Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.

Use cv::floodFill with start point inside your rectangle.

Drawing Functions in OpenCV, If -1 is passed for closed figures like circles, it will fill the shape. default To draw a rectangle, you need top-left corner and bottom-right corner of rectangle. I'm using Python 2.7.13 and OpenCV 2.4.13.3. I've been thinking to extend these lines and get intersection points of lines. Finally, I will get four coordinates of rectangle. But if the image is more complex, I don't know how to deal with.

Here is my solution in case id of help to anybody.

void FilledRoundedRectangle(cv::Mat& src,            //Image where rect is drawn
                      cv::Point topLeft,             //top left corner
                      cv::Size rectSz,               //rectangle size
                      const cv::Scalar fillColor,    //fill color
                      const int lineType,            //type of line
                      const int delta,               //angle between points on the ellipse
                      const float cornerCurvatureRatio) //curvature of the corner
{
    // corners:
    // p1 - p2
    // |     |
    // p4 - p3
    //
    cv::Point p1 = topLeft;
    cv::Point p2 = cv::Point (p1.x + rectSz.width, p1.y);
    cv::Point p3 = cv::Point (p1.x + rectSz.width, p1.y + rectSz.height);
    cv::Point p4 = cv::Point (p1.x, p1.y + rectSz.height);
    int cornerRadius = static_cast<int>(rectSz.height*cornerCurvatureRatio);
    std::vector<cv::Point> points;
    std::vector<cv::Point> pts;
    // Add arcs points

    cv::Size rad = cv::Size(cornerRadius, cornerRadius);

    // segments:
    //    s2____s3
    // s1          s4
    // |           |
    // s8          s5
    //   s7_____s6
    //
    //Add arc s1 to s2 
    cv::ellipse2Poly(p1 + cv::Point(cornerRadius, cornerRadius)  , rad, 180.0, 0, 90, delta , pts);
    points.insert(points.end(), pts.begin(), pts.end());
    pts.clear();
    //Add line s2-s3 
    points.push_back(cv::Point (p1.x + cornerRadius, p1.y)); points.push_back(cv::Point (p2.x - cornerRadius, p2.y));

    //Add arc s3 to s4 
    cv::ellipse2Poly(p2 + cv::Point(-cornerRadius, cornerRadius) , rad, 270.0, 0, 90, delta, pts);
    points.insert(points.end(), pts.begin(), pts.end());
    pts.clear();
    //Add line s4 to s5
    points.push_back(cv::Point (p2.x, p2.y + cornerRadius)); points.push_back(cv::Point (p3.x, p3.y - cornerRadius));

    //Add arc s5 to s6 
    cv::ellipse2Poly(p3 + cv::Point(-cornerRadius, -cornerRadius), rad, 0.0,   0, 90, delta, pts);
    points.insert(points.end(), pts.begin(), pts.end());
    pts.clear();
    //Add line s7 to s8
    points.push_back(cv::Point (p4.x + cornerRadius, p4.y)); points.push_back(cv::Point (p3.x - cornerRadius, p3.y));

    //Add arc s7 to s8 
    cv::ellipse2Poly(p4 + cv::Point(cornerRadius, -cornerRadius) , rad, 90.0,  0, 90, delta, pts);
    points.insert(points.end(), pts.begin(), pts.end());
    //Add line s1 to s8
    points.push_back(cv::Point (p1.x, p1.y + cornerRadius)); points.push_back(cv::Point (p4.x, p4.y - cornerRadius));    

    //fill polygon
    cv::fillConvexPoly(src, points, fillColor, lineType);
}


   int main(int argc, char** argv)
   {
      try
      {
          cv::Mat img = cv::Mat(600, 600,CV_8UC1,cv::Scalar(0));
          cv::Point topLeft(179, 179);
          cv::Size rectSz(321, 321);
          cv::Scalar fillColor(255, 255, 255);
          int delta                  = 1; //every 1 degree
          int lineType               = cv::LINE_AA;
          float cornerCurvatureRatio = 0.1;
          FilledRoundedRectangle(img,
                                 topLeft,
                                 rectSz,
                                 fillColor,
                                 lineType,
                                 delta,
                                 cornerCurvatureRatio);
          cv::imshow("", img);
          cv::waitKey(0);
         return 0;
         std::cin.get();
      } //end try
      catch ( std::exception const & ex )
      {
         std::string errMsg = ex.what();
         printf( "%s\n", errMsg.c_str() );
      }
      catch ( ... )
      {
         printf( "Error: unknown exception\n" );
      }



   }

Basic Drawing, And to draw the rook we employed MyLine, rectangle and a MyPolygon: Point( 0, 7*w/8.0 ), Point( w, w), Scalar( 0, 255, 255 ), -1, 8 ); /// 2.c. which means Red in BGR; Since thickness = -1, the circle will be drawn filled. How do we fill all pixels inside the circular boundary with white ? MATLAB has a function called imfill that allows you to fill holes, and you can use it in the following way. % MATLAB code for filling holes in a binary image. im = imfill(im,'holes'); imfill in OpenCV. There is no imfill function in OpenCV, but we can surely write one!

This answer is a generalization of the answer submitted by @Stephen Meschke in case anyone is interested

import cv2
import numpy as np

# Distance function
def distance(a,b): 
    return np.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2)

def RoundedRectPoints(topLeft,rectSz,cornerCurvature):
    # Define the rectangle parameters
    directions  = [(-1,0),(0,-1),(1,0),(0,1)]
    ro          = [(-1,-1),(1,-1),(1,1),(-1,1)]
    radius      = cornerCurvature*(rectSz[0]+rectSz[1]);
    increment   = 100
    angle       = 0
    corners     = [(topLeft[0]+rectSz[0],topLeft[1]+rectSz[1])]

    # Create list of corners
    for side in range(4): 
        corners.append((corners[side][0]+rectSz[side%2]*directions[side][0], corners[side][1]+rectSz[side%2]*directions[side][1]))

    # Compute the contour points for each side and corner
    contour_points = []
    for i in range(4):
        # Do the corner
        center = corners[i][0] + radius*ro[i][0], corners[i][1] + radius*ro[i][1]
        for angle_increment in range(increment):
            contour_points.append((int(center[0] + np.cos(angle) * radius), int(center[1] + np.sin(angle) * radius)))
            angle += .5*np.pi/increment
        # Do the line
        start = corners[i][0]+radius*directions[i][0], corners[i][1] + radius*directions[i][1]
        while distance(start, (corners[i][0]+radius*directions[i][0], corners[i][1] + radius*directions[i][1])) < np.min(rectSz)-2*radius:
            contour_points.append(start)
            start = start[0]+directions[i][0], start[1]+directions[i][1]
    return contour_points

# Draw the contour and show the image
img = np.zeros((600,600), np.uint8)
topLeft = (179,179)
rectSz = (321,321)
cornerCurvature = 0.09
contour_points = RoundedRectPoints(topLeft,rectSz,cornerCurvature)
cv2.drawContours(img, [np.array(contour_points, dtype=np.int32)], 0, 255, -1)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Drawing Fancy Round Rectangle using OpenCV Python, Here I will show how to implement OpenCV functions and apply them in various aspects using some great examples. Then the output will be visualized along with  Drawing functions work with matrices/images of arbitrary depth. The boundaries of the shapes can be rendered with antialiasing (implemented only for 8-bit images for now). All the functions include the parameter color that uses an RGB value (that may be constructed with CV_RGB or the Scalar_ constructor ) for color images and brightness for

OpenCV Drawing Functions, We can draw the various shapes on an image such as circle, rectangle, img = cv2.imread(r"C:\Users\DEVANSH SHARMA\cat.jpeg",1); cv2.circle(img,(80 The OpenCV provides a function to draw a simple, thick or filled up-right rectangle. OpenCV provides many drawing functions to draw geometric shapes and write text on images. Let’s see some of the drawing functions and draw geometric shapes on images using OpenCV. Some of the drawing functions are : cv2.line() : Used to draw line on an image. cv2.rectangle() : Used to draw rectangle on an image.

Draw geometric shapes on images using OpenCV, To demonstrate uses of the above-mentioned functions we need an image of size 400 X 400 filled with a solid colour (black in this case). Inorder to do this, We  Rectangle items are used to fill areas with solid color or gradients, and/or to provide a rectangular border. Appearance Each Rectangle item is painted using either a solid fill color, specified using the color property, or a gradient, defined using a Gradient type and set using the gradient property.

Draw filled ellipse matlab, For rectangle, I did it this way (need to fill the rectangle) but for ellipse it seems C++ and Python code for filling Vectors in MATLAB are represented by arrays,  Learn for free about math, art, computer programming, economics, physics, chemistry, biology, medicine, finance, history, and more. Khan Academy is a nonprofit with the mission of providing a free, world-class education for anyone, anywhere.

Comments
  • If I interpret this doc correctly, passing a negative thickness to cv::ellipse " indicates that a filled ellipse sector is to be drawn". So you could draw the four "corners" and then fill the reamaining "cross" (as rectangles).
  • Thank you for answering. I try this, but it will not fill the whole contour. Just the rounded corners where the partial ellipse is drawn
  • Why use math for math functions when you already have numpy imported? Also, it is recommended against multiple imports on one line, so I would refrain from putting that into answers, and similarly you should probably indent your code blocks and refrain from one-lining everything. More concisely, I would suggest to try and conform your code to PEP 8 when giving answers to nudge code towards being slightly more helpful to newbies. The answer and gif is great otherwise, btw.
  • Thank you very much for taking the time to answer me. This is a clever way to do this. My function need to be in C++, but I talk python too. However, my info is the left corner point and size of the box. With this code it is difficult for me to see how to use that info. I am analysing it and looks like this will draw rounded squares of side equal to leg. corner is the right lower corner of the square. I found a different way to solve this. However I will take the time to rework this to suit my purposes and publish it here. Thanks again.
  • I am creating a rounded rectangle by partilly drawing each of its edges. I am not sure I can use that function without creating some kind of contour.
  • Wow! Thank you so much for rewriting the code that I posted. It looks so much cleaner!