質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3529閲覧

多角形の内角の行列を求める方法

退会済みユーザー

退会済みユーザー

総合スコア0

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/02/26 13:30

以下の図形の内角をそれぞれ求めその行列を作成する方法はありますでしょうか?
イメージ説明
現在考えている方法は

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

輪郭抽出まではいつもの流れ

  1. グレースケール
  2. 2値化
  3. 輪郭抽出
  4. 輪郭の近似

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)

角度を計算する。

  1. 角度を求めたい点とその隣接する点を取得する。(np.take())
  2. 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

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/02/28 09:27

ありがとうございます。参考にさせていただきます。
guest

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

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2019/02/27 04:52 編集

内角と外角が区別する方法はないかなと思っていたのですが、そのようにすればいいのですね。 とても参考になりました。ありがとうございます。
退会済みユーザー

退会済みユーザー

2019/02/28 09:28

ありがとうございます。二つともベストアンサーにしたかったのですが、先に答えをいただいた方にさせて頂きます。こちらも参考にさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問