简体   繁体   English

如何在 Python 中屏蔽任意形状的外部或内部?

[英]How to mask outside or inside an arbitrary shape in Python?

from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
import cv2
a=np.arange(1,9)
filename = 'image_file_0.tiff'
img = cv2.imread(filename)
x = np.array([389, 392, 325, 211, 92,103,194,310])
y = np.array([184,281,365,401,333,188,127,126])
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]
tck, u = interpolate.splprep([x, y], s=0, per=True)
xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck)
fig, ax = plt.subplots(1, 1)

ax.plot(xi, yi, '-b')
plt.imshow(img)
plt.show()

我的形象

I want to transform the pixel values of the outer or inner region after forming an arbitrary closed curve in the image.我想在图像中形成任意闭合曲线后转换外部或内部区域的像素值。 How do I do it?我该怎么做?

You can do it using the cv2.fillpoly function. Using this picture for example:您可以使用cv2.fillpoly function 来完成。以这张图片为例:

在此处输入图像描述

We can get the shape we want to mask using:我们可以使用以下方法获得我们想要遮罩的形状:

from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
import cv2
a=np.arange(1,9)
filename = 'image_file_0.tiff'
img = cv2.imread('image_left.png', cv2.IMREAD_COLOR)
x = np.array([289, 292, 125, 111,  40,  80, 94,210])
y = np.array([84 , 181, 265, 241,133, 88, 27,  40])
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]
tck, u = interpolate.splprep([x, y], s=0, per=True)
xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck)

plt.imshow(img[:,:,[2,1,0]])
plt.scatter(xi, yi)
plt.show()

This results in:这导致: 在此处输入图像描述

Now the masking can be done using:现在可以使用以下方法完成屏蔽:

contour = np.array([[xii, yii] for xii, yii in zip(xi.astype(int), yi.astype(int))])
mask    = np.zeros_like(img)
cv2.fillPoly(mask, pts=[contour], color=(255, 255, 255))
masked_img = cv2.bitwise_and(img, mask)

And the result:结果: 在此处输入图像描述

Using the inverted mask you manipulate the outer pixels as you wish:使用倒置蒙版,您可以根据需要操纵外部像素:

mask    = np.ones_like(img)*255
cv2.fillPoly(mask, pts=[contour], color=(0,0,0))
masked_img = cv2.bitwise_and(img, mask)

This results in:这导致:

在此处输入图像描述

Here's another way to do it using cv2.drawContours() .这是使用cv2.drawContours()的另一种方法。 The idea is to take your rough contour points, smooth them out, draw this contour onto a mask, then cv2.bitwise_and() or inverse bitwise-and to extract the desired regions.这个想法是获取粗略的轮廓点,将它们平滑,将此轮廓绘制到蒙版上,然后cv2.bitwise_and()或按位反转 - 并提取所需的区域。


Input image -> Generated mask输入图像->生成的掩码

Result -> Inverted result结果->反转结果

import numpy as np
import cv2
from scipy import interpolate

# Load image, make blank mask, define rough contour points
image = cv2.imread('1.jpg')
mask = np.zeros(image.shape, dtype=np.uint8) 
x = np.array([192, 225, 531, 900, 500])
y = np.array([154, 281, 665, 821, 37])
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]

# Smooth contours
tck, u = interpolate.splprep([x, y], s=0, per=True)
x_new, y_new = interpolate.splev(np.linspace(0, 1, 1000), tck)
smooth_contour = np.array([[[int(i[0]), int(i[1])]] for i in zip(x_new, y_new)])

# Draw contour onto blank mask in white
cv2.drawContours(mask, [smooth_contour], 0, (255,255,255), -1)
result1 = cv2.bitwise_and(image, mask)
result2 = cv2.bitwise_and(image, 255 - mask)

cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.waitKey()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM