前提・実現したいこと
下の画像の青い線の長さをそれぞれ求めたいです。
知恵を貸していただけると幸いです。
ここに質問の内容を詳しく書いてください。
研究で心機能評価のための指標を算出しようとしています。その際、2値化された白い輪郭線をもとに青い線の長さを求める必要があります。
実際に手元にある画像は下のような画像で
①.一番下の直線の中点(点ABの中点)を求める
②.①で求めた中点から輪郭線上でもっとも離れた点(点C)を検出し、座標を求める。
③.①で求めた中点と点Cを結ぶ線分を20等分し、20個の領域に分ける。
④.20等分した点それぞれから線分に直交する線(青い線)を引きそれぞれの長さを求める。
発生している問題・エラーメッセージ
現状、
①②③はできています。
具体的には
①.直線検出(cv2.HoughlinesP)し、端点AとBの座標を求めた上で中点の座標を整数値として求める
②.①で求めた点から各輪郭点までのユークリッド距離を求め最大のものを点Cとする
③.np.linspaceで分割
です。
分割後の各点から垂線を引く方法と垂線と輪郭線との交点の座標を取得する方法がわからず試行錯誤しています。
コード #モジュールのインポート import cv2 import matplotlib.pyplot as plt %matplotlib inline import numpy as np import math #最大輪郭を得る関数 def find_max_contour(img): contours, _ = cv2.findContours( img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE ) max_contour = max(contours, key=lambda x:cv2.contourArea(x)) return max_contour # 画像の読み込み img = cv2.imread("opening2.png", 0) color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) lines = cv2.HoughLinesP(img, rho=1, theta=np.pi/360, threshold=80, minLineLength=80, maxLineGap=10) # 複数の直線がある場合、y座標の和がもっとも大きいものを採用 # 中点(mid_x, mid_y) y_sum_dict = {} for i, pos in enumerate(lines.squeeze(1)): y1, y2 = pos[1], pos[3] y_sum_dict[i] = y1 + y2 index = 0 y_sum_max = 0 for i, y_sum in y_sum_dict.items(): if i == 0: index = i y_sum_max = y_sum else: if y_sum_max < y_sum: y_sum_max =y_sum index = i pos = lines.squeeze(1)[index] x1, y1, x2, y2 = pos[0], pos[1], pos[2], pos[3] print(x1, y1, x2, y2) mid_x, mid_y = int((x1+x2)/2), int((y1+y2)/2) print(mid_x, mid_y) # 全ての輪郭上の点に対してユークリッド距離を計算する方針 def get_distance(x1, y1, x2, y2): d = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) return d # 中点から最大距離の点を見つける(api_x, api_y) dist_list = [] for point in max_cnt.squeeze(1): x, y = point[0], point[1] dist = get_distance(mid_x, mid_y, x, y) dist_list.append(dist) max(dist_list) max_dist_index = dist_list.index(max(dist_list)) apical = max_cnt.squeeze(1)[max_dist_index] api_x, api_y = apical[0], apical[1] # 20等分する lins = np.linspace((api_x, api_y), (mid_x, mid_y), 21)
試したこと
ベクトルの内積から垂線をひけるのではないかと考えましたが、その実装ができていません。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答2件
あなたの回答
tips
プレビュー