opencv 覆盖填充的半透明轮廓

mrfwxfqh  于 2023-08-06  发布在  其他
关注(0)|答案(3)|浏览(105)

我试图找到一个图像的轮廓,并将它们(用一些透明度)覆盖在另一个图像上。然而,当我执行下面的代码时,我得到了一个不希望的效果(见下图)。

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)


结果如下图所示:


f45qwnt8

f45qwnt81#

下面是在Python/OpenCV中实现这一点的一种方法。为了演示,我将在最大的区域上绘制一个部分透明的红色轮廓。我通过在输入上绘制一次全红色,然后与原始输入混合来实现这一点。我看不出有什么办法可以直接画出部分透明的轮廓。
输入:
x1c 0d1x的数据

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)

字符串
结果如下:


qkf9rpyu

qkf9rpyu2#

该问题是由addWeight()引起的,因为每个轮廓调用一次。这导致一些轮廓与原始图像的权重超过1,因此一些区域看起来更透明。我用以下方法解决了这个问题:

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)

字符串

bqjvbblv

bqjvbblv3#

更高效的this answer实现:

import cv2
import numpy as np

def draw_contours(
    frame: np.array,
    contours: tuple,
    indices: int = -1, 
    thickness = 1, 
    color: tuple = (0, 0, 255),
    alpha: float = 0.4,
):
    """
    Draw in-place some contours in a frame.
 
    Args:
        frame (np.array): The input frame.
        contours (tuple): The contours defining the mask.
        indices (int): The index of the contours to be drawn.
            Pass ``-1`` to consider all of them.
        color (tuple): The color used to draw the contours.
        alpha (float): A value between ``0.0`` (transparent)
            and ``1.0`` (opaque).
        thickness (int): The thickness of the contours.
    """
    if alpha:
        mask = np.zeros(frame.shape, np.uint8)
        cv2.drawContours(mask, contours, indices, color, -1)
        frame[:] = cv2.addWeighted(mask, alpha, frame, beta=1.0, gamma=0.0)
    cv2.drawContours(frame, contours, indices, color, thickness)

字符串

相关问题