Python 如何为numpy阵列创建圆形遮罩?

Python 如何为numpy阵列创建圆形遮罩?,python,arrays,numpy,image-processing,Python,Arrays,Numpy,Image Processing,我试图在Python中循环屏蔽一个图像。我在网上找到了一些示例代码,但我不确定如何更改数学以使我的圆圈位于正确的位置 我有一个图像image\u data,类型为numpy.ndarray,形状(37254797,3): 我看到这段代码应用欧几里德距离来计算距离中心的距离,但我不理解X-total行和Y-total列的部分。这将生成一个四分之一圆的遮罩,其中心位于图像的左上角 X和Y在圆圈中扮演什么角色?我如何修改这段代码以生成一个位于图像其他位置的掩模?您在线获得的算法部分错误,至少出于您的目

我试图在Python中循环屏蔽一个图像。我在网上找到了一些示例代码,但我不确定如何更改数学以使我的圆圈位于正确的位置

我有一个图像
image\u data
,类型为
numpy.ndarray
,形状
(37254797,3)

我看到这段代码应用欧几里德距离来计算距离中心的距离,但我不理解X-total行和Y-total列的部分。这将生成一个四分之一圆的遮罩,其中心位于图像的左上角


X
Y
在圆圈中扮演什么角色?我如何修改这段代码以生成一个位于图像其他位置的掩模?

您在线获得的算法部分错误,至少出于您的目的。如果我们有下面的图像,我们希望它像这样伪装:

创建这样一个掩码的最简单的方法是你的算法是如何进行的,但是它不是以你想要的方式呈现的,也不能让你以一种简单的方式修改它。我们需要做的是查看图像中每个像素的坐标,并获得该像素是否在半径内的真/假值。例如,这里有一张放大的图片,显示圆半径和严格在该半径范围内的像素:

现在,为了找出哪些像素位于圆内,我们需要图像中每个像素的索引。该函数提供两个向量,每个向量包含像素位置(或索引):列索引有一个列向量,行索引有一个行向量:

np.ogrid[:4,:5] [数组([[0], [1], [2], [3] 阵列([[0,1,2,3,4]])] 这种格式对我们来说很有用,所以如果我们在某些函数中使用它们,它实际上会创建一个包含所有索引的网格,而不仅仅是这两个向量。因此,我们可以使用
np.ogrid()
创建图像的索引(或像素坐标),然后检查每个像素坐标,看看它是在圆的内部还是外部。为了判断它是否在中心内,我们可以简单地找到从中心到每个像素位置的欧几里德距离,然后如果该距离小于圆半径,我们将其标记为包含在遮罩中,如果大于,我们将其从遮罩中排除

现在我们已经得到了创建这个掩码的函数所需的一切。此外,我们将为它添加一点不错的功能;我们可以输入中心和半径,或者让它自动计算它们

def创建圆形遮罩(h、w、中心=无、半径=无):
如果“中心”为“无”:#使用图像的中间部分
中心=(内部(w/2),内部(h/2))
如果半径为无:#使用中心和图像墙之间的最小距离
半径=最小值(中心[0],中心[1],w-中心[0],h-中心[1])
Y、 X=np.ogrid[:h,:w]
距离中心的距离=np.sqrt((X-中心[0])**2+(Y-中心[1])**2)

mask=dist_from_center我想提供一种不涉及np.ogrid()函数的方法。我将裁剪一个名为“robot.jpg”的图像,它是491 x 491像素。为了可读性,我不会像在实际程序中那样定义那么多变量:

导入库:

import matplotlib.pyplot as plt
from matplotlib import image
import numpy as np
导入图像,我称之为“z”。这是一个彩色图像,所以我也只提取一个彩色通道。接下来,我将显示它:

z = image.imread('robot.jpg')  
z = z[:,:,1]

zimg = plt.imshow(z,cmap="gray")
plt.show()

为了得到一个numpy数组(图像矩阵),其中有一个圆用作遮罩,我将从以下内容开始:

x = np.linspace(-10, 10, 491)
y = np.linspace(-10, 10, 491)
x, y = np.meshgrid(x, y)
x_0 = -3
y_0 = -6
mask = np.sqrt((x-x_0)**2+(y-y_0)**2)
请注意最后一条线上的圆方程,其中x_0和y_0定义了网格中圆的中心点,网格的高度和宽度为491个元素。因为我在x和y中定义了从-10到10的栅格,所以x_0和x_y设置圆的中心点相对于图像的中心

要查看生成的内容,我运行:

maskimg = plt.imshow(mask,cmap="gray")
plt.show()

要将其转换为实际的二进制值掩码,我只需要将低于某个值的每个像素设置为0,然后将高于某个值的每个像素设置为256。“确定值”将以上面定义的相同单位确定圆的半径,因此我将其称为“r”。在这里,我将“r”设置为某个值,然后循环通过遮罩中的每个像素,以确定它是“开”还是“关”:

要反转遮罩,我可以在上面的阈值循环中交换0和256,如果我这样做,我得到:


这实际上不是欧几里德距离。应该是该总和的平方根。是的,我认为你是对的,应该是
center\u row
center\u col
而不是
total…
我认为这个代码会产生一个以左上角为中心的四分之一圆遮罩,而不是图像中的中心圆遮罩(注意
dist\u from\u center
在这种情况下仍然是错误的)@AlexanderReynolds是的,它正在形成一个四分之一圆的面具,你能解释一下你是如何确定的吗?你能简单地解释一下
np.ogrid
,网络上所有关于
np.ogrid
的解释都超出了我的想象。当然,当我看到这一点时我正在移动,所以没有写完整的答案,我想等我到家的时候会有其他人,但我想不会。我会努力的。@AlexanderReynolds谢谢,我会等待你的答复。+1。我在顶部添加了
如果h%2==0:h=h+1
如果w%2==0:w=w+1
,因此它不会剪切偶数的最后一列和最后一行。
maskimg = plt.imshow(mask,cmap="gray")
plt.show()
r = 7
for x in range(0,490):
        for y in range(0,490):
                if mask[x,y] < r:
                        mask[x,y] = 0
                elif mask[x,y] >= r:
                        mask[x,y] = 256

maskimg = plt.imshow(mask,cmap="gray")
plt.show()
z_masked = np.multiply(z,mask)

zimg_masked = plt.imshow(z_masked,cmap="gray")
plt.show()