资讯动态

OpenCV绘图函数详解:坐标系统、BGR通道与可视化实战

发布时间:2026/10/14 23:40:37 来源:尧图企业网站定制
1. 从画一条线开始为什么OpenCV的绘图函数值得单独花一篇文章很多刚接触OpenCV的朋友上来就急着去跑YOLO、人脸检测这种大项目结果一到可视化环节就卡住了。检测框怎么画关键点怎么标 FPS显示在画面上怎么写文字这些看似琐碎的问题恰恰是调试视觉算法时最频繁的操作之一。 我最初做图像处理Demo的时候也栽过不少跟头——不是坐标算错了就是颜色通道写反了画面显示出来一片花半天找不到原因。其实OpenCV的绘图函数没有那么玄乎核心就是几个函数line、circle、rectangle、ellipse、polylines、putText外加一个容易被忽略但非常常用的Rect类。它们各自负责一类基础几何图元的绘制组合起来能覆盖绝大多数图像标注场景。本文就基于我在实际项目中反复调用的经验把这些函数的参数、用法、坑点全部捋一遍让后面要接手视觉开发的朋友少走弯路。这类知识适合谁来读只要你在用OpenCV做任何事情——无论是做目标检测的框选可视化、车道线的线段标注、人脸关键点的点位绘制还是单纯的图像处理Demo开发这篇文章都值得收藏。我会按函数逐个拆每个函数都给出可复现的代码示例遇到需要额外敲黑板的地方也会单独拎出来说。2. Opencv绘图前的必修课图像坐标系与颜色通道2.1 坐标原点为什么在左上角在真正开始画图之前我强烈建议先花两分钟搞清楚OpenCV的坐标系统。这是所有绘图函数的基础一旦理解偏差画出来的东西位置就会完全不对。OpenCV的图像坐标系以左上角为原点(0,0)x轴水平向右递增y轴垂直向下递增。这一点和我们数学课上学的直角坐标系不一样——y轴方向是反的。很多新手第一次画线时把(100, 100)到(300, 300)的线段想象成从左上到右下这没问题但如果你想“画一条从左上到右下的对角线”写成(0,0)到(image.shape[1], image.shape[0])实际画出来的就是从左上角到右下角的那条对角线——等一下这个例子恰好是对的。真正容易搞错的是圆形和矩形的定位。比如我想在图像中央画一个点可能会自然地写下(width//2, height//2)这是正确的但如果想画一个中心在某个物体框左上角的圆很容易把圆心的坐标和框的坐标搞混。一个比较实用的记忆方式把图像坐标系当作屏幕坐标系因为绝大多数图像最终都是在屏幕上展示的。你在屏幕上看到的左上角原点、右为x正、下为y正就是OpenCV的坐标方式。写代码时如果需要从数学坐标系转换过来记得做y_new height - y_old - 1这样的翻转。2.2 BGR和RGB的坑以及一个通用的画布创建套路另一个高频坑点是颜色通道。OpenCV读入图像时默认通道顺序是BGR不是RGB。也就是说(255, 0, 0)在OpenCV里表示纯蓝色(0, 0, 255)才是纯红色。这个约定来源于早期硬件设计的习惯但坑的是很多其他库比如Matplotlib用的是RGB如果直接把OpenCV的图像丢给Matplotlib显示画面颜色会失真。我自己调试时会遇到这种情况明明画了一条“红色”的线显示出来却是蓝色。排查半天代码里写的是(0,0,255)没错啊结果发现是显示环境的锅——某个封装好的显示函数内部把图像转成了RGB颜色自然就错位了。为了在空白画布上练习我们会经常创建纯色背景图。这里给出一个常用的初始化方式import cv2 import numpy as np canvas np.zeros((480, 640, 3), dtypenp.uint8)这段代码创建一个高度480像素、宽度640像素的黑色画布每个像素有三个通道BGR。dtypenp.uint8很重要——图像像素值范围是0到255用8位无符号整数存储是OpenCV的标准格式。如果忘了指定dtype默认的float64会让后面的绘图函数在处理颜色时出现类型报错或者颜色值溢出。有了这块画布我们就可以开始逐个体验绘图函数了。我会沿用这个640x480的画布作为所有示例的展示基础。3. 逐个拆解六大绘图函数的参数、用法与现场经验3.1 画直线——line函数line是OpenCV里最基础的绘图函数了无论是边界标注还是辅助线都离不开它。看一下它的完整签名cv2.line(img, pt1, pt2, color, thickness1, lineType8, shift0)参数不清楚的我按实际使用频率来说明img要绘制的图像直接在原图上操作函数会修改这个图。pt1、pt2线段的起点和终点坐标格式是(x, y)的元组。color线的颜色BGR格式的元组。如果想画红色就是(0, 0, 255)。thickness线宽默认1。设为-1表示填充整个封闭图形这个技巧后面画圆和矩形时会派上大用场。lineType线型常见的是cv2.LINE_4、cv2.LINE_8、cv2.LINE_AA。其中cv2.LINE_AA是抗锯齿线画出来边缘更平滑看起来不刺眼代价是计算量稍大一点。对于一般调试来说LINE_8默认值就足够了如果画出来的线在屏幕上显得粗糙可以试试抗锯齿。我来演示一个实际例子在画布上画一条从左上到右下、带有一定角度的线。import cv2 import numpy as np canvas np.zeros((480, 640, 3), dtypenp.uint8) start_point (50, 50) end_point (600, 400) color (0, 0, 255) thickness 3 cv2.line(canvas, start_point, end_point, color, thickness) cv2.imshow(Line Demo, canvas) cv2.waitKey(0) cv2.destroyAllWindows()如果执行环境不支持窗口显示比如服务器上开发可以把cv2.imshow换成cv2.imwrite来保存图片查看。我经常在服务器上跑实验用cv2.imwrite保存中间结果这是长期有效的工作方式。一个容易被忽略的点是shift参数它的作用是坐标值左移位数用于子像素精度绘制。日常开发中一般用不到但如果你在做相机标定或需要超精细定位的场景可以留意一下。说一说我踩过的坑画线时传入的坐标类型。pt1和pt2必须是整数坐标或者能被存成整数的坐标。如果从某些检测结果里拿到的坐标是浮点数概率、缩放之后的结果不转换就直接传进去OpenCV会直接报错。所以我通常会在传参前做一次int()强转或者用np.int32()处理。3.2 画圆——circle函数圆形类别的物体检测结果可视化几乎统一用circle来画。比如人脸关键点、麦克风阵列分布图或者某种圆形工件的检测框。函数签名也不复杂cv2.circle(img, center, radius, color, thickness1, lineType8, shift0)center圆心坐标(x, y)格式。radius半径整数。thickness同样如果设为-1会填充整个圆。画一个实心的红色圆center (320, 240) radius 60 color (0, 0, 255) # 空心圆 cv2.circle(canvas, center, radius, color, 2) # 实心圆 cv2.circle(canvas, center, radius, color, -1)半径的选择在实际项目中经常会碰到一个问题——你得到的可能是“外接框”而非“半径”。这时有的同学会直接把框的宽度除以2当作半径来画圆看起来挺合理但要注意检测框的宽高是针对物体外接矩形的如果物体本身是倾斜或非圆的画出来的圆就会明显偏大或偏移。更好的做法是用物体中心到边缘的平均距离作为半径或者仔细分析物体的形态而不是简单除以2。另外一个实用小技巧画圆的时候可以用shift0但如果你需要画圆形轮廓且图像尺寸较大可以留意一下圆的边缘是否出现锯齿。增加线宽比如设为2或3通常能明显改善整体观感。3.3 画矩形和Rect相关用法——rectangle函数与Rect类矩形框应该是视觉项目中出现频率最高的图元了目标检测的框、ROI区域、文字标注的背景底板全都要靠它。rectangle函数有两种常用的调用方式# 方式一直接给左上角和右下角坐标 cv2.rectangle(img, pt1, pt2, color, thickness1) # 方式二传入Rect对象 cv2.rectangle(img, rect, color, thickness1)其中pt1是左上角(x1, y1)pt2是右下角(x2, y2)。第二种方式里的rect就是一个Rect对象。关于Rect的细节我下面单独说。画一个目标检测框加标签底板是视觉调试最常见的操作x1, y1 100, 50 x2, y2 400, 350 # 画检测框 cv2.rectangle(canvas, (x1, y1), (x2, y2), (0, 255, 0), 2) # 在框上方画一个实心的底板用于放文字文字内容调用putText后面具体讲 cv2.rectangle(canvas, (x1, y1 - 30), (x2, y1), (0, 255, 0), -1)这个底板技巧非常实用。直接把文字画在检测框上方的空白背景上可能因为背景图案复杂导致看不清。先画一个实心小矩形当底板再把白色文字放在上面整个标注的可读性会提升一大截。我在做实测项目的时候几乎每个检测框都会用这个组合看起来要比单纯画一条裸框专业得多。3.4 Rect类的常用接口与陷阱Rect不是绘图函数而是一个数据结构常见于很多OpenCV函数传入框参数的场景。但它和rectangle的搭配格外紧密所以放在这里说。Rect的构造方式是这样的rect cv2.Rect(x, y, width, height)注意参数是左上角坐标和宽高不是两个对角点。这一点非常容易搞混因为很多地方Rect被用来表示ROI从一个检测结果中取得的值可能已经是(x, y, w, h)格式其中x, y代表左上角坐标。如果你拿到的结果实际上是中心点坐标和宽高那就需要先换算一下x center_x - w // 2 y center_y - h // 2 rect cv2.Rect(x, y, w, h)Rect对象自身提供了几个很有用的属性和方法我常用的是rect.tl()返回左上角坐标。rect.br()返回右下角坐标。rect.area()返回矩形面积。rect.contains(point)判断某个点是否在矩形内。rect other_rect两个矩形取交集。rect | other_rect两个矩形取并集。用rect.tl()和rect.br()可以把Rect直接转换成rectangle需要的两对角点方便得很rect cv2.Rect(100, 50, 300, 300) cv2.rectangle(canvas, rect.tl(), rect.br(), (0, 255, 255), 2)一个我深有体会的坑Rect的宽高如果是从外接框计算出来的很容易忽略越界问题。图像边缘的目标它的框可能有一部分超出了图像边界。此时直接画框虽然不会报错但画出来的框不完整或者在某些后续处理中比如裁剪ROI会因坐标越界而崩溃。建议在做ROI裁剪或传递Rect之前先做一次边界约束x max(0, min(x, img_width - 1)) y max(0, min(y, img_height - 1)) w min(w, img_width - x) h min(h, img_height - y)这段代码看着啰嗦但确实能避免一批莫名其妙的崩溃问题。3.5 画椭圆——ellipse函数的两种用法ellipse函数参数比较多是这几个绘图函数里最容易让新手看懵的。它的核心有两种场景画完整椭圆和画椭圆弧。函数签名如下一种常用形式cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness1, lineType8, shift0)其中center椭圆中心坐标。axes包含两个值(half_width, half_height)的元组表示椭圆长半轴和短半轴的长度即从中心到边缘的距离不是完整直径。angle椭圆整体旋转的角度单位是度。0度表示长轴水平。startAngle、endAngle画弧时的起始和终止角度。这两个角度不是椭圆参数方程里的角度而是以椭圆中心为原点的极坐标系中的角度。如果直接使用数学里的离心角概念画出来的弧会和你想象的不一样。thickness同样支持-1填充。画一个完整的椭圆center (320, 240) axes (150, 80) angle 30 # 整体逆时针旋转30度 cv2.ellipse(canvas, center, axes, angle, 0, 360, (255, 0, 0), 2)这里startAngle0、endAngle360表示从0度画到360度正好是一个完整椭圆。如果只画0到180就是上半部分严格来说是极角0到180对应的那部分弧线。角度方向同样是逆时针而且0度对应正右方向。我的实操体会ellipse在项目中常用于三个方面——仪表盘刻度绘制、椭圆形的ROI标注以及旋转目标检测框的模拟可视化。比如检测结果是一个带旋转角度的目标盒用角度和宽高表示可以通过ellipse把物体外轮廓描出来比画直线连四个角点要省事画出来的结果也更接近目标本身的形态。另外cv2.fitEllipse这个函数返回的正好就是(center, axes, angle)这种格式可以直接喂给cv2.ellipse来可视化拟合结果# 假设points是一组二维点集 rotated_rect cv2.fitEllipse(points) cv2.ellipse(canvas, rotated_rect, (0, 255, 0), 2)fitEllipse返回的是一个RotatedRect但你直接把它当作参数传给ellipse是可以的。我这里单独提一下是因为很多做轮廓分析的朋友正好卡在这个衔接点上——明明拟合出了椭圆参数却不知道怎么画出来。3.6 画多边形——polylines函数与填充方式polylines用来画多条折线可以用来显示道路边界、分割掩码的轮廓、任意多边形区域等。函数签名cv2.polylines(img, pts, isClosed, color, thickness1, lineType8, shift0)pts点的集合。这是一个“点的数组的数组”通常用NumPy数组表示形状是(N, 1, 2)或(N, 2)。如果同时画多个多边形就传一个形状为(M, N, 2)的数组M表示多边形个数。isClosed布尔值True表示首尾相连False表示只是折线。一个经典示例——画一个三角形和一个任意五边形triangle np.array([[200, 100], [100, 300], [300, 300]], dtypenp.int32) pentagon np.array([[400, 100], [500, 150], [550, 250], [450, 350], [350, 250]], dtypenp.int32) cv2.polylines(canvas, [triangle], True, (0, 255, 0), 2) cv2.polylines(canvas, [pentagon], True, (255, 0, 0), 2)注意这一行np.array(..., dtypenp.int32)。我这里踩过好几次坑了——pts里的坐标必须是整数类型如果用了float数组polylines在某些版本的OpenCV下不会报错但画出来的图形位置会乱掉或者什么都不显示。想要浮点精度可以和line一样使用shift参数而不是直接传浮点数。fillPoly函数常和polylines一起出现用来填充封闭多边形区域cv2.fillPoly(canvas, [triangle], (0, 200, 200))很多场景需要把分割结果可视化出来比如语义分割的mask用不同颜色填充fillPoly就是最直接的实现方法之一。如果填充多边形时边缘有锯齿可以配合lineTypecv2.LINE_AA来改善。再分享一个项目经验用polylines绘制多条独立线段时如果线段数量很大比如关键点连线那种几百条一条一条地画line函数性能会比较差。这个时间可以把所有线段的首尾点集中到一个(N, 2, 2)的数组里用一次polylines调用画完效率提升非常明显。我实测过在嵌入式设备上跑推理可视化时这个优化能节省不少时间开销。3.7 在图像上写文字——putText函数最后一个基础函数是putText它的作用是在图像上添加文字。这在可视化调试里几乎是必需品——把类别名、置信度分数、FPS计数器显示在画面上全靠它。函数签名cv2.putText(img, text, org, fontFace, fontScale, color, thickness1, lineType8, bottomLeftOriginFalse)参数含义text要写的字符串。org文字的左下角坐标这是一个非常关键的定位点。很多新手以为文字是从这个点开始向左下方向展开的实际正好相反。org是文字盒子的左下角文字从这点向右上方向绘制。写文字时如果不加注意把org当成左上角来算坐标就会出现文字偏到图像外面的情况。fontFace字体类型。常用的是cv2.FONT_HERSHEY_SIMPLEX标准小字体、cv2.FONT_HERSHEY_COMPLEX更复杂一点的大字体、cv2.FONT_HERSHEY_TRIPLEX更粗的字体。fontScale字体大小缩放系数。1.0是基础大小2.0就是两倍大。thickness文字线条粗细。lineType和前面一样LINE_AA可以让字体边缘更平滑。一个常见写法label Cat: 0.95 org (x1, y1 - 5) # 文字左下角坐标放在框上方 cv2.putText(canvas, label, org, cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2, cv2.LINE_AA)这里有一个特别容易踩的坑org是左下角不是左上角。假如你的检测框左上角是(x1, y1)想让文字出现在框的正上方直接把org设成(x1, y1)是可以的但再往上偏移一点比如减小y坐标时要注意不要偏太多——你减的是org.y意味着文字整体往上移但因为org在文字底部减得过多就可能让文字顶到图像上边缘或者被裁掉。我一般在写检测标签文字之前会先算一下文字自身的宽度和高度保证放置位置不越界。OpenCV有一个专门函数cv2.getTextSize来获取文字尺寸(text_width, text_height), baseline cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.8, 2)拿到尺寸后就可以精确地判断文字是否会在图像外面必要时平移org坐标。这个函数用得越早后面排版越省心。4. 综合实操把绘图函数组合成一套完整的视觉标注工具4.1 模拟一个目标检测结果可视化流程基础函数逐个介绍完之后如果不把它们组合起来始终少了点实战的感觉。这里我用一个非常贴近实际项目的例子模拟检测到了画面里一个目标需要完成三件事——画出检测框、画出置信度文本、在中心画一个关键点。import cv2 import numpy as np img np.zeros((480, 640, 3), dtypenp.uint8) # 模拟检测结果目标类别 cat置信度 0.95框坐标 (140, 100, 300, 260) x1, y1, x2, y2 140, 100, 440, 360 label fcat: {0.95:.2f} # 1. 画检测框 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) # 2. 在框上方画一个图文标签底板 (text_w, text_h), baseline cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.7, 2) label_x x1 label_y max(y1 - 10, text_h 10) # 防止文字顶端越界 cv2.rectangle(img, (label_x, label_y - text_h - baseline), (label_x text_w, label_y), (0, 255, 0), -1) cv2.putText(img, label, (label_x, label_y - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2, cv2.LINE_AA) # 3. 在框中心画一个红色实心圆作为关键点 cx, cy (x1 x2) // 2, (y1 y2) // 2 cv2.circle(img, (cx, cy), 6, (0, 0, 255), -1) cv2.imshow(Detection Visualization, img) cv2.waitKey(0) cv2.destroyAllWindows()这段代码的要点在于底板、文字和检测框之间的坐标换算。getTextSize得到的text_h是文字高度baseline是文字基线以下的偏移距离。在OpenCV的字体体系里文字总体高度大约是text_h baseline。画底板时我把text_h baseline当作矩形的高度保证了文字不会溢出到底板之外整体观感是整齐的。这个组合我用的频率极高可以说只要做视觉可视化就绕不开这套流程。把它封装成一个函数后续所有检测项目的代码都能复用def draw_detection(img, x1, y1, x2, y2, label, color(0, 255, 0)): cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) (text_w, text_h), baseline cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.7, 2) label_x x1 label_y max(y1 - 10, text_h 10) cv2.rectangle(img, (label_x, label_y - text_h - baseline), (label_x text_w, label_y), color, -1) cv2.putText(img, label, (label_x, label_y - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2, cv2.LINE_AA)以后每检测到一个目标就调用一次draw_detection省时省力代码也干净。像这种从项目里沉淀下来的小函数积少成多之后会发现它们就是自己开发效率的加速器。4.2 画一个简易仪表盘椭圆弧、线条、文字的实战组合为了把ellipse和polylines也真实用起来我设计了一个简单又有点技术含量的场景画一个直角坐标系加一个圆弧扇形的示意图。这种图形在做路径可视化、角度范围标注时很常见。img np.zeros((480, 640, 3), dtypenp.uint8) center (320, 300) # 画两条坐标轴模拟x轴和y轴 cv2.line(img, (100, 300), (540, 300), (255, 255, 255), 2) # x轴 cv2.line(img, (320, 100), (320, 450), (255, 255, 255), 2) # y轴 # 画一个120度的扇形/椭圆弧 axes (120, 80) cv2.ellipse(img, center, axes, 0, 0, 120, (0, 255, 255), 2)这里startAngle0、endAngle120画的是从极角0度到120度的椭圆弧。极角方向是逆时针。如果我想画一个向下开口的圆弧区域可以设置起始角为180度、终止角为300度。实际项目中比如处理雷达数据或者机械臂工作空间可视化这类弧线经常用来表示可运动范围用ellipse一笔搞定比手动计算一堆点再连成线要灵活得多。画完弧线之后有些场景需要在弧线端点处做标记比如在小圆点处写上“起点”和“终点”。这时组合使用circle和putText坐标需要根据椭圆方程计算import math start_angle_rad math.radians(0) end_angle_rad math.radians(120) ax, ay axes[0], axes[1] start_point (int(center[0] ax * math.cos(start_angle_rad)), int(center[1] ay * math.sin(start_angle_rad))) end_point (int(center[0] ax * math.cos(end_angle_rad)), int(center[1] ay * math.sin(end_angle_rad))) cv2.circle(img, start_point, 5, (0, 0, 255), -1) cv2.circle(img, end_point, 5, (0, 0, 255), -1) cv2.putText(img, Start, (start_point[0] - 20, start_point[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) cv2.putText(img, End, (end_point[0] 5, end_point[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)这里要注意一点椭圆形弧线上的点坐标计算用的是带旋转角度的一般公式。如果不考虑旋转角angle0上面的公式是成立的如果angle不为0需要额外把坐标系旋转一下。实际项目中如果需要精确标注建议直接封装一个椭圆参数点的计算函数输入中心、轴长、旋转角和极角输出对应的坐标。5. 常见错误与排查经验实录绘图函数的坑大多是隐性的——不报错但画面结果不对。我结合自己调试项目的经历把最容易出问题的几个情况整理成一份速查表希望大家遇到类似现象时能快速定位。现象可能原因排查和修复办法画出的线条/图形颜色与预期不符BGR与RGB通道顺序搞混检查颜色元组顺序(255,0,0)是蓝色(0,0,255)是红色画出的图形位置完全不对坐标用了数学坐标系y轴向上把y坐标换算为height - y - 1后再传参画线/多边形时程序报错或图形消失坐标类型是浮点数用int()或np.int32()转换为整数文字位置偏出画面或与检测框错位把org当成左上角记住org是文字左下角用getTextSize量尺寸Rect区域裁剪时出现越界异常检测框超出图像边界裁剪前做边界约束max/min剪切大量绘制线段时程序卡顿严重逐条调用line用polylines一次性绘制所有线段再补充一个高频问题cv2.putText不支持中文。在OpenCV默认字体库里并不包含中文字符集。如果你试着在图像上写“猫”得到的很可能是乱码甚至直接报错。解决方法是自行渲染中文——一个常用的思路是用PILPillow先把中文文字画到透明图层上再转换格式贴到OpenCV图像中。具体流程是创建PIL图像用支持中文的字体绘制文字然后转成numpy数组和原图做叠加。因为本文重点是OpenCV基础绘图函数这个扩展用法我就不铺开讲了只做提醒。6. 一套绘图风格和性能的优化建议内容接近尾声时我再从实际工程角度分享几个关于绘图风格和性能的建议。视觉项目做久了会越来越重视一个概念标注是否清晰可读以及可视化是否会拖慢整体帧率。关于标注清晰度我常用的一条铁律是文字一定要有底板。直接在复杂背景上写白色文字遇到浅色背景时几乎看不清。而用rectangle先画一个彩色实心底板再把文字放上去无论背景多花哨文字都稳稳可读。配合getTextSize做尺寸测量后底板可以和文字严格贴合不会出现文字溢出的情况。另一个建议是统一封装可视化函数。我见过不少人调试代码时把画框、画点、写字的代码散落在主流程里结果同一个框有的地方是绿色、有的地方是红色粗细还不统一最后看结果图时很难快速提取有效信息。更好的做法是像我上面那节提到的那样把可视化封装成单独的函数模块颜色用常量管理框宽、字体大小、底板风格通过函数参数统一控制。项目进度越往后这种规范化的收益越大。关于性能除了前面提到的用polylines聚合绘制线段之外还有几个优化点减少不必要的绘图调用——如果目标在画面中静止不动且不需要实时标注可以考虑只在结果图上绘制一次而不是每一帧都重绘。控制图像尺寸——在高分辨率图像上画大量图形时绘图本身也会占用一些CPU时间。如果只是做快速预览可以先缩小图像再绘制效果差不多速度能快上不少。用整数坐标——浮点运算比整数慢而且前面说过polylines需要整数类型。强制使用整数坐标后整体效率也会更稳定。最后再分享一个小技巧。如果你需要同时展示多个类别的检测结果可以给每个类别分配一个固定的颜色并把颜色表提前定义好。绘制的时候根据类别索引颜色这样最终展示图会显得很规整也便于阅读。颜色表建议用BGR格式统一管理避免来回转换产生混乱。这些绘图函数看起来简单但积少成多它们就是视觉工程可视化的地基。把这些函数用熟练后面的检测、分割、关键点可视化都会顺手很多。我个人做项目的体会是——真正花时间把基础工具打磨清楚比急着跑通一个大模型要实在得多。至少当结果图画出来的时候你能一眼看出哪里不对劲而不是对着满屏花花绿绿的位置疑神疑鬼。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑