在散点图中绘制感兴趣区域并打印matplotlib中包含的点

1 投票
1 回答
5605 浏览
提问于 2025-04-17 23:20

在一个散点图矩阵中,我想画一个感兴趣的区域(ROI),并打印出这个区域内的点。目前,我可以在子图中画出区域,但我不知道怎么获取并打印出那些在这个区域里的点。画区域时,需要按住 shift 键和左键鼠标。要关闭这个区域,则需要在按住 shift 键的同时,点击右键。关于如何打印出ROI内的点(类似于 LassoSelector演示 的功能),任何建议都非常感谢!提前谢谢大家!!

以下是代码:

 from pylab import *


 class ROI:

    def __init__(self, axes, fig):
        self.previous_point = []
        self.start_point = []
        self.end_point = []
        self.line = None    

        self.fig =  fig
        self.fig.canvas.draw()

    def motion_notify_callback(self, event):
        if event.inaxes: 
            axes = event.inaxes
            x, y = event.xdata, event.ydata
            if event.button == None and self.line != None and event.key == 'shift': # #Move line around
                self.line.set_data([self.previous_point[0], x],
                                   [self.previous_point[1], y])
                self.fig.canvas.draw()
         elif event.button == 1 and event.key == 'shift': # Free Hand Drawing
                    line = Line2D([self.previous_point[0], x],
                                  [self.previous_point[1], y])
                    axes.add_line(line)
                    self.previous_point = [x, y]
                    self.fig.canvas.draw()


    def button_press_callback(self, event):
        if event.inaxes: 
            x, y = event.xdata, event.ydata
            axes = event.inaxes
            if (event.key == 'shift') and (event.button == 1):  # If you press the right button
                    if self.line == None: # if there is no line, create a line
                        self.line = Line2D([x,  x],
                                           [y, y],
                                           marker = 's')
                        self.start_point = [x,y]
                        self.previous_point =  self.start_point
                        axes.add_line(self.line)
                        self.fig.canvas.draw()
                    # add a segment
                    else: # if there is a line, create a segment
                        self.line = Line2D([self.previous_point[0], x],
                                           [self.previous_point[1], y],
                                           marker = 'o')
                        self.previous_point = [x,y]
                        event.inaxes.add_line(self.line)
                        self.fig.canvas.draw()

            if (event.button == 3) and (event.key == 'shift') and (self.line != None): # close the loop
                        self.line.set_data([self.previous_point[0], self.start_point[0]],
                                           [self.previous_point[1], self.start_point[1]])                       
                        axes.add_line(self.line)
                        self.fig.canvas.draw()
                        self.line = None




def main():
    data = np.random.rand(100,4)
    plt.close("all")
    x, y = data[:, 0], data[:, 1]
    x1, y1 = data[:,2], data[:, 3]
    fig, axes = plt.subplots(ncols=2, nrows=1)
    for ax, marker in zip(axes.flat, ['o', 'o']):



        axes.flat[0].plot(x, y, 'r',  ls='', marker=marker, picker=3)

        axes.flat[1].plot(x, x1,'r', ls='', marker=marker, picker=3)

        cursor = ROI(ax, fig)

    #axes.set_title(" shift+left click: line segment       shift+left pressed: doodle        shift+right click: close region")

    fig.canvas.mpl_connect('motion_notify_event', cursor.motion_notify_callback)
    fig.canvas.mpl_connect('button_press_event', cursor.button_press_callback)
    show()

if __name__ == "__main__":
    main()   

1 个回答

1

我觉得matplotlib有一个很不错的功能,叫做matplotlib.nxutils,可以用来检查某些点是否在多边形内部。

http://matplotlib.org/faq/howto_faq.html#test-whether-a-point-is-inside-a-polygon

你可以把你的感兴趣区域(ROI)转换成一个多边形,然后使用nx.points_inside_poly来检查。

(编辑)不过matplotlib.nxutils已经被淘汰,换成了matplotlib.path.Path.contains_points。我之前不知道这个,谢谢提醒。这里有一小段代码示例,使用了Path.contains_points。

from pylab import *
from matplotlib.path import Path
import matplotlib.patches as patches

data = np.random.rand(100,4)

verts = [(0.3, 0.7), (0.3, 0.3), (0.7, 0.3), (0.7, 0.7)]

path1 = Path(verts)
index = path1.contains_points(data[:,:2])

print data[index, :2]

plot(data[:,0],data[:,1], 'b.')
patch = patches.PathPatch(path1, facecolor='orange', lw=2)
gca().add_patch(patch)
plot(data[index,0], data[index,1], 'r.')
show()

撰写回答