回答編集履歴
4
あ
test
CHANGED
@@ -258,12 +258,12 @@
|
|
258
258
|
|
259
259
|
|
260
260
|
|
261
|
+
```
|
262
|
+
|
261
263
|
flag に cv::FLOODFILL_FIXED_RANGE を指定した場合
|
262
264
|
|
263
265
|
|
264
266
|
|
265
|
-
```
|
266
|
-
|
267
267
|
隣接する画素値 - loDiff <= 走査中の画素 <= 隣接する画素値 + upDiff
|
268
268
|
|
269
269
|
|
3
あ
test
CHANGED
@@ -243,3 +243,81 @@
|
|
243
243
|
Utils.bitmapToMat(bitmap_toumei, mat_original);
|
244
244
|
|
245
245
|
```
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
## 連結成分と扱う基準について
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
完全に一致した画素でなく、ある程度似た色は同じ連結成分にしたいという幅を持たせるために loDiff, upDiff という引数があります。
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
同じ連結成分と判定する基準は [floodFill()](https://docs.opencv.org/3.4.3/d7/d1b/group__imgproc__misc.html#ga366aae45a6c1289b341d140839f18717) のリファレンスに記載があります。
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
flag に cv::FLOODFILL_FIXED_RANGE を指定した場合
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
```
|
266
|
+
|
267
|
+
隣接する画素値 - loDiff <= 走査中の画素 <= 隣接する画素値 + upDiff
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
flag に cv::FLOODFILL_FIXED_RANGE を指定していない場合
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
隣接する画素値 - loDiff <= seed の画素値 <= 隣接する画素値 + upDiff
|
276
|
+
|
277
|
+
```
|
278
|
+
|
279
|
+
loDiff, upDiff はグレースケールの場合は、cv::Scalar(s1), カラー画像の場合は cv::Scalar(s1, s2, s3) と指定します。
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
cv::FLOODFILL_FIXED_RANGE をつけるかどうかの違いは、似ているかどうか判断する際の比較する画素が seed の点なのか、隣接する点なのかの違いです。
|
284
|
+
|
285
|
+
以下のグラデーションの画像に各引数で試した結果です。
|
286
|
+
|
287
|
+
|
288
|
+
|
289
|
+

|
290
|
+
|
291
|
+
オリジナル画像
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+

|
296
|
+
|
297
|
+
cv::FLOODFILL_FIXED_RANGE, loDiff=cv::Scalr(0, 0, 0), upDiff=cv::Scalr(0, 0, 0)
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+

|
302
|
+
|
303
|
+
loDiff=cv::Scalr(0, 0, 0), upDiff=cv::Scalr(0, 0, 0)
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+

|
308
|
+
|
309
|
+
cv::FLOODFILL_FIXED_RANGE, loDiff=cv::Scalr(10, 10, 10), upDiff=cv::Scalr(10, 10, 10)
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+

|
314
|
+
|
315
|
+
loDiff=cv::Scalr(10, 10, 10), upDiff=cv::Scalr(10, 10, 10)
|
316
|
+
|
317
|
+
|
318
|
+
|
319
|
+
このパラメータをうまく調整することで精度を上げることができるかもしれません。
|
320
|
+
|
321
|
+
また似た色を同じ色として塗りつぶしたい場合は、第1引数 image の入力を RGB ではなく、cvtColor() で HSV に変換したほうがいいかもしれません。
|
322
|
+
|
323
|
+
[OpenCVでのHSV色空間lower,upperの取り扱い](https://qiita.com/miyamotok0105/items/ce6f44064f128a580640)
|
2
あ
test
CHANGED
@@ -225,3 +225,21 @@
|
|
225
225
|
|
226
226
|
|
227
227
|
チャンネルの並び順を確認するには、cv::imwrite() で書き出すとわかります。(チャンネルが反転してたらRGB、反転してなかったらBGR)
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
## 他に気になる点
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
BGR から BGRA に変換する処理が見当たりませんが、
|
236
|
+
|
237
|
+
mat_original は以下の関数で変換すると、すでに BGRA になっているのでしょうか?
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
```
|
242
|
+
|
243
|
+
Utils.bitmapToMat(bitmap_toumei, mat_original);
|
244
|
+
|
245
|
+
```
|
1
あ
test
CHANGED
@@ -97,3 +97,131 @@
|
|
97
97
|

|
98
98
|
|
99
99
|
結果画像
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
## 追記
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
### グレースケール画像に変換している部分について
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
```
|
112
|
+
|
113
|
+
//■チャネルの変更(floodfillは透明を扱えないため)
|
114
|
+
|
115
|
+
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2GRAY)
|
116
|
+
|
117
|
+
```
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
グレースケールに変換すると RGB の情報量は落ちてしまうので、同じ色を塗りつぶしたいのであれば、グレースケールにする必要はないと思います。
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+

|
126
|
+
|
127
|
+
カラー画像
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+

|
132
|
+
|
133
|
+
グレースケールに変換した画像
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
## mask を初期化していない。
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
```
|
142
|
+
|
143
|
+
Mat mat2 = new Mat(mat.height() + 2 , mat.width() + 2, CV_8UC1);
|
144
|
+
|
145
|
+
```
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
[floodFill()](https://docs.opencv.org/3.4.3/d7/d1b/group__imgproc__misc.html#ga366aae45a6c1289b341d140839f18717) のリファレンスを見ると、次のように書いてあります。
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
```
|
154
|
+
|
155
|
+
Since this is both an input and output parameter, you must take responsibility of initializing it.
|
156
|
+
|
157
|
+
```
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
floodFill() は、指定した点 seed の連結成分を走査する際、mask が0の画素だけ探します。mask が非0の画素は色が同じでも走査しません。名前通り、マスクとして機能するわけです。
|
162
|
+
|
163
|
+
また、floodFill() で見つけた連結成分には、mask に値が書き込まれます。この値は flag 引数の 8 ~ 16 ビット目で指定します。(255 << 8 としている部分です。この場合、連結成分に 255 が書き込まれます。)
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
このように入力または出力の両方で利用される引数であるため、mask の値を初期化するのは呼び出し側の責任になります。
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
今回は、mask はマスクとしては利用せず、走査した結果を受け取るためだけに利用します。走査はすべての画素を対象に行ってほしいので、mask の全要素は 0 で初期化します。
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
そのため、次のようにしていたのですが
|
176
|
+
|
177
|
+
```
|
178
|
+
|
179
|
+
//■Maskデータ作成 cv::Mat mask = cv::Mat::zeros(image.rows + 2, image.cols + 2, CV_8UC1);
|
180
|
+
|
181
|
+
```
|
182
|
+
|
183
|
+
このようにしてしまうと、mat2 の各値は未定義になってしまうので、floodFill() の結果もおかしくなると思われます。
|
184
|
+
|
185
|
+
```
|
186
|
+
|
187
|
+
Mat mat2 = new Mat(mat.height() + 2 , mat.width() + 2, CV_8UC1);
|
188
|
+
|
189
|
+
```
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
C++ 版には全部0で初期化した行列の作成には、cv::Mat::zeros() の他に、以下のものがありますが、Java ではどうでしょうか。
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
```
|
198
|
+
|
199
|
+
Mat(int rows, int cols, int type, const Scalar &s)
|
200
|
+
|
201
|
+
Mat(Size size, int type, const Scalar &s)
|
202
|
+
|
203
|
+
```
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
## チャンネルの並び順
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
チャンネルの並び順には RGB と BGR があり、imread() で読み込んだ場合は、並び順は BGR になります。
|
212
|
+
|
213
|
+
他のライブラリで読み込んだ画像の場合は RGB が多いです。
|
214
|
+
|
215
|
+
そのため、`COLOR_RGBA2GRAY` と `COLOR_BGRA2GRAY` では意味がかわってきますので、注意が必要です。
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
```
|
220
|
+
|
221
|
+
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2GRAY);
|
222
|
+
|
223
|
+
```
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
チャンネルの並び順を確認するには、cv::imwrite() で書き出すとわかります。(チャンネルが反転してたらRGB、反転してなかったらBGR)
|