首页 > 解决方案 > 无法在不创建副本的情况下在图像中画线。(问题仅存在于 .png 图像中)

问题描述

下面的代码不会在 png 图像上画任何线

imgPath = "./images/dummy.png"

img = cv2.imread(imgPath,cv2.IMREAD_UNCHANGED) 
imgBGR = img[:,:,:3] 
imgMask = img[:,:,3]

cv2.line(imgBGR, (200,100), (250,100), (0,100,255), thickness=9, lineType=cv2.LINE_AA)
plt.imshow(imgBGR[:,:,::-1])

关于创建 BGR 通道的副本并使用它来绘制线条作品。

imgPath = "./images/dummy.png"

img = cv2.imread(imgPath,cv2.IMREAD_UNCHANGED) 
imgBGR = img[:,:,:3] 
imgMask = img[:,:,3]

imgBGRCopy = imgBGR.copy()

cv2.line(imgBGRCopy , (200,100), (250,100), (0,100,255), thickness=9, lineType=cv2.LINE_AA)
plt.imshow(imgBGRCopy [:,:,::-1])

请解释为什么?

标签: pythonopencvopencv-python

解决方案


由于神秘的原因,OpenCV 无法在 NumPy 切片上绘图。

例如,请参见以下帖子:Why cv2.line can't draw on 1 channel numpy array slice inplace?

该错误与 PNG 与 JPEG 或 BGR 与 BGRA 无关。
该错误是因为您试图在切片上绘制。

例如,以下代码也失败:

imgBGR = cv2.imread('test.jpg', cv2.IMREAD_UNCHANGED)
imgB = imgBGR[:,:,0]  # Get a slice of imgBGR
cv2.circle(imgB, (100, 100), 10, 5)

作为替代方案,您可以在 BGRA 图像上绘图。

根据绘图功能文档:

注意当目标图像为 4 通道时,这些函数不支持 alpha 透明度。在这种情况下,颜色[3] 被简单地复制到重新绘制的像素。因此,如果要绘制半透明形状,可以在单独的缓冲区中绘制它们,然后将其与主图像混合。

以下代码正在工作:

img = cv2.imread(imgPath,cv2.IMREAD_UNCHANGED) 
cv2.line(img, (200,100), (250,100), (0,100,255), thickness=9, lineType=cv2.LINE_AA)

imgBGR = img[:,:,:3] 
plt.imshow(imgBGR[:,:,::-1])

注意:
Python 和 OpenCV 是“开源”的,所以理论上我们可以按照源代码来揭开问题的神秘面纱。


推荐阅读