Matplotlib - 多邊形選擇器



簡介

Matplotlib 沒有專用的多邊形選擇器小部件。但是,Matplotlib 提供了一種處理滑鼠事件的機制,我們可以使用這些事件處理功能來實現自定義多邊形選擇功能。

Matplotlib 允許我們捕獲滑鼠事件,例如按鈕點選、滑鼠移動和釋放。我們可以利用這些事件來實現多邊形選擇工具,使用者可以互動式地圍繞所需資料點繪製多邊形。

關鍵概念

以下是多邊形選擇器小部件的關鍵概念。

Matplotlib 中的事件處理

Matplotlib 提供了一個靈活的事件處理系統,允許我們捕獲使用者與繪圖的互動。常見的事件包括滑鼠點選、按鍵和移動。

Path 類

matplotlib.path 模組中的 Path 類表示一系列連線的線段和曲線段,可用於定義形狀,例如多邊形。我們將使用它來定義並檢查點是否在選定的多邊形內。

用例和擴充套件

以下是多邊形選擇器小部件的用例和擴充套件。

  • 區域選擇 - 自定義多邊形選擇器可用於透過允許使用者關注特定資料區域來定義和選擇繪圖中的特定感興趣區域。
  • 資料過濾 - 選定的多邊形點可用於過濾和分析已繪製資料集中的特定資料子集。
  • 與回撥函式的整合 - 我們可以透過整合響應多邊形選擇的回撥函式來擴充套件功能,從而允許根據選定區域執行自定義操作或分析。
  • 動態視覺化 - 實現動態視覺化更新,例如突出顯示多邊形內的點,可以增強使用者體驗。

自定義

我們可以根據特定需求增強和自定義多邊形選擇器。例如,我們可以新增清除當前多邊形的功能,根據所選區域動態更新繪圖,或將其整合到更大的互動式應用程式中。

實現步驟

現在讓我們一起了解在 Matplotlib 中建立自定義多邊形選擇器的基本示例的步驟。

匯入必要的庫

首先,我們必須匯入 Matplotlib 和 NumPy 庫,用於繪圖和陣列操作。

import matplotlib.pyplot as plt
import numpy as np

定義多邊形選擇器類

匯入必要的庫後,我們必須建立一個類來處理滑鼠事件,並允許使用者繪製多邊形。

class PolygonSelector:
   def __init__(self, ax):
      self.ax = ax
      self.polygon = None
      self.vertices = []
      self.cid_press = ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
      self.cid_release = ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
      self.cid_motion = ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

定義事件回撥

我們必須定義事件回撥來實現處理滑鼠按下、釋放和移動事件的方法。

示例

def on_press(self, event):
   if event.inaxes != self.ax:
      return

   if event.button == 1:  # Left mouse button
      if self.polygon is None:
         self.polygon = plt.Polygon([event.xdata, event.ydata], closed=False, fill=None, edgecolor='r')
         self.ax.add_patch(self.polygon)
         self.vertices.append((event.xdata, event.ydata))
   else:
      self.vertices.append((event.xdata, event.ydata))

def on_release(self, event):
   if event.inaxes != self.ax:
      return

   if event.button == 1:  # Left mouse button
      if len(self.vertices) > 2:
         self.vertices.append(self.vertices[0])  # Closing the polygon
         self.polygon.set_xy(np.array(self.vertices))
         plt.draw()

   def on_motion(self, event):
      if event.inaxes != self.ax:
         return

   if event.button == 1 and self.polygon is not None:
      self.vertices[-1] = (event.xdata, event.ydata)
      self.polygon.set_xy(np.array(self.vertices))
      plt.draw()

建立繪圖

接下來,我們必須生成樣本資料併為該生成的數建立繪圖。

x = np.random.rand(50)
y = np.random.rand(50)
fig, ax = plt.subplots()
ax.scatter(x, y)

初始化多邊形選擇器並顯示繪圖

現在用繪圖的座標軸例項化PolygonSelector類,然後顯示繪圖。

polygon_selector = PolygonSelector(ax)
plt.show()

現在讓我們將上述所有步驟組合在一起。

輸出
Create Plot

示例

import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.backend_bases import PickEvent
import numpy as np

class PolygonSelector:
   def __init__(self, ax):
      self.ax = ax
      self.points = []
      self.polygon = None
      self.cid_click = ax.figure.canvas.mpl_connect('button_press_event', self.on_click)
      self.cid_key = ax.figure.canvas.mpl_connect('key_press_event', self.on_key_press)

   def on_click(self, event):
      if event.inaxes == self.ax:
         if event.button == 1:  # Left mouse button
            self.points.append((event.xdata, event.ydata))
            self.update_polygon()

   def on_key_press(self, event):
      if event.key == 'enter':
         print("Polygon points:", self.points)
         self.reset_polygon()

   def update_polygon(self):
      if self.polygon:
         self.polygon.remove()
      if len(self.points) > 2:
         self.polygon = Polygon(self.points, edgecolor='red', alpha=0.2, closed=True)
         self.ax.add_patch(self.polygon)
         self.ax.figure.canvas.draw()

   def reset_polygon(self):
      self.points = []
      if self.polygon:
         self.polygon.remove()
         self.ax.figure.canvas.draw()

# Create a scatter plot with random data
np.random.seed(42)
x_data = np.random.rand(50)
y_data = np.random.rand(50)
fig, ax = plt.subplots()
ax.scatter(x_data, y_data)
# Initialize the PolygonSelector
polygon_selector = PolygonSelector(ax)
plt.show()
輸出
Polygon Selector

示例

這是一個在 matpltlib 繪圖上建立多邊形選擇器的另一個示例。

import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.backend_bases import PickEvent
import numpy as np
class PolygonSelector:
   def __init__(self, ax):
      self.ax = ax
      self.points = []
      self.polygon = None
      self.highlighted_points = None
      self.cid_click = ax.figure.canvas.mpl_connect('button_press_event', self.on_click)
      self.cid_key = ax.figure.canvas.mpl_connect('key_press_event', self.on_key_press)
   def on_click(self, event):
      if event.inaxes == self.ax:
         if event.button == 1:  # Left mouse button
            self.points.append((event.xdata, event.ydata))
            self.update_polygon()
   def on_key_press(self, event):
      if event.key == 'enter':
         self.highlight_points_inside_polygon()
         self.reset_polygon()
   def update_polygon(self):
      if self.polygon:
         self.polygon.remove()
         if len(self.points) > 2:
            self.polygon = Polygon(self.points, edgecolor='red', alpha=0.2, closed=True)
            self.ax.add_patch(self.polygon)
            self.ax.figure.canvas.draw()
   def reset_polygon(self):
      self.points = []
      if self.polygon:
         self.polygon.remove()
         self.ax.figure.canvas.draw()
   def highlight_points_inside_polygon(self):
      if self.highlighted_points:
         for point in self.highlighted_points:
            point.set_markersize(5)
         self.highlighted_points = []
      if self.polygon:
         path = self.polygon.get_path()
         points_inside_polygon = self.ax.plot([], [], 'o', markersize=8, markerfacecolor='yellow')[0]
         for i in range(len(self.ax.collections)):
            if isinstance(self.ax.collections[i], PickEvent):
               xs, ys = self.ax.collections[i].get_offsets().T
               points_inside = path.contains_points(np.column_stack((xs, ys)))
               self.highlighted_points.extend(
                  self.ax.plot(
                     xs[points_inside], ys[points_inside], 'o', markersize=8, markerfacecolor='yellow'))
               self.ax.figure.canvas.draw()

# Create a scatter plot with random data
np.random.seed(42)
x_data = np.random.rand(50)
y_data = np.random.rand(50)
fig, ax = plt.subplots()
ax.scatter(x_data, y_data)
# Initialize the PolygonSelector
polygon_selector = PolygonSelector(ax)
plt.show()
輸出
Polygon Selector

填充多邊形內的區域

在這個例子中,我們使用 matplotlib 庫填充多邊形內的區域。

示例
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon
import numpy as np
plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True
fig, ax = plt.subplots(1)
polygon = Polygon(np.random.rand(6, 2), closed=True, alpha=1)
collection = PatchCollection([polygon])
ax.add_collection(collection)
plt.show()
輸出
polygon_filler

注意 - 要在繪圖上繪製多邊形,請拖動游標,座標值將根據使用者選擇而變化。

廣告