1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画像ファイルgraph.jpgをPythonで読み取りたい(1)

Posted at

画像ファイルのグラフをPythonで数値として読み取りたい

何かDIYなどで工作する時,部品カタログを見ますよね.
そのpdfファイルは容易にWebからダウンロードできたりします.

ドキュメントの中に,製品の仕様を示すグラフが掲載されていたりするのですが,性能などを計算するのに数値データとして欲しい場面がたくさんあります.

<グラフサンプル>

graph.jpg

この画像ファイル(graph.jpg)から,数値データとしてゲットできないかなと思って,Pythonプログラムを試してみることにしました.

残念ながら,このプログラムでは,グラフの数値をうまく取得することができなかった.

引き続き,別のやり方を探っていこうと思っているので,今後のために,うまく取得できなかったプログラムや結果も残しておこうと思い,記事にしました.

強調

read_graph.py
# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
import japanize_matplotlib
![スクリーンショット 2025-03-09 10.05.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1979979/664174af-705a-450a-a97a-3ead1fec6d6c.jpeg)
![スクリーンショット 2025-03-09 10.05.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1979979/a5c4d67c-e753-42a1-b52e-7087ebe320c5.jpeg)
![read_graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1979979/ea55f152-e802-4d6b-9cca-5fae73d1978a.jpeg)

# 画像の読み込み
image_path = 'graph.jpg'
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

if image is None:
    print("Error: 画像が見つかりません。パスを確認してください。")
else:
    print("画像が正常に読み込まれました。")

    # エッジ検出を使用してグリッド線と外枠を検出
    edges = cv2.Canny(image, 50, 150)

    # 垂直線と水平線を検出
    lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=10)
    mask = np.ones_like(image) * 255

    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv2.line(mask, (x1, y1), (x2, y2), 0, 2)  # グリッド線と外枠を黒で描画

    # グリッド線と外枠を削除した画像を作成
    image_without_grid = cv2.bitwise_and(image, mask)

    # 画像の前処理(ノイズ除去)
    blurred = cv2.GaussianBlur(image_without_grid, (3, 3), 0)
    _, threshold = cv2.threshold(blurred, 150, 255, cv2.THRESH_BINARY_INV)

    # 輪郭の検出
    contours, _ = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # トルク曲線部分のデータポイントの抽出
    torque_points = []
    for contour in contours:
        # 輪郭の周囲の長さを計算
        perimeter = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True)
        
        # 曲線部分を判定するために頂点数が多いものを選択
        if len(approx) > 5 and cv2.contourArea(contour) < 1000:  # 閾値を調整
            # 指定されたx軸、y軸範囲内の点のみを抽出
            for point in contour:
                x, y = point[0]
                if 500 <= x <= 6500 and 95 <= y <= 155:
                    # 赤色の曲線を無視(色判定は実装が難しいため、位置情報で判定)
                    if (x + y) % 2 != 0:  # 例として偶数座標を無視
                        torque_points.append((x, y))

    # x, y座標のリストとして表示
    torque_x_coords = [point[0] for point in torque_points]
    torque_y_coords = [point[1] for point in torque_points]

    print("Torque Curve X座標:", torque_x_coords)
    print("Torque Curve Y座標:", torque_y_coords)

    # オリジナルの画像を表示
    plt.figure(figsize=(10, 6))
    plt.imshow(image, cmap='gray')
    plt.title('Original Image')
    plt.grid(False)
    plt.show()

    # 抽出したトルク曲線を表示
    plt.figure(figsize=(10, 6))
    plt.scatter(torque_x_coords, torque_y_coords, color='blue', marker='o', label='Torque Curve')
    plt.title('Scatter Plot of Extracted Torque Curve (Ignoring Grid Lines and Outline)')
    plt.xlabel('X座標')
    plt.ylabel('Y座標')
    plt.legend()
    plt.grid(True)
    plt.show()

<読み取ったx,y値をプロット>
read_graph.jpg

noteの記事に書きましたが,

やはり,こういった自分でグラフをなぞるといった一手間をかまさないと
OCR的に値を取得するのは難しいのでしょうか...

今後も,細々と改良を検討していこうと思っています...

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?