Как добавить маску на изображение, размывающее их пересечение? - PullRequest
0 голосов
/ 15 мая 2019

У меня есть маска и фоновое изображение. Я хочу добавить эту маску на фоновое изображение и размыть (или, возможно, что-то вроде cv2.inpaint ()) пересечение, чтобы сделать его более естественным, но я заблокирован из-за эффекта размытия, любая помощь будет высоко оценена.


Подробнее: У меня есть два изображения RGB. Первое изображение (на переднем плане) связано с двоичной маской, которую я хотел бы добавить на второе изображение (фон).

Проблема в том, что когда мы смотрим на окончательное изображение, мы ясно видим, какая часть была добавлена ​​на фоновом изображении. Следовательно, я хотел бы добавить эффект размытия на пересечении маски и фонового изображения. На данный момент мой код выглядит так:

#foreground image: we'll use only the mask part
#background image:  where we will add the mask
foreground = cv2.imread(path1) 
background = cv2.imread(path2)

#Convert to float
foreground = foreground.astype(float)
background = background.astype(float)
mask = mask.astype(float)

#Multiply the foreground with the mask 
foreground = cv2.multiply(mask, foreground)

#Multiply the background with everywhere except with mask
background = cv2.multiply(1.0 - mask, background)

#Add the masked foreground to background image
outImage = cv2.add(foreground, background)

Я не мог найти простой способ сделать это, но я думаю, у них должен быть такой. Многие связанные ответы в Интернете работают с пороговым значением некоторого значения в пикселях, но это не может быть использовано здесь. На данный момент самый простой способ, который я нашел, это:

  1. создать маску части, которую я хочу размыть
  2. размытие конечных изображений (фон + маска переднего плана)
  3. взять из размытия изображения только часть маски 1) и добавить к ней исходное конечное изображение (фон + маска переднего плана)

Прежде чем сделать это, мне было интересно, будут ли у кого-нибудь какие-то советы.

1 Ответ

0 голосов
/ 21 мая 2019

То, как я это делаю, пока работает хорошо, но я остаюсь открытым для любого другого лучшего решения!Вот мое:

def foreground_background_into1(background, foreground, with_smooth=True, thickness=3, mask=[]):

    '''will add the foreground image to the background image to create a new image, with smooth intersection
    -foreground image: this image must be either black where there is no mask, or the mask parameter must be specified in 
    the mask parameter
    -background image:  image on which we will add the mask
    -mask: binary mask if foreground image does not already contain this information

    Note: not tested with mask'''

    #make a copy for the smooth part
    img = foreground.copy()

    #create binary mask (as needed to multiply with the backgound) from foreground image if not existing (replacing all value 
    #bigger than 0 to 1)
    if len(mask)==0:
        _,mask = cv2.threshold(foreground,1,1,cv2.THRESH_BINARY)

    #verification
    if foreground.shape!=background.shape:
        raise Warning("the foreground is not of same shape as background, we will convert it")
        foreground = imresize(foreground, size=background.shape)

    #if mask has one channel add two others
    if len(mask.shape)==2:
        mask = skimage.color.gray2rgb(mask)

    #add foreground to background
    foreground = foreground.astype(float)
    background = background.astype(float)
    mask = mask.astype(float)
    foreground = cv2.multiply(mask, foreground) 
    background = cv2.multiply(1 - mask, background) #is the initial background with black where the mask of forground
    outImage = cv2.add(foreground, background)
    result = outImage.astype(np.uint8)

    if with_smooth:

        #find contour
        foreground_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        ret,thresh = cv2.threshold(foreground_gray,1,255,0)
        _, contours, __ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        #create intersection_mask
        intersection_mask = cv2.drawContours(np.zeros(foreground.shape, np.uint8),
                                             contours,-1,(0,255,0),thickness)

        #inpaint the contour in the first final image
        intersection_mask = cv2.cvtColor(intersection_mask, cv2.COLOR_BGR2GRAY)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1,1))
        intersection_mask = cv2.dilate(intersection_mask, kernel, iterations=1)
        result = cv2.inpaint(result,intersection_mask,1,cv2.INPAINT_TELEA)

    return(result)

Я в основном добавляю маску к фоновому изображению, а затем сглаживаю часть пересечения, окрашивая с помощью openCV контур маски.

...