Как сделать маску изображения, которая меняет часть изображения на градацию серого цвета?
Нужно наложить на изображение круг, за пределами которого изображение будет менять цвет на градацию серого цвета, а внутри круга цвет изображения не будет меняться.
В итоге, получилось только сделать так, чтобы цвет изображения за кругом менялся в негатив:
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 шт):
Автор решения: MaxU
→ Ссылка
Предлагаю решение с использованием 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:\download\mountain.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:\temp\out.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))
Автор решения: Alex Alex
→ Ссылка
Еще вариант:
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)
результат:




