はじめに
前回は「画像の座標を読み取る」ところまでのプログラムを紹介しましたが,今回は,そのプログラムをもとに,グラフ上の数値を読み取る(画像の座標からグラフ上の数値に変換する)ところをやってみました.
座標軸の入力精度が低く,大体の値しかでず,実務に使える代物ではありませんが,一応「こういうことをしたい」ということがイメージできる代物になったというところでしょうか.
課題としては,上述の通り,グラフの座標軸の入力精度を高めること,更に点のクリック時の精度を高めることだと思います.
ここから先はかなり難しそうです.
グラフ上の値への変換式
$$
x=x_{min}+(x_{max}-x_{min})\cdot \cfrac{k_{xx}-k_{xi}}{k_{xf}-k_{xi}}
$$
$$
y=y_{min}-(y_{max}-y_{min})\cdot \cfrac{k_{yy}-k_{yf}}{k_{yf}-k_{yi}}
$$
- $x$, $y$ : グラフ上のプロットの$x$および$y$座標
- $k_{xx}$, $k_{yy}$ : 画像領域のプロットの$x$および$y$座標
- $x_{min}$, $x_{max}$ : グラフ上のx軸の最小・最大
- $y_{min}$, $y_{max}$ : グラフ上のy軸の最小.最大
- $k_{xi}$, $k_{yi}$ : 画像領域におけるグラフの左上隅の座標
- $k_{xf}$, $k_{yf}$ : 画像領域におけるグラフの右下隅の座標
プログラム
py_img_test1.py
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import warnings;warnings.filterwarnings('ignore')
im=Image.open('fig_PSHQ1.png')
im_list=np.asarray(im)
plt.imshow(im_list)
# click left-top and right-bottom
nn=2
a=plt.ginput(n=nn)
xi=a[0][0]
yi=a[0][1]
xf=a[1][0]
yf=a[1][1]
del a
# click on the graph
nn=5
a=plt.ginput(n=nn)
b=np.array(a)
vec_x=b[:,0]
vec_y=b[:,1]
plt.plot( vec_x,vec_y, 'ro' )
# range of the graph
# (xmin,xmax)=(0,12000)
# (ymin,ymax)=(60,90)
xmin,xmax=map(float,input('xmin xmax= ').split())
ymin,ymax=map(float,input('ymin ymax= ').split())
# calculation of the values
xx=xmin+(xmax-xmin)*(vec_x-xi)/(xf-xi)
yy=ymin-(ymax-ymin)*(vec_y-yf)/(yf-yi)
for x,y in zip(xx,yy):
print(x,y)
plt.savefig('fig_test.png', bbox_inches="tight", pad_inches=0.2)
plt.show()
使い方
- プログラムをスタートすると画像が表示される
- グラフの左上と右下をクリックする.
これにより $(k_{xi},k_{yi})$ および $(k_{xf},k_{yf})$ が入力・定義される - 任意の5点をクリック
- コンソール上でx軸の最小と最大を聞いてくるので入力.これにより $x_{min}$,$x_{max}$ が入力・定義される.
- コンソール上でy軸の最小と最大を聞いてくるので入力.これにより $y_{min}$,$y_{max}$ が入力・定義される.
- クリックした5点のグラフ上の値が表示される
- 表示を閉じて終了
コンソールでの入出力
$ python3 py_img_test1.py
xmin xmax= 0 12000
ymin ymax= 60 90
-31.25 62.1212121212
1937.5 70.202020202
3968.75 74.0404040404
6000.0 77.1717171717
9968.75 82.2222222222
出力画像
以 上