OpenCV-Python学习之Draw-Functions

本文详细介绍了OpenCV-Python中的绘图函数,包括线、矩形、圆、椭圆、多边形线条及文字绘制。通过具体函数参数解析与源码分析,辅以实例代码,帮助读者深入理解并掌握这些常用绘图功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenCV-Python绘图函数

  本文是一篇基本的功能学习笔记,一直在使用opencv版本的各种画图函数,里面主要是每个接口函数的参数使用说明,加上基本c原码的基本分析。来系统了解一下opencv的各种画图函数使用。

函数cv2.line()
def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
"""
line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img
.   @brief Draws a line segment connecting two points.
.   
.   The function line draws the line segment between pt1 and pt2 points in the image. The line is
.   clipped by the image boundaries. For non-antialiased lines with integer coordinates, the 8-connected
.   or 4-connected Bresenham algorithm is used. Thick lines are drawn with rounding endings. Antialiased
.   lines are drawn using Gaussian filtering.
.   
.   @param img Image.
.   @param pt1 First point of the line segment.
.   @param pt2 Second point of the line segment.
.   @param color Line color. (B, G, R)
.   @param thickness Line thickness.
.   @param lineType Type of the line. See #LineTypes.
.   @param LineTypes: 
.          FILLED = -1
.          LINE_4 = 4
.          LINE_8 = 8
.          LINE_AA = 16
.   @param shift Number of fractional bits in the point coordinates.
"""

  线起点:pt1 = (startX, startY)
  线终点:pt2 = (endX, endY)
  色彩:color = (B, G, R)
  线宽:thickness

线段line源码简要分析:

void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color,
           int thickness, int line_type, int shift )
{
    CV_INSTRUMENT_REGION();

    Mat img = _img.getMat();
	// 判断输入line_type和图像的深度, 默认line_type = 8
    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;
	// 输入thickness 范围 [0 32767]
    CV_Assert( 0 < thickness && thickness <= MAX_THICKNESS );
    CV_Assert( 0 <= shift && shift <= XY_SHIFT );

    double buf[4];
    scalarToRawData( color, buf, img.type(), 0 );
    // ThickLine划线函数,内部根据输入参数条件调用Line, Line2, LineAA函数
    ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
}

测试用例如下:

import numpy as np
import cv2

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
pt1 = (128, 128)
pt2 = (255, 128)
color = (255, 0, 0)
thickness = 2
cv2.line(img, pt1, pt2, color, thickness)
# draw the show
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数cv2.rectangle()
def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
"""
rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img
.   @brief Draws a simple, thick, or filled up-right rectangle.
.   
.   The function cv::rectangle draws a rectangle outline or a filled rectangle whose two opposite corners
.   are pt1 and pt2.
.   
.   @param img Image.
.   @param pt1 Vertex of the rectangle.
.   @param pt2 Vertex of the rectangle opposite to pt1 .
.   @param color Rectangle color or brightness (grayscale image).
.   @param thickness Thickness of lines that make up the rectangle. Negative values, like #FILLED,
.   mean that the function has to draw a filled rectangle.
.   @param lineType Type of the line. See #LineTypes
.   @param LineTypes: 
.          FILLED = -1
.          LINE_4 = 4
.          LINE_8 = 8
.          LINE_AA = 16
.   @param shift Number of fractional bits in the point coordinates.
"""

  矩形左上角点:pt1 = (startX, startY)
  矩形右下角点:pt2 = (endX, endY)
  色彩:color = (B, G, R)
  线宽:thickness;若为负数,则矩形内填充color色彩

矩形框rectangle源码简要分析:

void rectangle( InputOutputArray _img, Point pt1, Point pt2,
                const Scalar& color, int thickness,
                int lineType, int shift )
{
    CV_INSTRUMENT_REGION();

    Mat img = _img.getMat();

    if( lineType == CV_AA && img.depth() != CV_8U )
        lineType = 8;

    CV_Assert( thickness <= MAX_THICKNESS );
    CV_Assert( 0 <= shift && shift <= XY_SHIFT );

    double buf[4];
    scalarToRawData(color, buf, img.type(), 0);

    Point2l pt[4];

    pt[0] = pt1;
    pt[1].x = pt2.x;
    pt[1].y = pt1.y;
    pt[2] = pt2;
    pt[3].x = pt1.x;
    pt[3].y = pt2.y;

    if( thickness >= 0 ) // 画线函数
        PolyLine( img, pt, 4, true, buf, thickness, lineType, shift );
    else  // 如果thickness<0 那么将其填满
        FillConvexPoly( img, pt, 4, buf, lineType, shift );
}

测试用例如下:

import numpy as np
import cv2

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
pt1 = (10, 10)
pt2 = (100, 100)
color = (0, 0, 255) # red
thickness = -1
cv2.rectangle(img, pt1, pt2, color, thickness)
# draw the show
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数cv2.circle()
def circle(img, center, radius, color, thickness=None, lineType=None, shift=None): 
    """
    circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
    .   @brief Draws a circle.
    .   
    .   The function cv::circle draws a simple or filled circle with a given center and radius.
    .   @param img Image where the circle is drawn.
    .   @param center Center of the circle.
    .   @param radius Radius of the circle.
    .   @param color Circle color.
    .   @param thickness Thickness of the circle outline, if positive. Negative values, like #FILLED,
    .   mean that a filled circle is to be drawn.
    .   @param lineType Type of the circle boundary. See #LineTypes
    .   @param shift Number of fractional bits in the coordinates of the center and in the radius value.
    """

  中心点:center
  半径:radius
  色彩:color = (B, G, R)
  线宽:thickness;若为负数,则圆内填充color色彩

画圆circle源码简要分析:

void circle( InputOutputArray _img, Point center, int radius,
             const Scalar& color, int thickness, int line_type, int shift )
{
    CV_INSTRUMENT_REGION();

    Mat img = _img.getMat();

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;
	// 对圆半径 线基本判断
    CV_Assert( radius >= 0 && thickness <= MAX_THICKNESS &&
        0 <= shift && shift <= XY_SHIFT );

    double buf[4];
    scalarToRawData(color, buf, img.type(), 0);

    if( thickness > 1 || line_type != LINE_8 || shift > 0 )
    {
        Point2l _center(center);
        int64 _radius(radius);
        _center.x <<= XY_SHIFT - shift;
        _center.y <<= XY_SHIFT - shift;
        _radius <<= XY_SHIFT - shift;
        EllipseEx( img, _center, Size2l(_radius, _radius),
                   0, 0, 360, buf, thickness, line_type );
    }
    else // 如果thickness<0 那么圆填充
        Circle( img, center, radius, buf, thickness < 0 );
}

测试用例如下:

import numpy as np
import cv2

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
center = (256, 256)
radius = 20
color = (255, 128, 0)
thickness = 1
cv2.circle(img, center, radius, color, thickness)
# draw the show
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数cv2.ellipse()
def ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness=None, lineType=None, shift=None): 
    """
    ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]]) -> img
    .   @brief Draws a simple or thick elliptic arc or fills an ellipse sector.
    .   
    .   The function cv::ellipse with more parameters draws an ellipse outline, a filled ellipse, an elliptic
    .   arc, or a filled ellipse sector. The drawing code uses general parametric form.
    .   A piecewise-linear curve is used to approximate the elliptic arc
    .   boundary. If you need more control of the ellipse rendering, you can retrieve the curve using
    .   #ellipse2Poly and then render it with #polylines or fill it with #fillPoly. If you use the first
    .   variant of the function and want to draw the whole ellipse, not an arc, pass `startAngle=0` and
    .   `endAngle=360`. If `startAngle` is greater than `endAngle`, they are swapped. The figure below explains
    .   the meaning of the parameters to draw the blue arc.
    .   
    .   ![Parameters of Elliptic Arc](pics/ellipse.svg)
    .   
    .   @param img Image.
    .   @param center Center of the ellipse.
    .   @param axes Half of the size of the ellipse main axes.
    .   @param angle Ellipse rotation angle in degrees.
    .   @param startAngle Starting angle of the elliptic arc in degrees.
    .   @param endAngle Ending angle of the elliptic arc in degrees.
    .   @param color Ellipse color.
    .   @param thickness Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that
    .   a filled ellipse sector is to be drawn.
    .   @param lineType Type of the ellipse boundary. See #LineTypes
    .   @param shift Number of fractional bits in the coordinates of the center and values of axes.
    
    
    
    ellipse(img, box, color[, thickness[, lineType]]) -> img
    .   @overload
    .   @param img Image.
    .   @param box Alternative ellipse representation via RotatedRect. This means that the function draws
    .   an ellipse inscribed in the rotated rectangle.
    .   @param color Ellipse color.
    .   @param thickness Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that
    .   a filled ellipse sector is to be drawn.
    .   @param lineType Type of the ellipse boundary. See #LineTypes
    """

  椭圆中心点:center
  长短半轴半径长度:axes
  旋转角度:angle
  起始角:startAngle
  终止角:endAngle
  色彩:color = (B, G, R)
  画线宽:thickness;若为负数,则圆内填充color色彩

画椭圆ellipse源码简要分析:

void ellipse( InputOutputArray _img, Point center, Size axes,
              double angle, double start_angle, double end_angle,
              const Scalar& color, int thickness, int line_type, int shift )
{
    CV_INSTRUMENT_REGION();

    Mat img = _img.getMat();

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;

    CV_Assert( axes.width >= 0 && axes.height >= 0 &&
        thickness <= MAX_THICKNESS && 0 <= shift && shift <= XY_SHIFT );

    double buf[4];
    scalarToRawData(color, buf, img.type(), 0);

    int _angle = cvRound(angle);
    int _start_angle = cvRound(start_angle);
    int _end_angle = cvRound(end_angle);
    Point2l _center(center);
    Size2l _axes(axes);
    _center.x <<= XY_SHIFT - shift;
    _center.y <<= XY_SHIFT - shift;
    _axes.width <<= XY_SHIFT - shift;
    _axes.height <<= XY_SHIFT - shift;
	// 椭圆绘图函数
    EllipseEx( img, _center, _axes, _angle, _start_angle,
               _end_angle, buf, thickness, line_type );
}

测试用例如下:

import numpy as np
import cv2

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
center = (256, 256)
axes = (28, 60)
angle = 30
startAngle = 0
endAngle = 360
color = (0, 0, 255)
thickness = 1
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness)
# draw the show
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数cv2.polylines()
def polylines(img, pts, isClosed, color, thickness=None, lineType=None, shift=None):
    """
    polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) -> img
    .   @brief Draws several polygonal curves.
    .   
    .   @param img Image.
    .   @param pts Array of polygonal curves.
    .   @param isClosed Flag indicating whether the drawn polylines are closed or not. If they are closed,
    .   the function draws a line from the last vertex of each curve to its first vertex.
    .   @param color Polyline color.
    .   @param thickness Thickness of the polyline edges.
    .   @param lineType Type of the line segments. See #LineTypes
    .   @param shift Number of fractional bits in the vertex coordinates.
    .   
    .   The function cv::polylines draws one or more polygonal curves.
    """

  点集:pts
  是否闭合:isClosed
  色彩:color = (B, G, R)
  画线宽:thickness;若为负数,则圆内填充color色彩

画多条线polylines源码简要分析:

void polylines( Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed,
                const Scalar& color, int thickness, int line_type, int shift )
{
    CV_INSTRUMENT_REGION();

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;

    CV_Assert( pts && npts && ncontours >= 0 &&
               0 <= thickness && thickness <= MAX_THICKNESS &&
               0 <= shift && shift <= XY_SHIFT );

    double buf[4];
    scalarToRawData( color, buf, img.type(), 0 );

    for( int i = 0; i < ncontours; i++ )
    {
        std::vector<Point2l> _pts(pts[i], pts[i]+npts[i]);
        PolyLine( img, _pts.data(), npts[i], isClosed, buf, thickness, line_type, shift );
    }
}
函数cv2.putText()
def putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None): 
    """
    putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) -> img
    .   @brief Draws a text string.
    .   
    .   The function cv::putText renders the specified text string in the image. Symbols that cannot be rendered
    .   using the specified font are replaced by question marks. See #getTextSize for a text rendering code
    .   example.
    .   
    .   @param img Image.
    .   @param text Text string to be drawn.
    .   @param org Bottom-left corner of the text string in the image.
    .   @param fontFace Font type, see #HersheyFonts.
    .   @param fontScale Font scale factor that is multiplied by the font-specific base size.
    .   @param color Text color.
    .   @param thickness Thickness of the lines used to draw a text.
    .   @param lineType Line type. See #LineTypes
    .   @param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise,
    .   it is at the top-left corner.
    """

  写入内容:text
  坐标位置:org
  类型:fontFace
  尺度大小:fontScale
  色彩:color = (B, G, R)
  画线宽:thickness;若为负数,则圆内填充color色彩

在图像上填写内容源码简要分析:

void putText( InputOutputArray _img, const String& text, Point org,
              int fontFace, double fontScale, Scalar color,
              int thickness, int line_type, bool bottomLeftOrigin )

{
    CV_INSTRUMENT_REGION();

    if ( text.empty() )
    {
        return;
    }
    Mat img = _img.getMat();
    const int* ascii = getFontData(fontFace);

    double buf[4];
    scalarToRawData(color, buf, img.type(), 0);

    int base_line = -(ascii[0] & 15);
    int hscale = cvRound(fontScale*XY_ONE), vscale = hscale;

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;

    if( bottomLeftOrigin )
        vscale = -vscale;

    int64 view_x = (int64)org.x << XY_SHIFT;
    int64 view_y = ((int64)org.y << XY_SHIFT) + base_line*vscale;
    std::vector<Point2l> pts;
    pts.reserve(1 << 10);
    const char **faces = cv::g_HersheyGlyphs;

    for( int i = 0; i < (int)text.size(); i++ )
    {
        int c = (uchar)text[i];
        Point2l p;

        readCheck(c, i, text, fontFace);

        const char* ptr = faces[ascii[(c-' ')+1]];
        p.x = (uchar)ptr[0] - 'R';
        p.y = (uchar)ptr[1] - 'R';
        int64 dx = p.y*hscale;
        view_x -= p.x*hscale;
        pts.resize(0);

        for( ptr += 2;; )
        {
            if( *ptr == ' ' || !*ptr )
            {
                if( pts.size() > 1 )
                    PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
                if( !*ptr++ )
                    break;
                pts.resize(0);
            }
            else
            {
                p.x = (uchar)ptr[0] - 'R';
                p.y = (uchar)ptr[1] - 'R';
                ptr += 2;
                pts.push_back(Point2l(p.x*hscale + view_x, p.y*vscale + view_y));
            }
        }
        view_x += dx;
    }
}

测试用例如下:

import numpy as np
import cv2

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
context = 'opencv'
text_loc = (50, 50)
font = cv2.FONT_HERSHEY_SIMPLEX
fontScale = 1
color = (0, 0, 255)
thickness = 1

pt1 = (50, 50)
pt2 = (200, 100)
cv2.rectangle(img, pt1, pt2, color, thickness)
cv2.putText(img, context, text_loc, font, fontScale, color, thickness, cv2.LINE_AA)

draw the show
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
参考

https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_drawing_functions/py_drawing_functions.html#drawing-functions

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值