如何在openCV c ++中填充圆角矩形

问题描述 投票:0回答:4

我想方设法使用OpenCV C ++绘制一个圆角矩形。我的功能是:

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

现在我想填充矩形。我找到了一些填充函数,例如cv::fillPoly() and cv::fillConvexPoly,但是,我需要一个带点的向量。我如何从我的建筑中获得积分清单?

c++ opencv draw rounded-corners
4个回答
0
投票

要从使用cv::linecv::ellipse构造的形状中获取点,可以在黑色背景上绘制形状,然后找到该图像的轮廓。

另一种不使用lineellipse命令的方法是直接使用trig计算形状的轮廓。

rectangle being drawn

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

0
投票

使用cv :: floodFill和矩形内的起点。


0
投票

这是我的解决方案,以帮助任何人的id。

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



   }

0
投票

这个答案是对@Stephen Meschke提交的答案的概括,以防任何人感兴趣

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()
© www.soinside.com 2019 - 2024. All rights reserved.