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

回答編集履歴

4

追記

2018/01/11 15:51

投稿

LouiS0616
LouiS0616

スコア35678

answer CHANGED
@@ -133,7 +133,7 @@
133
133
  main(img_file=sys.argv[1])
134
134
  ```
135
135
 
136
- **partition.py**
136
+ **partition.py** [OpenCV内部実装](https://github.com/opencv/opencv/blob/c7049ca627f47fece7adb2c132ba118209d517e6/modules/core/include/opencv2/core/operations.hpp#L440)の焼き直し
137
137
  ```Python
138
138
  from itertools import product
139
139
  from UnionFind import UnionFind

3

説明追記

2018/01/11 15:51

投稿

LouiS0616
LouiS0616

スコア35678

answer CHANGED
@@ -73,6 +73,7 @@
73
73
  ---
74
74
  前述の理由により正しく動作しませんが... (make_buoy_mask関数に相当)
75
75
  その部分さえ修正できれば、充分実用できるかと。
76
+
76
77
  **find_buoy.py**
77
78
  ```Python
78
79
  import sys
@@ -83,6 +84,7 @@
83
84
  from partition import partition
84
85
 
85
86
 
87
+ # 質問のブイマスク抽出の流用
86
88
  def make_buoy_mask(img):
87
89
  return cv2.inRange(
88
90
  cv2.cvtColor(img, cv2.COLOR_BGR2HSV),
@@ -90,6 +92,7 @@
90
92
  upperb=np.array([200,255,255])
91
93
  )
92
94
 
95
+ # マスク画像を生成してから、ブイの座標のnp.arrayを返す
93
96
  def find_buoy(img):
94
97
  return np.vstack(
95
98
  np.where(make_buoy_mask(img)==255)
@@ -135,6 +138,7 @@
135
138
  from itertools import product
136
139
  from UnionFind import UnionFind
137
140
 
141
+ # 番号を振りなおす e.g. [0, 0, 3, 5, 3, 2] -> [0, 0, 2, 3, 2, 1]
138
142
  def renumber(id_list):
139
143
  id_set = set(id_list)
140
144
  replace_dict = dict(zip(
@@ -143,6 +147,8 @@
143
147
  ))
144
148
  return [replace_dict[elem] for elem in id_list]
145
149
 
150
+ # UnionFind法を用いて、データを分類していく
151
+ # 同一のクラスタであるとの判断基準はpredicate_funcで与える
146
152
  def partition(src_list, predicate_func):
147
153
  src_len = len(src_list)
148
154
  uf = UnionFind(src_len)

2

追記

2018/01/11 15:48

投稿

LouiS0616
LouiS0616

スコア35678

answer CHANGED
@@ -67,4 +67,118 @@
67
67
 
68
68
  ---
69
69
  **実際**
70
- ![実際](46dea120c1c96f487f5d957307d1bae6.jpeg)
70
+ ![実際](46dea120c1c96f487f5d957307d1bae6.jpeg)
71
+
72
+ 『ブイ候補』を正しく認識できたなら...
73
+ ---
74
+ 前述の理由により正しく動作しませんが... (make_buoy_mask関数に相当)
75
+ その部分さえ修正できれば、充分実用できるかと。
76
+ **find_buoy.py**
77
+ ```Python
78
+ import sys
79
+
80
+ import numpy as np
81
+ import cv2
82
+
83
+ from partition import partition
84
+
85
+
86
+ def make_buoy_mask(img):
87
+ return cv2.inRange(
88
+ cv2.cvtColor(img, cv2.COLOR_BGR2HSV),
89
+ lowerb=np.array([170,100,190]),
90
+ upperb=np.array([200,255,255])
91
+ )
92
+
93
+ def find_buoy(img):
94
+ return np.vstack(
95
+ np.where(make_buoy_mask(img)==255)
96
+ ).T
97
+
98
+ def main(img_file):
99
+ img = cv2.imread(img_file)
100
+
101
+ # Find buoy pixels
102
+ buoy_pts = find_buoy(img)
103
+ buoy_ids = partition(
104
+ buoy_pts,
105
+ lambda x, y: np.linalg.norm(x-y) <= 10
106
+ )
107
+
108
+ # Get center of buoys
109
+ num_of_buoy = max(buoy_ids) + 1
110
+ typical_buoy_pts = [
111
+ buoy_pts[buoy_ids.index(i)]
112
+ for i in range(num_of_buoy)
113
+ ]
114
+
115
+ # Check buoy position
116
+ RED = (0, 0, 255)
117
+ for buoy in typical_buoy_pts:
118
+ cv2.circle(img, tuple(buoy), radius=10, color=RED, thickness=5)
119
+
120
+ # Show result
121
+ cv2.imshow('result', img)
122
+ cv2.waitKey()
123
+ cv2.destroyAllWindows()
124
+
125
+ if __name__ == '__main__':
126
+ if len(sys.argv) != 2:
127
+ print('Usage: find_buoy.py img_file')
128
+ exit()
129
+
130
+ main(img_file=sys.argv[1])
131
+ ```
132
+
133
+ **partition.py**
134
+ ```Python
135
+ from itertools import product
136
+ from UnionFind import UnionFind
137
+
138
+ def renumber(id_list):
139
+ id_set = set(id_list)
140
+ replace_dict = dict(zip(
141
+ sorted(list(id_set)),
142
+ [i for i, _ in enumerate(id_set)]
143
+ ))
144
+ return [replace_dict[elem] for elem in id_list]
145
+
146
+ def partition(src_list, predicate_func):
147
+ src_len = len(src_list)
148
+ uf = UnionFind(src_len)
149
+
150
+ loop_obj = product(src_list, src_list)
151
+ for ij, (ei, ej) in enumerate(loop_obj):
152
+ i, j = divmod(ij, src_len)
153
+
154
+ if ei is ej:
155
+ continue
156
+ if not predicate_func(ei, ej):
157
+ continue
158
+
159
+ uf.union(i, j)
160
+
161
+ return renumber(uf._id)
162
+ ```
163
+
164
+ **test_partition.py**
165
+ ```Python
166
+ import unittest
167
+ from partition import partition
168
+
169
+ class TestPartition(unittest.TestCase):
170
+ def test_partition(self):
171
+ self.assertEqual(
172
+ partition([1, 2, 3, 7, 8, 9, 2], lambda x, y: abs(x-y) <= 1),
173
+ [0, 0, 0, 1, 1, 1, 0]
174
+ )
175
+ self.assertEqual(
176
+ partition([1, 1, 1, 3, 4, 4, 5, 6], lambda x, y: x % 2 == y % 2),
177
+ [0, 0, 0, 0, 1, 1, 0, 1]
178
+ )
179
+
180
+ if __name__ == '__main__':
181
+ unittest.main()
182
+ ```
183
+
184
+ UnionFind.pyは、[既にあるもの](https://gist.github.com/SonechkaGodovykh/18f60a3b9b3e6812c071456f61f9c5a6)を利用。

1

追記

2018/01/11 15:42

投稿

LouiS0616
LouiS0616

スコア35678

answer CHANGED
@@ -26,4 +26,45 @@
26
26
  『良い感じに赤色の物体が写っている画像』を用意するのはなかなか大変です。
27
27
  どれくらいの大きさ、どれくらいの数を想定しているのかわからないですから。
28
28
 
29
- 適当にテスト画像を用意してくださると回答しやすいので、次回以降は気にかけてみてください。
29
+ 適当にテスト画像を用意してくださると回答しやすいので、次回以降は気にかけてみてください。
30
+
31
+ そもそもブイを正しく抽出できてなさそう
32
+ ---
33
+ 次のコードで実験しました、が...
34
+ ```Python
35
+ import cv2
36
+ import numpy as np
37
+
38
+
39
+ def main():
40
+ img = cv2.imread('sea.jpg')
41
+
42
+ hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
43
+ lower_red = np.array([170,100,190])
44
+ upper_red = np.array([200,255,255])
45
+ mask = cv2.inRange(hsv_img, lower_red, upper_red)
46
+
47
+ #
48
+ # Write points
49
+ points = np.vstack(
50
+ np.where(mask==255)
51
+ ).T
52
+
53
+ RED = (0, 0, 255)
54
+ for pt in map(tuple, points):
55
+ cv2.circle(img, pt, radius=20, color=RED, thickness=-1)
56
+
57
+ cv2.imwrite('result.jpg', img)
58
+ #
59
+ #
60
+
61
+ if __name__ == "__main__":
62
+ main()
63
+ ```
64
+
65
+ **期待**
66
+ ![期待](714fa0fa145802b955c0111eb97ab977.jpeg)
67
+
68
+ ---
69
+ **実際**
70
+ ![実際](46dea120c1c96f487f5d957307d1bae6.jpeg)