如何使用 Python 用连续的非分支线包围热图上的某些像素?
How to encircle some pixels on a heat map with a continuous, not branched line using Python?
我正在使用 plt.imshow()
在网格上绘制值(在我的例子中是 CCD 数据)。示例图:
我需要在上面标出一个屏障,以显示我关心的像素。这与我需要的类似:
我知道如何添加, gridlines to an image,但是这些知识并不能解决问题,也不能在图片中添加单个方块,这也是我的能力范围内。我需要一条线环绕网格上的一个区域(这条线总是需要在像素之间穿过,而不是穿过它们,所以这可能会使它更简单一点)。
我该怎么做?
Iury Sousa has provided a nice work-around to the question above. However, it is not strictly circling the area with a line (rather plotting a mask to the picture and then covering most of it with the picture again), and it fails when I try to encircle overlapping group of pixels. ImportanceOfBeingErnest suggested in the comments that I should simply use the plt.plot
sample. Using Iury Sousa 的例子作为起点让我们有:
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
selected1 = Z>1.5
现在 selected1
是一个 布尔数组 数组,我们只想圈出相应 Z 值大于 1.5 的那些像素。我们还想圈出 selected2
,其中包含值高于 0.2 且低于 1.8 的像素的 True
值:
upperlim_selected2 = Z<1.8
selected2 = upperlim_selected2>0.2
Iury Sousa 的解决方法不适用于这种情况。 plt.plot
我认为会。什么是实现 selected1
和 selected2
循环的有效方法,使用 plt.plot
或其他方法?
我尝试了一些应该符合您需要的东西。
首先我定义了一个任意数据:
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
在这里您可以定义符合您要突出显示的模式的条件:
selected = Z>1.5
要绘图,您将使用 scatter
而不是 imshow
。您将绘制所有数据,然后将所选数据再绘制两次,一次使用带有突出显示颜色的较大方块,另一次通常使用相同的颜色参考和限制。
info = dict(marker='s',vmin=-2,vmax=2)
fig,ax = plt.subplots()
plt.scatter(X.ravel(),Y.ravel(),100,c=Z.ravel(),**info)
plt.scatter(X[selected].ravel(),Y[selected].ravel(),150,c='r',marker='s')
plt.scatter(X[selected].ravel(),Y[selected].ravel(),100,c=Z[selected].ravel(),**info)
ax.axis('equal')
类似于中的答案
您可以创建分辨率更高的网格并绘制 contour
图。
import numpy as np
import matplotlib.pyplot as plt
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
resolution = 25
f = lambda x,y: Z[int(y),int(x) ]
g = np.vectorize(f)
x = np.linspace(0,Z.shape[1], Z.shape[1]*resolution)
y = np.linspace(0,Z.shape[0], Z.shape[0]*resolution)
X2, Y2= np.meshgrid(x[:-1],y[:-1])
Z2 = g(X2,Y2)
plt.pcolormesh(X,Y, Z)
plt.contour(X2,Y2,Z2, [1.5], colors='r', linewidths=[1])
plt.show()
另一个对我有用的解决方案:
让我们以网格为例:
grid=[[0, 6, 8, 2, 2, 5, 25, 24, 11],
[4, 15, 3, 22, 225, 1326, 2814, 1115, 18],
[6, 10, 9, 201, 3226, 3549, 3550, 3456, 181],
[42, 24, 46, 1104, 3551, 3551, 3551, 3382, 27],
[9, 7, 73, 2183, 3551, 3551, 3551, 3294, 83],
[9, 7, 5, 669, 3544, 3551, 3074, 1962, 18],
[10, 3545, 9, 10, 514, 625, 16, 14, 5],
[5, 6, 128, 10, 8, 6, 7, 40, 4]]
我们绘制它:
plt.pcolormesh(grid)
假设我们要包围每个值大于1420的像素。我们创建一个布尔数组:
threshold=1420
booleangrid=np.asarray(grid)>threshold
intgrid=booleangrid*1
然后我们在每个像素周围创建一条线段:
down=[];up=[];left=[];right=[]
for i, eachline in enumerate(intgrid):
for j, each in enumerate(eachline):
if each==1:
down.append([[j,j+1],[i,i]])
up.append([[j,j+1],[i+1,i+1]])
left.append([[j,j],[i,i+1]])
right.append([[j+1,j+1],[i,i+1]])
并加入他们:
together=[]
for each in down: together.append(each)
for each in up: together.append(each)
for each in left: together.append(each)
for each in right: together.append(each)
(为清楚起见单独创建。)
我们遍历这些单独的线段,只保留那些只出现一次的线段,即在我们上面定义的布尔数组 (booleangrid
) 定义的特征边缘的线段:
filtered=[]
for each in together:
c=0
for EACH in together:
if each==EACH:
c+=1
if c==1:
filtered.append(each)
然后我们用for循环绘制网格和单独的线段:
plt.pcolormesh(grid)
for x in range(len(filtered)):
plt.plot(filtered[x][0],filtered[x][1],c='red', linewidth=8)
给我们结果:
有了它我们会很开心。
我正在使用 plt.imshow()
在网格上绘制值(在我的例子中是 CCD 数据)。示例图:
我需要在上面标出一个屏障,以显示我关心的像素。这与我需要的类似:
我知道如何添加
我该怎么做?
Iury Sousa has provided a nice work-around to the question above. However, it is not strictly circling the area with a line (rather plotting a mask to the picture and then covering most of it with the picture again), and it fails when I try to encircle overlapping group of pixels. ImportanceOfBeingErnest suggested in the comments that I should simply use the plt.plot
sample. Using Iury Sousa 的例子作为起点让我们有:
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
selected1 = Z>1.5
现在 selected1
是一个 布尔数组 数组,我们只想圈出相应 Z 值大于 1.5 的那些像素。我们还想圈出 selected2
,其中包含值高于 0.2 且低于 1.8 的像素的 True
值:
upperlim_selected2 = Z<1.8
selected2 = upperlim_selected2>0.2
Iury Sousa 的解决方法不适用于这种情况。 plt.plot
我认为会。什么是实现 selected1
和 selected2
循环的有效方法,使用 plt.plot
或其他方法?
我尝试了一些应该符合您需要的东西。
首先我定义了一个任意数据:
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
在这里您可以定义符合您要突出显示的模式的条件:
selected = Z>1.5
要绘图,您将使用 scatter
而不是 imshow
。您将绘制所有数据,然后将所选数据再绘制两次,一次使用带有突出显示颜色的较大方块,另一次通常使用相同的颜色参考和限制。
info = dict(marker='s',vmin=-2,vmax=2)
fig,ax = plt.subplots()
plt.scatter(X.ravel(),Y.ravel(),100,c=Z.ravel(),**info)
plt.scatter(X[selected].ravel(),Y[selected].ravel(),150,c='r',marker='s')
plt.scatter(X[selected].ravel(),Y[selected].ravel(),100,c=Z[selected].ravel(),**info)
ax.axis('equal')
类似于contour
图。
import numpy as np
import matplotlib.pyplot as plt
X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
resolution = 25
f = lambda x,y: Z[int(y),int(x) ]
g = np.vectorize(f)
x = np.linspace(0,Z.shape[1], Z.shape[1]*resolution)
y = np.linspace(0,Z.shape[0], Z.shape[0]*resolution)
X2, Y2= np.meshgrid(x[:-1],y[:-1])
Z2 = g(X2,Y2)
plt.pcolormesh(X,Y, Z)
plt.contour(X2,Y2,Z2, [1.5], colors='r', linewidths=[1])
plt.show()
另一个对我有用的解决方案:
让我们以网格为例:
grid=[[0, 6, 8, 2, 2, 5, 25, 24, 11],
[4, 15, 3, 22, 225, 1326, 2814, 1115, 18],
[6, 10, 9, 201, 3226, 3549, 3550, 3456, 181],
[42, 24, 46, 1104, 3551, 3551, 3551, 3382, 27],
[9, 7, 73, 2183, 3551, 3551, 3551, 3294, 83],
[9, 7, 5, 669, 3544, 3551, 3074, 1962, 18],
[10, 3545, 9, 10, 514, 625, 16, 14, 5],
[5, 6, 128, 10, 8, 6, 7, 40, 4]]
我们绘制它:
plt.pcolormesh(grid)
假设我们要包围每个值大于1420的像素。我们创建一个布尔数组:
threshold=1420
booleangrid=np.asarray(grid)>threshold
intgrid=booleangrid*1
然后我们在每个像素周围创建一条线段:
down=[];up=[];left=[];right=[]
for i, eachline in enumerate(intgrid):
for j, each in enumerate(eachline):
if each==1:
down.append([[j,j+1],[i,i]])
up.append([[j,j+1],[i+1,i+1]])
left.append([[j,j],[i,i+1]])
right.append([[j+1,j+1],[i,i+1]])
并加入他们:
together=[]
for each in down: together.append(each)
for each in up: together.append(each)
for each in left: together.append(each)
for each in right: together.append(each)
(为清楚起见单独创建。)
我们遍历这些单独的线段,只保留那些只出现一次的线段,即在我们上面定义的布尔数组 (booleangrid
) 定义的特征边缘的线段:
filtered=[]
for each in together:
c=0
for EACH in together:
if each==EACH:
c+=1
if c==1:
filtered.append(each)
然后我们用for循环绘制网格和单独的线段:
plt.pcolormesh(grid)
for x in range(len(filtered)):
plt.plot(filtered[x][0],filtered[x][1],c='red', linewidth=8)
给我们结果:
有了它我们会很开心。