我正在尝试找到图像的轮廓并将它们(具有一定的透明度)覆盖在另一个图像上。但是,当我执行以下代码时,我得到了一个不想要的效果(见下图)。
img = cv2.imread('image1.bmp',cv2.IMREAD_GRAYSCALE)
contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
im = cv2.imread('image2.jpg')
im_copy = im.copy()
for j,cont in enumerate(contours):
im_copy = cv2.drawContours(im_copy, [cont], -1, (0, 0, 255), -1)
im = cv2.addWeighted(im_copy, 0.4, im, 1 - 0.2, 0)
im = cv2.drawContours(im, [cont], -1, (0, 0, 255), 0)
cv2.imwrite(f'projects/{prj.name}/logs/repeated_img/{file}', im)
我调用 drawContours()
两次以获得半透明填充和实心边框。显然,其中一个轮廓似乎比另一个更不透明。我怀疑同一轮廓的 drawContours 被调用了两次,所以我尝试了以下更改:
im_copy = cv2.drawContours(im_copy, [cont], j, (0, 0, 255), -1)
im = cv2.addWeighted(im_copy, 0.4, im, 1 - 0.2, 0)
im = cv2.drawContours(im, [cont], j, (0, 0, 255), 0)
尝试绘制第二个轮廓时会产生以下错误:
(-215:Assertion failed) 0 <= contourIdx && contourIdx < (int)last in function 'drawContours'
轮廓会根据某些条件以不同的颜色绘制,因此我需要能够独立绘制它们。
是什么导致了这种不良影响?
编辑
回答评论,使用以下代码转换为rbga
im = cv2.imread('image2.jpg')
im = cv2.cvtColor(im, cv2.COLOR_BGR2BGRA)
im_copy = im.copy()
for j,cont in enumerate(contours):
im_copy = cv2.drawContours(im_copy, [cont], -1, (0, 0, 255,128), -1)
im = cv2.drawContours(im, [cont], -1, (0, 0, 255, 255), 0)
结果如下图:
答案 0 :(得分:1)
这是在 Python/OpenCV 中执行此操作的一种方法。为了演示,我将在最大的区域上绘制一个部分透明的红色轮廓。我通过在输入上绘制一次全红色然后与原始输入混合来做到这一点。我看不到直接绘制部分透明轮廓的方法。
输入:
import cv2
import numpy as np
# read image
img = cv2.imread('scan.png')
hh, ww = img.shape[:2]
# convert to gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# get largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# draw red filled contour on image background
back = img.copy()
cv2.drawContours(back, [big_contour], 0, (0,0,255), -1)
# blend with original image
alpha = 0.25
result = cv2.addWeighted(img, 1-alpha, back, alpha, 0)
# write results
cv2.imwrite('scan_transparent_contour.png', result)
# show results
cv2.imshow("img", img)
cv2.imshow("thresh", thresh)
cv2.imshow("result", result)
cv2.waitKey(0)
结果:
答案 1 :(得分:0)
该问题是由 addWeight() 引起的,因为每个轮廓调用一次。这导致一些轮廓与原始图像的权重超过一倍,因此一些区域看起来更透明。我通过以下方式解决了这个问题:
im = cv2.imread('image1.jpg')
im_copy = im.copy()
alpha = 0.5
for cont in contours:
if cv2.contourArea(cont) <= 1:
im_copy = cv2.drawContours(im_copy, [cont], -1, (0, 0, 255), -1)
else:
im_copy = cv2.drawContours(im_copy, [cont], -1, (51, 197, 255), -1)
filled = cv2.addWeighted(im, alpha, im_copy, 1-alpha, 0)
for cont in contours:
if cv2.contourArea(cont) <= 1:
result = cv2.drawContours(filled, [cont], -1, (0, 0, 255), 0)
else:
result = cv2.drawContours(filled, [cont], -1, (51, 197, 255), 0)
cv2.imwrite('result.bmp', result)