回答編集履歴
4
追記
answer
CHANGED
@@ -172,4 +172,85 @@
|
|
172
172
|
```
|
173
173
|
jug1 = cv2.pointPolygonTest(box, X1, False)
|
174
174
|
jug2 = cv2.pointPolygonTest(box, X2, False)
|
175
|
+
```
|
176
|
+
|
177
|
+
## 提示されたコードの修正バージョン
|
178
|
+
|
179
|
+
```python
|
180
|
+
import cv2
|
181
|
+
import math
|
182
|
+
import matplotlib.pyplot as plt
|
183
|
+
import numpy as np
|
184
|
+
|
185
|
+
img_src = cv2.imread("sample.jpg")
|
186
|
+
|
187
|
+
gauss = cv2.GaussianBlur(img_src, (11, 11), 0)
|
188
|
+
gray = cv2.cvtColor(gauss, cv2.COLOR_BGR2GRAY)
|
189
|
+
ret,th1 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
|
190
|
+
edges = cv2.Canny(th1, 50, 150)
|
191
|
+
img, contours, hierarchy = cv2.findContours(th1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1)
|
192
|
+
|
193
|
+
for cnt in contours:
|
194
|
+
cnt = contours[i]
|
195
|
+
area = cv2.contourArea(cnt)
|
196
|
+
print(area)
|
197
|
+
|
198
|
+
if 500 < area < 5000:
|
199
|
+
rect = cv2.minAreaRect(cnt)
|
200
|
+
box = cv2.boxPoints(rect)
|
201
|
+
|
202
|
+
(cx, cy), (width, height), angle = rect
|
203
|
+
diag = np.linalg.norm([width, height])
|
204
|
+
print(width, height, diag)
|
205
|
+
# 161.91236877441406 16.144147872924805 162.715237986
|
206
|
+
|
207
|
+
# 長方形の幅、高さ、対角線の長さは cv2.minAreaRect() の返り値
|
208
|
+
# を見ればわかるので計算しなくてもよい。
|
209
|
+
x1, x2, x3, x4 = box
|
210
|
+
A = np.linalg.norm(x1 - x2)
|
211
|
+
B = np.linalg.norm(x1 - x3)
|
212
|
+
C = np.linalg.norm(x1 - x4)
|
213
|
+
print("頂点",x1, x2, x3, x4)
|
214
|
+
print("Aの長さ", A) # Aの長さ 16.1441
|
215
|
+
print("Bの長さ",B) # Bの長さ 162.715
|
216
|
+
print("Cの長さ",C) # Cの長さ 161.912
|
217
|
+
|
218
|
+
if A < B:
|
219
|
+
min = A
|
220
|
+
else:
|
221
|
+
min = B
|
222
|
+
if C < min:
|
223
|
+
min = C
|
224
|
+
print("最小", min)
|
225
|
+
if 5 < min < 25:
|
226
|
+
# drawContours() の contours 引数は int 型でないといけない。
|
227
|
+
cv2.drawContours(img_src, [box.astype(int)], -1, (0, 255, 0), 2)
|
228
|
+
|
229
|
+
|
230
|
+
def within(line, rect):
|
231
|
+
"""line が rect に含まれるかどうか
|
232
|
+
"""
|
233
|
+
p1, p2 = tuple(line[:2]), tuple(line[2:])
|
234
|
+
# 線の始点と終点が長方形内に含まれるかどうか
|
235
|
+
return cv2.pointPolygonTest(box, p1, False) >= 0 and \
|
236
|
+
cv2.pointPolygonTest(box, p2, False) >= 0
|
237
|
+
|
238
|
+
LSD = cv2.createLineSegmentDetector()
|
239
|
+
lines, width, prec, nfa = LSD.detect(edges)
|
240
|
+
lines = np.squeeze(lines)
|
241
|
+
|
242
|
+
for line in lines:
|
243
|
+
p1, p2 = tuple(line[:2]), tuple(line[2:])
|
244
|
+
|
245
|
+
if within(line, rect):
|
246
|
+
# 長方形に含まれる場合は赤色で描画
|
247
|
+
cv2.line(img_src, p1, p2, (0, 0, 255), 2)
|
248
|
+
else:
|
249
|
+
# 長方形に含まれない場合は赤色で描画
|
250
|
+
cv2.line(img_src, p1, p2, (255, 0, 0), 2)
|
251
|
+
|
252
|
+
# cv2.imwrite("teratail.jpg", img_src)
|
253
|
+
cv2.imshow('src', img_src)
|
254
|
+
cv2.waitKey()
|
255
|
+
cv2.destroyAllWindows()
|
175
256
|
```
|
3
変更点提示
answer
CHANGED
@@ -142,4 +142,34 @@
|
|
142
142
|
cv2.line(_img, p1, p2, (255, 0, 0), 2)
|
143
143
|
```
|
144
144
|
|
145
|
-

|
145
|
+

|
146
|
+
|
147
|
+
### TypeError: contour is not a numerical tuple について
|
148
|
+
|
149
|
+
cv2.pointPolygonTest() の第1引数 contour に渡された値がおかしいというエラーです。
|
150
|
+
OpenCV の Python ラッパーで contour というものが出てきたら、これは (NumPoints, 2) の numpy 配列です。
|
151
|
+
|
152
|
+
実際、値を見てみると、以下のようになっています。
|
153
|
+
cv2.minAreaRect() で輪郭を囲む回転した長方形の `((中心の x 座標, 中心の y 座標), (長方形の幅, 長方形の高さ), 回転角度)` を返すので、これを cv2.boxPoints() で4点の座標からなる輪郭 (contour) に変換しているので、あなたのコード中の `rect` ではなく、`box`を渡さないといけません。
|
154
|
+
|
155
|
+
```
|
156
|
+
print(rect)
|
157
|
+
# ((177.51132202148438, 77.53165435791016), (161.91236877441406, 16.144147872924805), -19.653823852539062)
|
158
|
+
print(box)
|
159
|
+
# [[103 112]
|
160
|
+
# [ 98 97]
|
161
|
+
# [251 42]
|
162
|
+
# [256 57]]
|
163
|
+
```
|
164
|
+
|
165
|
+
変更が必要な箇所
|
166
|
+
|
167
|
+
```
|
168
|
+
jug1 = cv2.pointPolygonTest(rect, X1, False)
|
169
|
+
jug2 = cv2.pointPolygonTest(rect, X2, False)
|
170
|
+
```
|
171
|
+
↓
|
172
|
+
```
|
173
|
+
jug1 = cv2.pointPolygonTest(box, X1, False)
|
174
|
+
jug2 = cv2.pointPolygonTest(box, X2, False)
|
175
|
+
```
|
2
画像が間違っていたので修正
answer
CHANGED
@@ -142,4 +142,4 @@
|
|
142
142
|
cv2.line(_img, p1, p2, (255, 0, 0), 2)
|
143
143
|
```
|
144
144
|
|
145
|
-

|
1
コード追記
answer
CHANGED
@@ -71,4 +71,75 @@
|
|
71
71
|
rect contains line 2.
|
72
72
|
```
|
73
73
|
|
74
|
-

|
74
|
+

|
75
|
+
|
76
|
+
----
|
77
|
+
|
78
|
+
## 追記
|
79
|
+
|
80
|
+
```
|
81
|
+
import cv2
|
82
|
+
import numpy as np
|
83
|
+
|
84
|
+
def extract_contour(binary):
|
85
|
+
"""2値画像から輪郭を抽出する。
|
86
|
+
"""
|
87
|
+
# 輪郭を抽出する。
|
88
|
+
_, contours, _ = cv2.findContours(
|
89
|
+
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1)
|
90
|
+
|
91
|
+
if not contours:
|
92
|
+
return # 輪郭がない場合
|
93
|
+
|
94
|
+
# 面積が最大の輪郭を抽出する。
|
95
|
+
cnt = max(contours, key=lambda cnt: cv2.contourArea(cnt))
|
96
|
+
# 輪郭を囲む回転した長方形を取得する。
|
97
|
+
rect = cv2.boxPoints(cv2.minAreaRect(cnt))
|
98
|
+
|
99
|
+
return rect
|
100
|
+
|
101
|
+
# 画像を読み込む。
|
102
|
+
img = cv2.imread("test.jpg")
|
103
|
+
# グレースケールにする。
|
104
|
+
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
105
|
+
# 2値化する。
|
106
|
+
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
|
107
|
+
|
108
|
+
# 長方形を取得する。
|
109
|
+
rect = extract_contour(binary)
|
110
|
+
|
111
|
+
# 回転した長方形を描画する。
|
112
|
+
_img = img.copy()
|
113
|
+
cv2.drawContours(_img, [rect.astype(int)], -1, (0, 255, 0), 2)
|
114
|
+
|
115
|
+
def within(line, rect):
|
116
|
+
"""line が rect に含まれるかどうか
|
117
|
+
"""
|
118
|
+
p1, p2 = tuple(line[:2]), tuple(line[2:])
|
119
|
+
# 線の始点と終点が長方形内に含まれるかどうか
|
120
|
+
return cv2.pointPolygonTest(rect, p1, False) >= 0 and \
|
121
|
+
cv2.pointPolygonTest(rect, p2, False) >= 0
|
122
|
+
|
123
|
+
# Canny エッジ検出を行う。
|
124
|
+
edges = cv2.Canny(binary, 50, 150)
|
125
|
+
|
126
|
+
# 直線を検出する。
|
127
|
+
LSD = cv2.createLineSegmentDetector()
|
128
|
+
lines, _, _, _ = LSD.detect(edges)
|
129
|
+
|
130
|
+
print(lines.shape) # (18, 1, 4)
|
131
|
+
lines = np.squeeze(lines) # 余分な次元削除
|
132
|
+
|
133
|
+
# 線が長方形内に含まれるかどうか調べる。
|
134
|
+
for line in lines:
|
135
|
+
p1, p2 = tuple(line[:2]), tuple(line[2:])
|
136
|
+
|
137
|
+
if within(line, rect):
|
138
|
+
# 長方形に含まれる場合は赤色で描画
|
139
|
+
cv2.line(_img, p1, p2, (0, 0, 255), 2)
|
140
|
+
else:
|
141
|
+
# 長方形に含まれない場合は赤色で描画
|
142
|
+
cv2.line(_img, p1, p2, (255, 0, 0), 2)
|
143
|
+
```
|
144
|
+
|
145
|
+

|