以下の図形の内角をそれぞれ求めその行列を作成する方法はありますでしょうか?
現在考えている方法は
python
1import cv2 2import numpy as np 3 4# 画像読み込み 5img = cv2.imread('test.png', 0) 6# 輪郭抽出 7contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
により各頂点の座標を求めてから内角を求める方法を考えています。よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
輪郭抽出まではいつもの流れ
- グレースケール
- 2値化
- 輪郭抽出
- 輪郭の近似
python
1import cv2 2import numpy as np 3 4# 画像読み込み 5img = cv2.imread('test.png') 6# 2値化 7gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8ret, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV) 9# 輪郭抽出 10contours = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0] 11cnt = contours[0] 12# 近似 13arclen = cv2.arcLength(cnt, closed=True) 14approx = cv2.approxPolyDP(cnt, epsilon=0.03 * arclen, closed=True) 15approx = approx.squeeze(axis=1)
角度を計算する。
- 角度を求めたい点とその隣接する点を取得する。(np.take())
- 2つのベクトルのなす角の求め方 より角度を求める。
angles = [] for i in range(len(approx)): # ある点とその隣接する点を取得し、ベクトルを作る。 p1, p2, p3 = np.take(approx, [i - 1, i, i + 1], axis=0, mode='wrap') v1, v2 = p1 - p2, p3 - p2 # ベクトル v1, v2 のなす角を求める。 cos = np.inner(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) deg = np.rad2deg(np.arccos(cos)) angles.append(deg) print(angles)
描画する。(デバッグ用)
python
1from matplotlib.patches import Polygon 2fig, ax = plt.subplots(figsize=(6, 6)) 3# 画像を描画する。 4ax.imshow(img[...,::-1]) 5ax.axis('off') 6# 輪郭の点同士を結ぶ線を描画する。 7ax.add_patch(Polygon(approx, color='b', fill=None, lw=2)) 8# 輪郭の点を描画する。 9ax.plot(approx[:, 0], approx[:, 1], 'ro', mew=0, ms=6) 10# 角度を描画する。 11for (x, y), angle in zip(approx, angles): 12 ax.text(x, y, '{:.0f}'.format(angle), fontsize=16) 13plt.show()
投稿2019/02/26 13:59
総合スコア21956
0
tiitoiさん回答に少しだけ付け足しです。
ベクトルの内積に対してarccosで角度を求めると内角が180未満なのか180度超なのか区別がつかず常に180未満となります。arccosの値域が0~πだからです。内角を求める場合はそれぞれのベクトルに対して全ての象限の方向を区別できるような方法で計算するとよいと思います。例えばarctan2の値域は-π~πなのでこういう計算には都合がよいと思います。
Python
1# tiitoiさんのコードの一部 2 3... 4 # ベクトル v1, v2 のなす角を求める。 5 cos = np.inner(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) 6 deg = np.rad2deg(np.arccos(cos)) 7... 8 9# 上記を次のように変更 10 11... 12 # ベクトル v1, v2 のなす角(反時計回りの角度)を求める。 13 dir1 = np.rad2deg(np.arctan2(v1[1], v1[0])) # v1の方向 14 dir2 = np.rad2deg(np.arctan2(v2[1], v2[0])) # v2の方向 15 deg = (dir2 - dir1) % 360 16...
こういうふうに変更するとprint([*map(round, angles)])
の結果は
[109.0, 109.0, 279.0, 54.0, 85.0, 53.0, 283.0, 109.0]
になります。
投稿2019/02/27 04:09
総合スコア18394
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/02/28 09:28
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/02/28 09:27