【问题标题】:Gradient mask blending in opencv pythonopencv python中的渐变蒙版混合
【发布时间】:2017-07-24 12:21:12
【问题描述】:

我有一个图像和圆形区域。我需要模糊所有,除了圆形区域。我还需要使圆的边界平滑。
输入:

输出(在带有掩码的图像编辑器中制作,但我认为 opencv 仅使用位图掩码):

现在我在 python 中有代码,它不会模糊圆圈的边界。

def blur_image(cv_image, radius, center, gaussian_core, sigma_x):
    blurred = cv.GaussianBlur(cv_image, gaussian_core, sigma_x)
    h, w, d = cv_image.shape
# masks
    circle_mask = np.ones((h, w), cv_image.dtype)
    cv.circle(circle_mask, center, radius, (0, 0, 0), -1)
    circle_not_mask = np.zeros((h, w), cv_image.dtype)
    cv.circle(circle_not_mask, center, radius, (2, 2, 2), -1)
# Computing
    blur_around = cv.bitwise_and(blurred, blurred, mask=circle_mask)
    image_in_circle = cv.bitwise_and(cv_image, cv_image, mask=circle_not_mask)
    res = cv.bitwise_or(blur_around, image_in_circle)
    return res

当前版本:
我怎样才能模糊圆圈的边界?在输出示例中,我在程序中使用了渐变蒙版。 opencv 中有类似的东西吗?
UPDATE 04.03
所以,我尝试了this answered topic 的公式以及我所拥有的:

代码:

def blend_with_mask_matrix(src1, src2, mask):
    res = src2 * (1 - cv.divide(mask, 255.0)) + src1 * cv.divide(mask, 255.0)
return res

此代码应该与最近的代码类似,但事实并非如此。圆圈中的图像略有不同。颜色有一些问题。 问题仍未解决。

【问题讨论】:

  • 看看THIS PAGE
  • @Jeru 我已经找到了一个合适的公式,但是在将它集成到 python 中时遇到了一些问题。 (mask/255) * blur + (1-mask/255)*another img。我试图在没有循环的情况下工作,只使用内置的 numpy 矩阵运算
  • 你的公式效果如何?
  • @Jeru 我是从link 得到的。主要问题是我不能在 255 上用掩码划分矩阵,因为我收到断言错误OpenCV Error: Assertion failed (depth == CV_8U || depth == CV_16U || depth == CV_32F)

标签: python opencv image-processing mask


【解决方案1】:

所以(mask/255) * blur + (1-mask/255)*another img 的主要问题是运营商。他们只使用一个频道。下一个问题是使用浮点数进行“平滑”。
我已将与 Alpha 通道混合的代码更改为:
1) 我正在为源图像和蒙版获取每个通道
2) 执行公式
3) 合并频道

def blend_with_mask_matrix(src1, src2, mask):
    res_channels = []
    for c in range(0, src1.shape[2]):
        a = src1[:, :, c]
        b = src2[:, :, c]
        m = mask[:, :, c]
        res = cv.add(
            cv.multiply(b, cv.divide(np.full_like(m, 255) - m, 255.0, dtype=cv.CV_32F), dtype=cv.CV_32F),
            cv.multiply(a, cv.divide(m, 255.0, dtype=cv.CV_32F), dtype=cv.CV_32F),
           dtype=cv.CV_8U)
        res_channels += [res]
    res = cv.merge(res_channels)
    return res

作为渐变蒙版,我只是使用模糊的圆圈。

def blur_image(cv_image, radius, center, gaussian_core, sigma_x):
    blurred = cv.GaussianBlur(cv_image, gaussian_core, sigma_x)

    circle_not_mask = np.zeros_like(cv_image)
    cv.circle(circle_not_mask, center, radius, (255, 255, 255), -1)
#Smoothing borders
    cv.GaussianBlur(circle_not_mask, (101, 101), 111, dst=circle_not_mask)
# Computing
    res = blend_with_mask_matrix(cv_image, blurred, circle_not_mask)
    return res

结果:

它的运行速度比没有更平滑边框的第一个版本要慢一些,但没关系。
结束问题。

【讨论】:

  • 感谢您发布解决方案。真的很有帮助。你也可以验证这个答案
【解决方案2】:

您可以使用以下功能轻松遮盖图像:

def transparentOverlay(src, overlay, pos=(0, 0), scale=1):
    overlay = cv2.resize(overlay, (0, 0), fx=scale, fy=scale)
    h, w, _ = overlay.shape  # Size of foreground
    rows, cols, _ = src.shape  # Size of background Image
    y, x = pos[0], pos[1]  # Position of foreground/overlay image

    # loop over all pixels and apply the blending equation
    for i in range(h):
        for j in range(w):
            if x + i >= rows or y + j >= cols:
                continue
            alpha = float(overlay[i][j][3] / 255.0)  # read the alpha channel
            src[x + i][y + j] = alpha * overlay[i][j][:3] + (1 - alpha) * src[x + i][y + j]
    return src

您需要传递源图像,然后是叠加蒙版和要设置蒙版的位置。 您甚至可以设置遮罩比例。像这样调用它。

transparentOverlay(face_cigar_roi_color,cigar,(int(w/2),int(sh_cigar/2)))

详情可以看这个链接:Face masking and Overlay using OpenCV python

输出:

【讨论】:

    【解决方案3】:

    我想也许你想要这样的东西。

    这是源图片

    源模糊对

    ma​​sk-alphablened-pair


    代码注释中有描述的代码。

    #!/usr/bin/python3
    # 2018.01.16 13:07:05 CST
    # 2018.01.16 13:54:39 CST
    import cv2
    import numpy as np
    
    def alphaBlend(img1, img2, mask):
        """ alphaBlend img1 and img 2 (of CV_8UC3) with mask (CV_8UC1 or CV_8UC3)
        """
        if mask.ndim==3 and mask.shape[-1] == 3:
            alpha = mask/255.0
        else:
            alpha = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)/255.0
        blended = cv2.convertScaleAbs(img1*(1-alpha) + img2*alpha)
        return blended
    
    img = cv2.imread("test.png")
    
    H,W = img.shape[:2]
    mask = np.zeros((H,W), np.uint8)
    cv2.circle(mask, (325, 350), 40, (255,255,255), -1, cv2.LINE_AA)
    mask = cv2.GaussianBlur(mask, (21,21),11 )
    
    blured = cv2.GaussianBlur(img, (21,21), 11)
    
    blended1 = alphaBlend(img, blured, mask)
    blended2 = alphaBlend(img, blured, 255- mask)
    
    cv2.imshow("blened1", blended1);
    cv2.imshow("blened2", blended2);
    cv2.waitKey();cv2.destroyAllWindows()
    

    一些有用的链接:

    1. OpenCV C++ 中的 Alpha 混合:Combining 2 images with transparent mask in opencv

    2. OpenCV Python 中的 Alpha 混合: Gradient mask blending in opencv python

    【讨论】:

      【解决方案4】:

      您可以尝试使用 PIL 库中的函数。 示例 -

      from PIL import Image, ImageFilter
      blur_factor = 3 # for smooth borders as you have mentioned
      
      blurred_mask = mask.filter(ImageFilter.GaussianBlur(blur_factor)) # your circle = 255, background = 0
      final_img = Image.composite(blurred_img, original_img, blurred_mask) # here blurred image is the one which you have already blurred, original image is your sharp non blurred image
      

      【讨论】:

        猜你喜欢
        • 2022-06-29
        • 1970-01-01
        • 1970-01-01
        • 2021-11-21
        • 1970-01-01
        • 1970-01-01
        • 2016-02-27
        • 2013-12-20
        相关资源
        最近更新 更多