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