Up

グラフの値の読み取り

改訂:2026.03.03

 

データとその分析結果はグラフで表示されることが多い。分析は、何らかの視点から行われるが、分析者の視点とは異なる観点からの分析を行いたいときもある。他の観点から分析を行うためには、グラフから必要なデータ値を読み取ることになる。PyGameを利用してグラフから値を読み取ることを試みた。

まず、グラフに傾きがない場合を扱い、次に傾きがある場合を扱う。グラフの画像は、大きすぎたり小さすぎることもあるので、適度の大きに調整することも試みた。

 

 

画像ファイル上の位置の読み込み

 

A.1の画像ファイルから折れ線のデータ点の値を読み取ることを試みる。

 

A.1 画像ファイルSampleData.png

 

A.1のファイルから折れ線のデータ点を読み取るスクリプトをリストA.1のように作成した。Python 3.13.12を利用した(2026.02.22)。ファイルは、files1.zipにまとめた。

 

 

リストA.1 グラフの点の読み取り(read_graph.py

 

import pygame as pg

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pygame import font

 

infl_nm = input('Input Image File = ')

outxl_nm = input('Output Excel File Name(*.xlsx) = ')

 

pg.init()

font.init()

 

screen = pg.display.set_mode(size=(1200, 700))    #   画面の大きさ

screen.fill((0,0,0))                              #   黒で塗りつぶす

 

img_expln = pg.image.load(infl_nm)    #    画像ファイルのロード

rect_expln = img_expln.get_rect()     #    画像の大きさ

img_tmp = pg.Surface.copy(img_expln)  #    画像ファイルのコピー

 

img_x0 = (1200-rect_expln.width)//2   #    提示画像の左上の角のX座標

img_y0 = (700-rect_expln.height)//2   #    提示画像の左上の角のY座標(下方が正)

(x,y) = (0,0)   #   ポインター位置変数の初期値

data = []       #   クリック位置のリスト

n = 0           #   クリックデータの数

ck = True

while ck:

    #     スクリーンを黒で塗りつぶす

    screen.fill((0,0,0))

    img_tmp = pg.Surface.copy(img_expln)

    (x,y) = pg.mouse.get_pos()   

    #     ポインターの位置に緑の小円を描く

    pg.draw.circle(img_tmp,(0,255,0), (x-img_x0,y-img_y0), 10, 2)

    screen.blit(img_tmp,

                ((1200-rect_expln.width)//2,(700-rect_expln.height)//2))

    #     スクリーンの表示   

    pg.display.flip()

    for e in pg.event.get():

        if e.type == pg.QUIT:

            ck = False

            break

        if e.type == pg.KEYDOWN:

            if e.key == pg.K_q:     #   キーGが押されたかのチェック

                ck = False

                break

        if e.type == pg.MOUSEBUTTONDOWN:

            #     クリックされた位置に赤の小円をimg_explnに描き、dataに記録する。

            pg.draw.circle(img_expln,(255, 0, 0), (x-img_x0,y-img_y0), 8, 2)

            data.append([n, x-img_x0,y-img_y0])

            n += 1

 

font.quit()

pg.quit()

 

print(data)

 

#     dataを辞書型に変換

dict_data = {'data_id':[], 'x':[], 'y':[]}

for v in data:

    dict_data['data_id'].append(v[0])

    dict_data['x'].append(v[1])

    dict_data['y'].append(v[2])

#     辞書型データをExcelファイルに保存

print(dict_data)

dframe = pd.DataFrame(dict_data)

dframe.to_excel(outxl_nm, index=False)

 

 

 

リストA.1のスクリプトを実行すると、入力データファイル名と読み込んだ値を出力するExcelファイル名の設定が求められる。

 

= RESTART: ****\files1\read_graph.py

pygame 2.6.1 (SDL 2.28.4, Python 3.13.12)

Hello from the pygame community. https://www.pygame.org/contribute.html

Input Image File = SampleData.png

Output Excel File Name(*.xlsx) = Sample.xlsx

 

出力ファイル名は、適当なExcelファイル名を設定する。

ファイル名を設定すると、画像ファイルが読み込まれ、図A.2のような画面が表示される。他のWindowに隠れて見えないときがあるが、Windows画面の下端のタスクバー上のPythonのアイコン上にマウスのポインターを置くと、Python関係の実行中のWindowが表示されるので、A.2Windowを選んでクリックすればよい。

 

A.2

 

画像の上にマウスのポインターを置くと、その位置に緑の小円が表示される。

 

A.3

 

マウスのボタンをクリックすると、緑の小円の内側に赤の小円が表示される(図A.4)。

 

A.4

 

このとき、次のスクリプトにより、クリック位置がリストdataに追加される。

 

        if e.type == pg.MOUSEBUTTONDOWN:

            #     クリックされた位置に赤の小円をimg_explnに描き、dataに記録する。

            pg.draw.circle(img_expln,(255, 0, 0), (x-img_x0,y-img_y0), 8, 2)

            data.append([n, x-img_x0,y-img_y0])

            n += 1

 

マウスの移動は、速さを遅く設定しておくと位置決めが容易になる。マウスの移動速度は、「システム|Bluetoothとデバイス|マウス」の「マウスポインターの速度」で選ぶことができる。

キーQを押すと、画面が閉じられて、グラフ値の読み込みが終了する。

読み込まれたグラフ値のリストdataは、以下のスクリプトでPandasDataFrame型に変換され、Exelファイルとして保存される。

 

#     dataを辞書型に変換

dict_data = {'data_id':[], 'x':[], 'y':[]}

for v in data:

    dict_data['data_id'].append(v[0])

    dict_data['x'].append(v[1])

    dict_data['y'].append(v[2])

#     辞書型データをExcelファイルに保存

print(dict_data)

dframe = pd.DataFrame(dict_data)

dframe.to_excel(outxl_nm, index=False)

 

スクリプトの実行終了後、保存されたExcelファイルを開くと、図A.5のようになっている。意図せずにクリックされて記録された行は、削除すればよい。

 

A.5

 

 

 

保存されたExcelファイルのチェック

 

グラフ値を読み込み、作成されたExcelファイルのチェックを行うスクリプトを、リストB.1のように用意した。

 

 

リストB.1 読み込みデータのチェック(check_values.py

 

import pygame as pg

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pygame import font

 

infl_nm = input('Image File Name = ')

xlfl_nm = input('Excel file name = ')

 

pg.init()

font.init()

 

screen = pg.display.set_mode(size=(1200, 700))    #   画面の大きさ

screen.fill((0,0,0))                              #   黒で塗りつぶす

my_font = pg.font.SysFont(None, 20)               #   フォントの大きさ

 

img_expln = pg.image.load(infl_nm) 

rect_expln = img_expln.get_rect()

 

img_x0 = (1200-rect_expln.width)//2

img_y0 = (700-rect_expln.height)//2

 

values = pd.read_excel(xlfl_nm).values

print(values)

for v in values:

    #     読み込み値の表示

    pg.draw.circle(img_expln,(255, 0, 0), (v[1],v[2]), 7, 1)

   

screen.blit(img_expln, ((1200-rect_expln.width)//2,(700-rect_expln.height)//2))

 

for v in values:

    #     読み込み値のIDの表示

    img_str = my_font.render(f'{v[0]}',

                             True, (255,0, 0), None)

    rect_str = img_str.get_rect()

    screen.blit(img_str, (3+v[1]+img_x0, 3+v[2]+img_y0)) # (x-img_x0,y-img_y0))

 

ck = True

while ck:  

    pg.display.flip()

    for e in pg.event.get():

        if e.type == pg.QUIT:

            ck = False

            break

        if e.type == pg.KEYDOWN:

            if e.key == pg.K_q:     #   キーGが押されたかのチェック

                ck = False

                break

 

font.quit()

pg.quit()

 

 

リストB.1のスクリプトを実行すると、グラフ値の読み込みを行った画像ファイル名と読み取りの結果を格納したExcelファイル名の入力が求められる。

 

= RESTART: ****\files1\check_values.py

pygame 2.6.1 (SDL 2.28.4, Python 3.13.12)

Hello from the pygame community. https://www.pygame.org/contribute.html

Image File Name = SampleData.png

Excel file name = Sample.xlsx

 

ファイル名を設定すると、図B.1の画面が表示される。

 

B.1

 

画像データの上に、クリックした位置が赤の小円で、その右下にデータ識別子(図A.5Excelファイルの第1欄の文字列)が表示されている。不適切なデータがあれば、Excelで開いて該当行を削除すればよい。

問題が無ければ、次に進み、読み込んだグラフ値の描画を行う。

 

 

 

読み込みグラフ値の表示

 

グラフから読み込んだ値は座標がピクセル値であるが、これをグラフで用いられている尺度値に変換して表示する。リストC.1にスクリプトを示す。

 

 

リストC.1 読み込み値の表示(ReConstrctn.py

 

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

 

xlfl_nm = input('Excel file name = ')

 

values = pd.read_excel(xlfl_nm).values

print(values)

#      X座標の基準点

x_1 = values[0][1]

x_9 = values[1][1]

#      Y座標の基準点

y_0 = values[2][2]

y_20 = values[3][2]

 

 

def x_transf(v):

    """

             読み込み値をX座標に変換

    """

    return 1.0 + (9 - 1) * (v - x_1) / (x_9 - x_1)

 

def y_transf(v):

    """

             読み込み値をY座標に変換

    """

    return 0.0 + (20 - 0) * (v - y_0) / (y_20 - y_0)

 

x = []

y = []

for i in range(4, 13):

    x.append(x_transf(values[i][1]))

    y.append(y_transf(values[i][2]))

 

plt.plot(x, y, 'o-')

plt.title('Read Out Values', fontsize=16)

plt.show()

 

 

上のスクリプトを実行すると、グラフ値を読み込んだExcelファイル名の設定が求められる。

 

= RESTART: ****\files1\ReConstrctn.py

Excel file name = Sample.xlsx

 

ファイル名を設定すると、図C.1のグラフが表示される。

 

C.1

 

Excelファイルは、座標がピクセル値であるが、これを図B.1に合わせて、入力グラフの尺度値に以下のように変換している。

 

X軸、Y軸への座標値の変換は、図B.1における0番の点、1番の点、および2番の点、3番の点のデータから次の関数でピクセル値から元の座標値への変換を行っている。

 

#      X座標の基準点

x_1 = values[0][1]

x_9 = values[1][1]

#      Y座標の基準点

y_0 = values[2][2]

y_20 = values[3][2]

 

 

def x_transf(v):

    """

             読み込み値をX座標に変換

    """

    return 1.0 + (9 - 1) * (v - x_1) / (x_9 - x_1)

 

def y_transf(v):

    """

             読み込み値をY座標に変換

    """

    return 0.0 + (20 - 0) * (v - y_0) / (y_20 - y_0)

 

 

この変換関数により、図B.1の点4から点12までのピクセル値を次のスクリプトで元の尺度値に変換した座標をリストxおよびyに格納している。

 

x = []

y = []

for i in range(4, 13):

    x.append(x_transf(values[i][1]))

    y.append(y_transf(values[i][2]))

 

変換された座標による描画を、次のスクリプトで行っている。

 

plt.plot(x, y, 'o-')

plt.title('Read Out Values', fontsize=16)

plt.show()

 

 

 

傾いたグラフ

 

グラフが、図D.1のように傾いている場合を考える。なお、傾いている場合用のスクリプトは、グラフが傾いていない場合にも使用できる。ファイルは、files2.zipにまとめた。

 

D.1 SampleDataRot.png

 

D.1の画像ファイルからグラフの値を読み込むスクリプトは、リストA.1のスクリプトで行う。

リストA.1のスクリプトを実行すると、読み取る画像ファイル名と読み込んだ結果を出力するExcelファイル名の設定が求められる。

 

= RESTART: ****\files2\read_graph.py

pygame 2.6.1 (SDL 2.28.4, Python 3.13.12)

Hello from the pygame community. https://www.pygame.org/contribute.html

Input Image File = SampleDataRot.png

Output Excel File Name(*.xlsx) = SampleRot.xlsx

 

ファイル名を設定すると、図D.1Windowが表示される。図A.2の場合と同様に読み込み点をクリックしていく。

 

D.2

 

点の読み込みが終わったら、キーQを押して終了する。

 

読み込んだ値のチェックは、リストB.1のスクリプトで行える。上のデータの場合、図D.3のようになる。

 

D.3

 

出力Excelファイルは、図D.4のようである。

 

D.4

 

不適当なデータがあれば、Excelファイルにおいて削除すればよい。

 

点の読み込みで作成されたExcelファイルからグラフの尺度値に変換するスクリプトは、リストD.1のように用意した。

 

 

リストD.1 画像グラフの傾きを考量したグラフの尺度値の構成スクリプト(ReConstrctnRot.py

 

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

 

xlfl_nm = input('Input Excel file name = ')

xlfout_nm = input('Output Excel file name = ')

 

values = pd.read_excel(xlfl_nm).values

print(values)

 

 

class TransF():

    def __init__(self, x0, x1,    #    X軸の左と右の基準点

                 v0, v1,          #    X軸の基準点の値

                 y0, y1,          #    Y軸の下と上の基準点

                 w0, w1):         #    Y軸の基準点の値

        #      X座標の単位ベクトル

        e_x = np.array(x1) - np.array(x0)

        self.e_x = e_x / (np.sum(e_x**2)**0.5)

        self.x0 = np.dot(np.array(x0), self.e_x)

        self.x1 = np.dot(np.array(x1), self.e_x)

        self.v0 = v0

        self.v1 = v1

        #      Y座標の単位ベクトル

        e_y = np.array(y1) - np.array(y0)

        self.e_y = e_y / (np.sum(e_y**2)**0.5)

        self.y0 = np.dot(np.array(y0), self.e_y)

        self.y1 = np.dot(np.array(y1), self.e_y)

        self.w0 = w0

        self.w1 = w1

 

    def t_func(self, p):    #   pのピクセル値の座標をXY軸の座標に変換

        p = np.array(p)

        p_x = np.dot(p, self.e_x)

        x = self.v0 + (self.v1 - self.v0) * \

                (p_x - self.x0) / (self.x1 - self.x0)

        p_y = np.dot(p, self.e_y)

        y = self.w0 + (self.w1 - self.w0) * \

                (p_y - self.y0) / (self.y1 - self.y0)

 

        return x, y

       

tf = TransF([values[0][1], values[0][2]], [values[1][1], values[1][2]],

            1, 9,

            [values[2][1], values[2][2]], [values[3][1], values[3][2]],

            0, 20)

x = []

y = []

for i in range(4, 13):

    vx, vy = tf.t_func([values[i][1], values[i][2]])

    x.append(vx)  

    y.append(vy)  

 

plt.plot(x, y, 'o-')

plt.title('Read Out Values', fontsize=16)

plt.show()

 

dict_out = {'X':x, 'Y':y}

dframe = pd.DataFrame(dict_out)

dframe.to_excel(xlfout_nm, index=False)

print(xlfout_nm, 'was saved.')

 

 

 

リストD.1のファイルを実行する。

 

= RESTART: ****\files2\ReConstrctnRot.py

Input Excel file name = SampleRot.xlsx

Output Excel file name = SampleExcel.xlsx

 

グラフ値を読み取ったExcelファイルと、変換した尺度値を出力するExcelファイルの名前を設定すると、グラフの尺度値が算出されて図D.5のように表示される。

 

D.5

 

ピクセル値座標からグラフの元の尺度値への変換は、次のクラスTransFによって行っている。

 

class TransF():

    def __init__(self, x0, x1,    #    X軸の左と右の基準点

                 v0, v1,          #    X軸の基準点の値

                 y0, y1,          #    Y軸の下と上の基準点

                 w0, w1):         #    Y軸の基準点の値

 

グラフの傾きを戻すために、X軸方向のベクトルとY軸方向のベクトルを、図D.6に示すようにとっている。

 

テキスト ボックス: Y軸方向のベクトル

D.6

 

すなわち、

 

tf = TransF([values[0][1], values[0][2]], [values[1][1], values[1][2]],

            1, 9,

            [values[2][1], values[2][2]], [values[3][1], values[3][2]],

            0, 20)

 

である。

 点0から点1までのベクトルをとり、点0でのX座標を1,点1でのX座標を9としている。

 点2から点3までのベクトルをとり、点2でのY座標を0,点3でのY座標を20としている。

 

D.5に表示されているグラフの値は、出力用Excelファイルに図D.7のように格納されている。

 

D.7

 

グラフから読み取った値は、Excelファイルに格納されているので、いろいろな分析を適用することができる。

 

 

 

画像の大きさの調整

 

画像が、図A.2の枠に対して大き過ぎる、あるいは小さ過ぎるときに、画像ファイルの大きさを調整するスクリプトとしてリストE.1のスクリプトを作成してみた。ファイルは、files3.zipにまとめた。

 

 

リストE.1 画像ファイルのリサイズ(rescale_img.py

 

import cv2          # pip install opencv-python

import pygame as pg

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

 

inflnm = input('Input Image File = ')

img0 = cv2.imread(inflnm)   

outflnm = input('Output Image File = ')

 

pg.init()

screen = pg.display.set_mode(size=(1200, 700))    #   画面の大きさ

screen.fill((0,0,0))                              #   黒で塗りつぶす

 

v_scl = 100       #    rescaling fatorの初期値 100%

 

(h0, w0, _rgb0) = np.shape(img0)

 

while True:

    pg.init()

    screen = pg.display.set_mode(size=(1200, 700))    #   画面の大きさ

    screen.fill((0,0,0))    

    #

    #         Rescaling

    #

    sw = int(w0*v_scl/100)

    sh = int(h0*v_scl/100)

    img1 = np.empty((sh, sw, 3), dtype = 'uint8')

    cv2.resize(img0, dsize=(sw, sh), dst=img1)

 

    cv2.imwrite(outflnm, img1)            #   リサイズした画像の一時保存

 

 

 

    pg.display.set_caption(f'{v_scl}%')

    img_rescl = pg.image.load(outflnm)    #    リサイズ画像の読み込み

    rect_rescl = img_rescl.get_rect()     #    画像の大きさ

 

    img_x0 = (1200-rect_rescl.width)//2   #    提示画像の左上の角のX座標

    img_y0 = (700-rect_rescl.height)//2   #    提示画像の左上の角のY座標(下方が正)

 

    ck = True

    while ck:

        #     スクリーンを黒で塗りつぶす

        screen.fill((0,0,0))

        #     リサイズ画像の貼り付け

        screen.blit(img_rescl,

                    ((1200-rect_rescl.width)//2,(700-rect_rescl.height)//2))

        #     スクリーンの表示   

        pg.display.flip()

        for e in pg.event.get():

            if e.type == pg.QUIT:

                ck = False

                break

            if e.type == pg.KEYDOWN:

                if e.key == pg.K_q:     #   キーGが押されたかのチェック

                    ck = False

                    break

 

    pg.quit()

 

    v = input('Is the resizing OK? Y(es) or N(o) = ')

    if v in {'Y', 'y'}:

        break

    v_scl = float(input('Resizing factor(%) = '))

         

print(outflnm, 'was daved.')

 

 

リストE.1のスクリプトを実行すると、大きさを調整したい画像ファイルの名前と、調整後の画像ファイルを格納する出力ファイル名の設定が求められる。

 

= RESTART: ****\files3\rescale_img.py

pygame 2.6.1 (SDL 2.28.4, Python 3.13.12)

Hello from the pygame community. https://www.pygame.org/contribute.html

Input Image File = sampleRGB.png

Output Image File = FResize.png

 

上の例では、入力画像ファイル名としてsampleRGB.png、出力ファイル名としてFResize.pngが設定されている。

ファイル名を設定すると、入力画像ファイルが表示される。黒の枠画面は、図A.2の画面と同じ大きさである。

 

E.1

 

E.1Windowがフォーカスされているとき(図E.1Window内をクリックすればよい)にキーQを押す、あるいは図E.1のWindowの右上角のX印をクリックするとWindowは閉じられて、端末上に次のメッセージが表示される。図E.1に表示されている画像サイズを変えるときは、Nを入力する。

Nを入力すると、画像の拡大/縮小率の設定が求められる。

 

Is the resizing OK? Y(es) or N(o) = N

Resizing factor(%) = 170

 

拡大/縮小率を設定(上の例では170%)すると、指定した拡大/縮小率による画像ファイルが表示される(図E.2)。

 

E.2

 

E.2WindowをクリックしてフォーカスしてからキーQを押す、あるいは図E.2Windowの右上角のX印をクリックすると、Windowは閉じられて、拡大/縮小した画像のサイズでよいか端末上で聞いてくる。

 

Is the resizing OK? Y(es) or N(o) = Y

FResize.png was daved.

 

Yと入力すれば、スクリプトは終了して、拡大/縮小した画像ファイルの出力ファイル名が表示される。

 

 

 

Home