前提・実現したいこと
独学でPythonの学習をしております。
3次元のデータをAxes3Dにて3次元グラフ上で表示し、そのグラフの隣に各座標に対応する画像を表示させたいと考えております。
具体的には今回のサンプルプログラムでプロットされている30点それぞれに画像が用意されており、マウスと一番近い座標にあるポイントに対応する画像を表示します。
3次元グラフの必要事項としてマウスオーバーでラベル表示させる必要があり、以下のサイトを参考にプログラムを作成しました。
参考プログラムの流れ
参考サイト
[https://www.xspdf.com/help/51593042.html]
visualize3DDataにてグラフを用意し、マウスイベントを監視する。
↓
onMouseMotionにてマウスイベントを取得。
↓
calcClosestDatapointとdistanceにてマウスに一番近い座標を計算する。
↓
annotatePlotにてマウスから一番近い座標にラベルを追加する。
↓
Print_Picにてマウスから一番近い座標に対応する画像を表示する。(この部分を追加したい)
発生している問題・エラーメッセージ
画像はax1=plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))で表示しようとしました。
3次元グラフと上記の画像を並べた際に「"'AxesSubplot' object has no attribute 'get_proj'"」とエラーが出る現象を解決したいです。
おそらく画像上にマウスカーソルを移動させた際に、画像には2次元座標しかないため「x2, y2, _ = proj3d.proj_transform(point[0], point[1], point[2], plt.gca().get_proj())」がエラーになっていると考えておりますが、
解決策がありましたらご教授いただければ幸いです。
コード
import
1import pandas as pd 2from PIL import Image 3import cv2 4import matplotlib 5matplotlib.use('tkagg') 6import matplotlib.pyplot as plt 7from mpl_toolkits.mplot3d import Axes3D 8from mpl_toolkits.mplot3d import proj3d 9 10def visualize3DData (X): 11 fig = plt.figure(figsize = (16,10)) 12 ax = fig.add_subplot(111, projection = '3d') 13 ax.grid(True) 14 ax.scatter(X[:, 0], X[:, 1], X[:, 2], depthshade = False, picker = True,s=2) 15 16 def distance(point, event): 17 assert point.shape == (3,), "distance: point.shape is wrong: %s, must be (3,)" % point.shape 18 x2, y2, _ = proj3d.proj_transform(point[0], point[1], point[2], plt.gca().get_proj()) 19 x3, y3 = ax.transData.transform((x2, y2)) 20 return np.sqrt ((x3 - event.x)**2 + (y3 - event.y)**2) 21 22 23 def calcClosestDatapoint(X, event): 24 distances = [distance (X[i, 0:3], event) for i in range(X.shape[0])] 25 return np.argmin(distances) 26 27 def annotatePlot(X, index): 28 if hasattr(annotatePlot, 'label'): 29 annotatePlot.label.remove() 30 x2, y2, _ = proj3d.proj_transform(X[index, 0], X[index, 1], X[index, 2], ax.get_proj()) 31 annotatePlot.label = plt.annotate( "Value %d" % index, 32 xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom', 33 bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5), 34 arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0')) 35 fig.canvas.draw() 36 37 38 def Print_Pic(X, index): 39 img = cv2.imread('test.png') 40 ax1 = fig.add_subplot(1,1,2) #これでエラーが出る 41 plt.show() 42 43 44 def onMouseMotion(event): 45 closestIndex = calcClosestDatapoint(X, event) 46 annotatePlot (X, closestIndex) 47 Print_Pic (X, closestIndex) 48 49 fig.canvas.mpl_connect('motion_notify_event', onMouseMotion) 50 plt.show() 51 52 53if __name__ == '__main__': 54 X = np.random.random((30,5)) 55 X=np.array(X, dtype=np.float64) 56 visualize3DData (X)
補足情報
Anaconda3
Python 3.7
Jupyter Notebookで描画しています。
エラー内容
ax1 = fig.add_subplot(1,1,2)を追加した際に以下のエラーがマウスイベント発生時に表示されます。
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\user\anaconda3\lib\tkinter_init_.py", line 1892, in call
return self.func(*args)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py", line 272, in motion_notify_event
FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 1903, in motion_notify_event
self.callbacks.process(s, event)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\cbook_init_.py", line 229, in process
self.exception_handler(exc)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\cbook_init_.py", line 81, in exception_printer
raise exc
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\cbook_init.py", line 224, in process
func(*args, **kwargs)
File "<ipython-input-1-848925ac800b>", line 48, in onMouseMotion
Print_Pic (X, closestIndex)
File "<ipython-input-1-848925ac800b>", line 41, in Print_Pic
ax1 = fig.add_subplot(1,1,2) #これでエラーが出る
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\figure.py", line 1402, in add_subplot
ax = subplot_class_factory(projection_class)(self, *args, **kwargs)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\axes_subplots.py", line 39, in init
self._subplotspec = SubplotSpec._from_subplot_args(fig, args)
File "C:\Users\user\anaconda3\lib\site-packages\matplotlib\gridspec.py", line 689, in _from_subplot_args
raise ValueError(
ValueError: num must be 1 <= num <= 1, not 2