前提・実現したいこと
以下の質問にいただいた回答
URL: https://teratail.com/questions/342736
から、実測値を出力することまではできました。
補足
・二値化、contourによる輪郭の検出
ここまでは可視化することによって正しい処理がなされていることが確認できました。
・boudingRect,及びnumpyによるベクトルの算出
ここからが理解できていません。どのような計算プロセスを経て結果が出力さているのかがわからず、
そのため、なぜ誤差が生じているのかもわかっていません。
発生している問題・エラーメッセージ
長めの線や平行な線ならほとんど誤差なく検出できます。しかし、
・↑の画像のように線が斜めに交差している場合(実際はもう少し複雑に分岐)
・短い線が複数(上記画像内に10本程度のイメージ)
主にこれらのパターンで許容できないレベルの誤差(±10%程度)が生じてしまいます。
なお、線分の太さは統一しています。
ここから精度を上げる方法はあるのでしょうか。
ご教授いただければ幸いです。
該当のソースコード
Python
1import cv2 2import numpy as np 3import glob 4import os 5 6""" 7赤 青 それ以外で二値化 8輪郭の座標から線分の長さを計算 9""" 10 11# 赤色の範囲 12lower = (0, 20, 0) # 下限 13upper = (94, 255, 255) # 上限 14# 青色の範囲 15lower_blue = np.array([90, 64, 0]) # 下限 16upper_blue = np.array([150, 255, 255]) # 上限 17 18# ①画像読み込み 19file = find_files() 20img = cv2.imread(file, cv2.IMREAD_COLOR) 21img_2 = cv2.imread(file, cv2.IMREAD_COLOR) 22 23# ②HSV変換 24hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 25hsv_2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 26 27# ③二値化 28binary = cv2.inRange(hsv, lower, upper) 29binary_2 = cv2.inRange(hsv, lower_blue, upper_blue) 30 31# ④輪郭の座標を抽出 32contours, hierarchy = cv2.findContours( 33 binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 34 35contours_2, hierarchy_2 = cv2.findContours( 36 binary_2, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 37 38# 長さ計算用 39red_length = 0.0 40blue_length = 0.0 41 42# 赤色 43for i in range(len(contours)): 44 # ⑤輪郭情報から外接矩形の座標を抽出 45 x, y, w, h = cv2.boundingRect(contours[i]) 46 # ⑥線分の長さを計算(lengthに足す) 47 red_length += np.linalg.norm([w, h]) 48 print(red_length) 49 50# 青色 51for i in range(len(contours_2)): 52 x, y, w, h = cv2.boundingRect(contours_2[i]) 53 blue_length += np.linalg.norm([w, h]) 54 print(blue_length) 55 56# 出力 57Scale_set = int(input('縮尺を入力してください:')) 58red_length_True = Scale_set * red_length / blue_length 59 60print(f'{file} の赤線の実測値:{red_length_True}')
試したこと
contourの結果を可視化することで目標とする線分(赤/青ともに)が正しく認識できていることを確認しました。
線分がどんな状態であっても輪郭の検出までは上手く行っています。
しかし、実現したいことにあるような
・短めの線が多数
・線同士が重なり合っている
といった状況だと出力される値(boudingRect→numpyによる計算)に誤差が生じてしまいます。
contourAreaによる面積の算出、arcLengthによる周囲長さの算出も試しましたが、
面積:以下のような状況で、何故か出力が0になってしまう事がある
・輪郭を正しく認識できている
・引数として渡しているcontourの結果(contours)の中身には座標の値が入っている
周囲長さ:基準線は線分を1本のみ、赤い線分は複数検出ため、赤い線分の値が大きくなってしまう
といった問題が発生しており、上手く行っていません。
boudingRect,及びnumpyによるベクトルの算出については自分なりに調べてみましたが、最終的に何を求めているのか、理解ができていません。
補足情報(FW/ツールのバージョンなど)
python3.8
anaconda