2023年6月24日土曜日

pythonで近似式とR2を求める

Pythonを使って下記を行います。

・二次元配列(100x2)の値を間引く
・二次元配列(10x2)の値を第0列の値で昇順にソート
・二次元配列をx,yの散布図と考えて、1次、2次、5次の多項式近似で近似曲線を作成
・各近似式の決定係数R2を求める

numpyが必要

import numpy as np

arr = np.random.rand(100, 2)    # 100 x 2の配列の乱数
arr2=arr[::10]                  #1/10に間引く
arr3 = np.sort(arr2,axis=0)     #0番の列で昇順にソート

coe1 = np.polyfit(arr3[:,0], arr3[:,1], 1)  #1次多項式
coe2 = np.polyfit(arr3[:,0], arr3[:,1], 2)  #2次多項式
coe5 = np.polyfit(arr3[:,0], arr3[:,1], 5)  #3次多項式

fit1=np.poly1d(coe1)(arr3[:,0])
fit2=np.poly1d(coe2)(arr3[:,0])
fit5=np.poly1d(coe5)(arr3[:,0])

r2_1 = np.corrcoef(arr3[:,1], fit1)[0,1] ** 2   #yの値同士を入れる
r2_2 = np.corrcoef(arr3[:,1], fit2)[0,1] ** 2   #yの値同士を入れる
r2_5 = np.corrcoef(arr3[:,1], fit5)[0,1] ** 2   #yの値同士を入れる

print(r2_1,r2_2,r2_5)

 

=========

Pythonを使ってグラフを読み取ります。作りかけです。

・グラフの枠の座標を取得する
・グラフの枠内を白く塗りつぶす
・軸の数字と座標を認識する
グラフデータの読み込みや画像の座標からグラフの数値への変換は未実装です。

pillow、pyocr、Opencv、Tesseract、numpyが必要です。


import sys
import os
from PIL import Image
import pyocr
import cv2
import numpy as np

#Tesseractのインストール場所をOSに教える
tesseract_path = "C:\Program Files\Tesseract-OCR"
if tesseract_path not in os.environ["PATH"].split(os.pathsep):
    os.environ["PATH"] += os.pathsep + tesseract_path

#OCRエンジンを取得する
tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("OCRエンジンが指定されていません")
    sys.exit(1)
else:
    tool = tools[0]

# 8ビット1チャンネルのグレースケールとして画像を読み込む
img_org = cv2.imread("sample.bmp", cv2.IMREAD_GRAYSCALE)
img=cv2.bitwise_not(img_org)    # 白黒反転 輪郭検出で白色の枠を検出するため、外枠が白になるように白黒反転

#輪郭検出 cv2.RETR_EXTERNAL 最外部の輪郭のみ検出 CHAIN_APPROX_TC89_L1:直線近似できる部分の輪郭点を省略
#contours[輪郭番号][点の番号][0][X座標, Y座標]
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1 )

# 画像表示用に入力画像をカラーデータに変換する
img_disp = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
img_disp_org = cv2.cvtColor(img_org, cv2.COLOR_GRAY2BGR)

# 輪郭の点の描画
#contours[輪郭番号][点の番号][0][X座標, Y座標]
for i, contour in enumerate(contours):
    # 輪郭を描画 画像名、輪郭座標、輪郭番号、色、線幅(-1は塗りつぶし)
    cv2.drawContours(img_disp, contours, i, (255, 0, 0), 2)

    # 傾いていない外接する矩形領域
    x,y,w,h = cv2.boundingRect(contour)
    if w>100:       #幅100より大きい(グラフの外枠)のとき、orgのほうは白く塗りつぶし
        cv2.rectangle(img_disp,(x,y),(x+w-1,y+h-1),(0,255,0),2)
        cv2.rectangle(img_disp_org,(x,y),(x+w-1,y+h-1),(255,255,255),-1)    #白く塗りつぶす
       
#fileに書いて後ろでもう一度読み込んでいる。絶対もっと良い方法がある
cv2.imwrite('output.png', img_disp_org)

#画像の読み込み
file_path = "sample.bmp"
img = Image.open('output.png')      #ここはいつか改善する
img2 = img_disp_org                 #グラフ部を塗りつぶした画像

#文字と座標を読み取る
box_builder = pyocr.builders.WordBoxBuilder(tesseract_layout=6)     #6が最適かは不明
text_position = tool.image_to_string(img,lang="eng",builder=box_builder)

#取得した座標と文字を出力、画像に枠を書き込む
for res in text_position:
    print(res.content)
    print(res.position)
    cv2.rectangle(img2,res.position[0],res.position[1],(0,0,255),2)

#検出した軸ラベルの座標からx,y軸それぞれのグラフ範囲を推定する処理を入れる 未
#別途グラフの系列データを認識して、グラフ範囲に変換する 未

#四角を書き込んだ画像を表示
cv2.imshow("image",img2)
cv2.waitKey(0)