TransWikia.com

Как сделать маску изображения, которая меняет часть изображения на градацию серого цвета?

Stack Overflow на русском Asked on September 28, 2020

Нужно наложить на изображение круг, за пределами которого изображение будет менять цвет на градацию серого цвета, а внутри круга цвет изображения не будет меняться.

В итоге, получилось только сделать так, чтобы цвет изображения за кругом менялся в негатив:

import matplotlib.cbook as cbook
import matplotlib.pyplot as plt
import numpy as np
import skimage.io as io
from skimage import color
import cv2
from skimage.color import rgb2gray
import matplotlib.image as mpimg

fig = plt.figure(figsize=(16,12))

ax_1 = fig.add_subplot(231)
ax_1.set(xticks=[], yticks=[])
ax_1.Img = io.imread ('Testphoto.jpg')

mask = ax_1.Img <87
l_x, l_y = ax_1.Img.shape[0], ax_1.Img.shape[1]
X, Y = np.ogrid[:l_x, :l_y]
outer_disk_mask = (X - l_x / 2)**2 + (Y - l_y/2)**2 > (l_x / 3)**2

img1 = ax_1.Img[outer_disk_mask]
ax_1.Img[outer_disk_mask] = img1-41


ax_1.axis('off')
ax_1.imshow(ax_1.Img)

Кто знает, как это можно реализовать?

Первая картинка на изображении:

Зона за кругом должна быть в градации серого.

2 Answers

Предлагаю решение с использованием OpenCV и Numpy:

import numpy as np
import cv2


def get_circle_mask(img, center=None, radius=None):
    height, width, depth = img.shape
    if center is None:
        center = (width // 2, height // 2)
    if radius is None:
        radius = min(height, width) // 4
    circle_mask = np.zeros((height, width), np.uint8)
    return cv2.circle(circle_mask, center, radius, 1, thickness=-1)
    
def mask_grayscale(img, mask, alpha=1.0, beta=1.0):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # convert grayscale to 3-channel grayscale image
    img_gray = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    # invert mask, to select the area outside of a circle
    inv_mask = (mask == 0).astype("int8")
    # overlay - black out all pixels outside of a circle
    overlay = cv2.bitwise_and(img, img, mask=mask)
    # background - black out all pixels inside of a circle
    background = cv2.bitwise_and(img_gray, img_gray, mask=inv_mask)
    out = background.copy()
    return cv2.addWeighted(overlay, alpha, out, beta, 0, out)
    

# fn = r"D:downloadmountain.jpg"
# img = cv2.imread(fn)

url = "https://www.alpinschule-ortler.com/uploads/tx_bh/titel_32.jpg"
cap = cv2.VideoCapture(url)
ret,img = cap.read()

mask = get_circle_mask(img)
out = mask_grayscale(img, mask)
cv2.imshow("result", out)
cv2.imwrite(r"c:tempout.jpg", out)

введите сюда описание изображения


UPDATE: используя функцию mask_grayscale() можно подсветить или затемнить каждую из частей изображения:

im_small = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
mask = get_circle_mask(im_small)

cv2.imshow("", mask_grayscale(im_small, mask, alpha=1.3, beta=0.6))

введите сюда описание изображения

cv2.imshow("", mask_grayscale(im_small, mask, alpha=0.6, beta=1.5))

введите сюда описание изображения

Correct answer by MaxU on September 28, 2020

Еще вариант:

import cv2
url = "https://www.alpinschule-ortler.com/uploads/tx_bh/titel_32.jpg"
cap = cv2.VideoCapture(url)
ret,img = cap.read()
height, width, depth = img.shape
center = (width // 2, height // 2)
radius = min(height, width) // 4
hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v=cv2.split(hsv)
mask=s.copy()
mask[:]=0
mask=cv2.circle(mask, center, radius, 255, thickness=-1)
s=cv2.bitwise_and(s, mask)
cv2.merge((h,s,v), dst=hsv)
img2=cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

cv2.imshow('sample', img2)

результат:

введите сюда описание изображения

Answered by Alex Alex on September 28, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP