質問するログイン新規登録

回答編集履歴

1

a

2018/10/21 17:29

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -11,4 +11,93 @@
11
11
  返り値
12
12
  * retval: 輪郭の長さ
13
13
 
14
- [参考リンク](http://pynote.hatenablog.com/entry/opencv-contour-manipulation#%E8%BC%AA%E9%83%AD%E3%82%92%E8%BF%91%E4%BC%BC%E3%81%99%E3%82%8B)
14
+ [参考リンク](http://pynote.hatenablog.com/entry/opencv-contour-manipulation#%E8%BC%AA%E9%83%AD%E3%82%92%E8%BF%91%E4%BC%BC%E3%81%99%E3%82%8B)
15
+
16
+
17
+ ## 追記
18
+
19
+ ### 回転した長方形の4点から中心、回転角度、大きさを計算するコード
20
+
21
+ ```python
22
+ def get_rect_info(rect):
23
+ # 長方形の中心
24
+ center = (rect[0] + rect[2]) / 2
25
+
26
+ # 長さが異なる2つの辺の長さをそれぞれ計算する。
27
+ vec1 = rect[0] - rect[1]
28
+ vec2 = rect[1] - rect[2]
29
+ vec1_len = np.linalg.norm(vec1)
30
+ vec2_len = np.linalg.norm(vec2)
31
+
32
+ # 長辺が幅、短辺が高さとする。
33
+ if vec1_len < vec2_len:
34
+ widht, height = vec2_len, vec1_len
35
+ vecw = vec2
36
+ else:
37
+ widht, height = vec1_len, vec2_len
38
+ vecw = vec1
39
+
40
+ # x 軸と長辺のなす角を計算する。
41
+ if np.isclose(vecw[0], 0):
42
+ angle = 0
43
+ else:
44
+ angle = -np.arctan(vecw[1] / vecw[0])
45
+ angle = np.rad2deg(angle)
46
+
47
+ return {'center': center, 'angle': angle, 'size': (width, height)}
48
+ ```
49
+
50
+ ### テスト
51
+
52
+ ```python
53
+ import cv2
54
+ import matplotlib.pyplot as plt
55
+ import numpy as np
56
+ from matplotlib.patches import Polygon
57
+
58
+ x, y = 100, 150
59
+ width, height = 300, 100
60
+ rect = np.array([
61
+ [x, y],
62
+ [x + width, y],
63
+ [x + width, y + height],
64
+ [x, y + height],
65
+ [x, y]], dtype=float)
66
+
67
+ # 長方形を描画する。
68
+ fig, axes = plt.subplots(figsize=(6, 6))
69
+ axes.set_xlim(0, 500)
70
+ axes.set_ylim(0, 500)
71
+
72
+ for angle in range(0, 360, 40):
73
+ # 長方形の中心周りに -angle 回転させる回転行列を作成する。
74
+ center = tuple(((rect[0] + rect[2]) / 2).astype(int))
75
+ R = cv2.getRotationMatrix2D(center, -angle, 1.)
76
+
77
+ # 回転行列を適用し、回転した長方形の点を計算する。
78
+ rotated_rect = cv2.transform(rect.reshape(1, -1, 2), R)[0]
79
+
80
+ # 確認用に描画する。
81
+ axes.add_patch(Polygon(rotated_rect, fill=None, lw=2., color='b'))
82
+
83
+ # 4点の座標から中心、回転角度、大きさを計算する。
84
+ info = get_rect_info(rotated_rect)
85
+
86
+ print('center: {}, angle: {:.2f}, size: {}'.format(info['center'], info['angle'], info['size']))
87
+
88
+ plt.show()
89
+ ```
90
+
91
+ ```
92
+ center: [250. 200.], angle: 0.00, size: (300, 100.0)
93
+ center: [250. 200.], angle: -40.00, size: (300, 100.00000000000001)
94
+ center: [250. 200.], angle: -80.00, size: (300, 100.00000000000004)
95
+ center: [250. 200.], angle: 60.00, size: (300, 100.00000000000004)
96
+ center: [250. 200.], angle: 20.00, size: (300, 99.99999999999999)
97
+ center: [250. 200.], angle: -20.00, size: (300, 100.00000000000004)
98
+ center: [250. 200.], angle: -60.00, size: (300, 100.00000000000001)
99
+ center: [250. 200.], angle: 80.00, size: (300, 100.00000000000006)
100
+ center: [250. 200.], angle: 40.00, size: (300, 100.00000000000001)
101
+ ```
102
+
103
+ ![イメージ説明](e37b0dea807681ee1451cedeecf2a231.png)