Python OpenCV 绘制线宽

Bri*_*ter 4 python opencv draw

当指定大于 1 的线宽时,由 cv2.line() 绘制的结果线宽比指定的宽。指定 1、2、3、4、5、6 的粗细分别产生 1、3、5、5、7、7 的线宽。我尝试使用不同的 lineType 值 (4,8,16) 和带有 shift 参数的子像素点位置,而对线宽没有影响。难道我做错了什么?

例如:

import numpy as np
import cv2

a = np.zeros((10,10), dtype=np.uint8)
cv2.line(a, (0,4), (9,4), 1, 2)
print(a)
Run Code Online (Sandbox Code Playgroud)

产生:

 [[0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]
Run Code Online (Sandbox Code Playgroud)

DrV*_*DrV 7

你的问题很简单,答案也很简单:不,你没有做错任何事。OpenCV 中画线的实现似乎很基础。

我尝试了几种线宽以及分数开始和结束位置。线宽参数实际上不起作用。简单的 Brezenham 线(来自整数像素位置的单像素线)很好,但较粗的线不好。

看到这个测试代码:

import numpy as np
import cv2

a = np.zeros((200,200),dtype=np.uint8)
for u in np.exp(np.linspace(0,1j*2*np.pi,25)):
    cv2.line(a, (100, 100), (int(100+100*u.real+.5), int(100+100*u.imag+.5)), 255, 2)
cv2.imwrite('lines.png', a)
Run Code Online (Sandbox Code Playgroud)

你得到的是这样的:

在此处输入图片说明

线条粗细在很大程度上取决于角度;对角线比水平或垂直线粗得多。此外,正如您所注意到的,线条的粗细无论如何都是错误的(最薄的 3 个)。使用抗锯齿不会产生重大变化。

但是,如果用分数坐标来做,厚度变化较小(但厚度仍然是错误的):

import numpy as np
import cv2

a = np.zeros((200,200),dtype=np.uint8)
for u in np.exp(np.linspace(0,1j*2*np.pi,25)):
    cv2.line(a, (1600, 1600), (int(1600+1600*u.real+.5), int(1600+1600*u.imag+.5)), 255, 2, shift=4)
cv2.imwrite('lines_shift.png', a)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

此外,问题似乎随着粗线(粗细设置为 5,实际粗细 7,无小数坐标)而消失。这表明旋转相关误差是可加的:

在此处输入图片说明

然后让我们尝试用不同的灰度绘制宽度为 10、11 和 12 的重叠文件:

import numpy as np
import cv2

a = np.zeros((200,200),dtype=np.uint8)
for u in np.exp(np.linspace(0,1j*2*np.pi,25)):
    cv2.line(a, (100, 100), (int(100+100*u.real+.5), int(100+100*u.imag+.5)), 255, 12)
    cv2.line(a, (100, 100), (int(100+100*u.real+.5), int(100+100*u.imag+.5)), 128, 11)
    cv2.line(a, (100, 100), (int(100+100*u.real+.5), int(100+100*u.imag+.5)), 64, 10)
cv2.imwrite('lines_variation.png', a)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

原则上应该看到三种颜色,但实际上只有两种可见。这意味着宽度为 11 和 12 的线以相同的宽度 (13) 绘制。任何使用小数坐标的技巧都会产生相同的结果。

总结:只有奇数线宽可用。如果不使用分数(移位)坐标,窄线具有较大的相对宽度误差。如果您需要更多控制,请以更高的分辨率绘制更粗的线,然后下采样。(笨拙,我知道。)

上述测试是在 OpenCV 2.4.9 版上进行的。