OpenCV에서 그래프 이미지를 가져와 그래프 최종 지점의 좌표를 얻습니다.

12501 단어 파이썬OpenCV

경위



파치 슬롯 데이터 사이트의 슬럼프 그래프에서 자동으로 차 매수를 산출하고 싶었다.



↑그래프는 이러한 형태.

그 계산에 그래프의 최종 지점의 y 좌표(이미지의 빨간색 원 부분)가 필요했기 때문에 OpenCV를 사용하여 그래프 이미지를 읽고 좌표를 얻는 코드를 썼습니다.

코드


import cv2
import numpy as np
import time

start = time.time()
file_path = 'C:\\Users\\Pictures\\sample_graph.png'
# グラフ画像読み込み
img = cv2.imread(file_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # imgの中身:[y座標, x座標, [R, G, B]]
# x軸とy軸の要素数取得
i_range = img.shape[0]
j_range = img.shape[1]
# 座標格納用配列
graph_coordinate = [[0 for i in range(3)] for j in range(i_range * j_range)]
x_list = []
# y軸ループ
for i in range(i_range):
    # x軸ループ
    for j in range(j_range):
        # RGB値をそれぞれ格納
        R, G, B = img[i, j]
        # グラフ色に当てはまる座標のみ取得
        if (230 <= R <= 255) and (0 <= G <= 30) and (130 <= B <= 160):
                graph_coordinate.append([i, j, img[i, j]])
                x_list.append(j)
coordinate = np.asarray(graph_coordinate)
# x軸の最大値(グラフ終点のx座標)からy座標を求める
target = np.where(coordinate[:, 1] == max(x_list))
y_axis_target = coordinate[target]
y_axis = y_axis_target[0][0]
print(f'y_axis:{y_axis}')
print('elapsed_time:{time} sec'.format(time=time.time() - start))

그래프가 없는 경우의 처리나 y좌표의 대상이 복수 있는 경우의 처리도 이 계속에 있습니다만 길어지므로 할애.

처리의 대략적인 흐름 설명



우선, 그래프를 읽어 numpy.ndarray형으로 전체 픽셀 정보를 취득.
(img에는 ​​[y 좌표, x 좌표, [R, G, B]] 형태로 데이터가 저장되어 있는 상태입니다)

픽셀 정보에서 모든 픽셀을 탐색하여 그래프 색상과 일치하는 픽셀의 좌표를 모두 목록에 저장합니다.
(그래프색의 RGB값은 사전에 화상으로부터 조사해 설정)

마지막으로 x축의 최대치(그래프 종점)로부터 대상의 y 좌표를 취득해 완료.

라는 흐름입니다.

처리 속도 향상



이것으로 일단 요건은 충족하고 있습니다만 for문의 이중 루프 때문에 처리 속도가 느린.

실행 결과
y_axis:36
elapsed_time:2.9471683502197266 sec

우선 형태만 만들어 두고 싶고 곧바로 생각해 낸 상기 코드로 우선은 썼습니다만, 절각 numpy형으로 그래프의 요소를 읽어오고 있으므로 그것을 살릴 수 있는 형태로 재작성했습니다.
import cv2
import numpy as np
import time

start = time.time()
file_path = 'C:\\Users\\Pictures\\sample_graph.png'
# グラフ画像読み込み
img = cv2.imread(file_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# グラフ開始地点ピクセルのRGB値を取得(img[y座標][x座標])
color_pattern = img[180][45]
# 2値化(0 or 255)
mask = cv2.inRange(img, color_pattern, color_pattern)
# グラフ部分のみの座標取得
coordinate = np.stack(np.where(mask == 255), axis=1)
# x軸の最大値(グラフの終点)
max_x_axis = coordinate[:, 1].max()
# x軸の最大値からy座標を求める
y_axis_target = coordinate[np.where(coordinate[:, 1] == max_x_axis)]
y_axis = y_axis_target[0][0]
print(f'y_axis:{y_axis}')
print('elapsed_time:{time} sec'.format(time=time.time() - start))

방금 전과 달리, 우선은 그래프 개시 지점의 픽셀로부터 그래프의 RGB치를 취득.
※전제조건:화상 사이즈나 그래프 개시지점의 좌표는 항상 일정

그런 다음 그래프의 RGB 값과 일치하는 픽셀과 그렇지 않은 픽셀로 이진화.
그런 다음 numpy.where를 사용하여 그래프 부분(255)만의 좌표를 가져옵니다.
마지막은 개선 전의 코드와 같이 x축의 최대치로부터 y좌표를 구해 완료.

재기록 후의 처리 속도가 이쪽.

실행 결과
y_axis:36
elapsed_time:0.015000581741333008 sec

폭속! ! !

참고 링크



Python으로 이미지 처리 : Pillow, NumPy, OpenCV의 차이와 구분
Python, NumPy로 이미지 처리 (로드, 연산, 저장)
Python으로 이미지 처리 이미지 배열과 RGB를 이해합시다!
[Python] Numpy 참조, 추출, 결합
파이썬에서 특정 색상의 좌표를 출력하는 방법
【python/OpenCV】 이미지의 특정 색을 추출하는 방법

좋은 웹페이지 즐겨찾기