質問編集履歴

4

微修正

2019/08/06 02:34

投稿

fana
fana

スコア11663

test CHANGED
File without changes
test CHANGED
@@ -268,7 +268,7 @@
268
268
 
269
269
 
270
270
 
271
- に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません
271
+ に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません
272
272
 
273
273
 
274
274
 
@@ -282,7 +282,7 @@
282
282
 
283
283
  図3は,とりあえず簡単に試せる伝達手段として,モルフォロジとガウシアンフィルタを用いてみた結果です.
284
284
 
285
- 図3左が閾値マップで,図3右がそれを用いて図1右上の画像を2値化した結果です.
285
+ 図3左が閾値マップで,図3右がそれを用いて図1右上のぼかし画像を2値化した結果です.
286
286
 
287
287
  大まかな形はなんとなく図2の方向に向かっているようにも見えますが,
288
288
 

3

試行内容追記

2019/08/06 02:34

投稿

fana
fana

スコア11663

test CHANGED
File without changes
test CHANGED
@@ -253,3 +253,45 @@
253
253
  }
254
254
 
255
255
  ```
256
+
257
+
258
+
259
+ ---
260
+
261
+
262
+
263
+ **やったことの追記**
264
+
265
+
266
+
267
+ > ぼかした結果に対して画素毎に異なる閾値を与えて2値化
268
+
269
+
270
+
271
+ に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません,)
272
+
273
+
274
+
275
+ 各位置の閾値を高くすべきか低くすべきか?のヒントは,元画像と形状を丸めた画像との差分から得られるであろう,と考えました.
276
+
277
+ (元画像で白だった部分が丸めた結果黒になったならば,その逆処理を行うにはその**付近**の閾値を小さく与えれば良く,元画像で黒だった部分が白に変わった箇所の**付近**では閾値を大きく与えればよい)
278
+
279
+ 問題は,「**付近**」にその情報をどのようにして伝達すればよいか?という部分で,ここがまだ未解決です.
280
+
281
+
282
+
283
+ 図3は,とりあえず簡単に試せる伝達手段として,モルフォロジとガウシアンフィルタを用いてみた結果です.
284
+
285
+ 図3左が閾値マップで,図3右がそれを用いて図1右上の画像を2値化した結果です.
286
+
287
+ 大まかな形はなんとなく図2の方向に向かっているようにも見えますが,
288
+
289
+ 元の形状でとがっていた部分が残念な形になっています→これは閾値マップ生成時の「付近への伝達」手段に点広がり的な方法を用いたためであると思います.
290
+
291
+ 何か指向性のある(?)伝達手段を用意できれば,改善するのかもしれません.
292
+
293
+
294
+
295
+ ##### 図3:変動閾値試行結果
296
+
297
+ ![イメージ説明](5d63b36e173a26f50de9ef771f9014ce.png)

2

コード追加

2019/08/06 02:32

投稿

fana
fana

スコア11663

test CHANGED
File without changes
test CHANGED
@@ -63,3 +63,193 @@
63
63
  (ぼかした結果に対して画素毎に異なる閾値を与えて2値化すれば所望の形状が得られるのではないか?と考えているのですが,
64
64
 
65
65
  肝心の妥当な閾値を決める処理をどうすればよいのか?というところで行き詰っております.)
66
+
67
+
68
+
69
+ ```C++
70
+
71
+ //思いつきでやってみた形状強調処理(結果は思わしくない)
72
+
73
+ //
74
+
75
+ //処理概要:
76
+
77
+ // 入力Contour[k]に関する,結果Result[k]は,
78
+
79
+ // 近隣(Contour[k-Wnd]~Contour[k+Wnd])の座標平均GとContour[k]との差deltaを用いて,
80
+
81
+ // Result[k] = Contour[k] + Rate*delta
82
+
83
+ // where delta = Contour[k] - G
84
+
85
+ // ただし,deltaが閾値以下の場合は
86
+
87
+ // Result[k] = Contour[k]
88
+
89
+ // とする.
90
+
91
+ //[Args]
92
+
93
+ // Contour : 入力形状(外周画素群の座標)
94
+
95
+ // WndR : 参照する近隣範囲
96
+
97
+ // Rate : 強調率
98
+
99
+ // IgnoreDeltaThresh : ごく小さい変化を強調しない用の閾値
100
+
101
+ //[Ret]
102
+
103
+ // 結果形状(外周画素群の座標)
104
+
105
+ std::vector<cv::Point> EnhanceShape( const std::vector< cv::Point > &Contour, int WndR, float Rate, float IgnoreDeltaThresh=1.0f )
106
+
107
+ {
108
+
109
+ WndR = std::max( 1, WndR );
110
+
111
+ const int WndSize = 2*WndR + 1;
112
+
113
+ const float SqThresh = IgnoreDeltaThresh * IgnoreDeltaThresh;
114
+
115
+
116
+
117
+ const int N = (int)Contour.size();
118
+
119
+ std::vector< cv::Point > Result = Contour;
120
+
121
+
122
+
123
+ for( int i=0; i<N; ++i )
124
+
125
+ {
126
+
127
+ //近隣重心G
128
+
129
+ int SumX=0;
130
+
131
+ int SumY=0;
132
+
133
+ for( int k=-WndR; k<=WndR; k++ )
134
+
135
+ {
136
+
137
+ int kk = i+k;
138
+
139
+ if( kk>=N )kk-=N;
140
+
141
+ if( kk<0 )kk+=N;
142
+
143
+
144
+
145
+ SumX += Contour[kk].x;
146
+
147
+ SumY += Contour[kk].y;
148
+
149
+ }
150
+
151
+ float GX = (float)SumX / WndSize;
152
+
153
+ float GY = (float)SumY / WndSize;
154
+
155
+ //delta
156
+
157
+ float dx = Contour[i].x - GX;
158
+
159
+ float dy = Contour[i].y - GY;
160
+
161
+ //Result
162
+
163
+ if( dx*dx + dy*dy > SqThresh )
164
+
165
+ {
166
+
167
+ Result[i].x += cvRound( Rate*dx );
168
+
169
+ Result[i].y += cvRound( Rate*dy );
170
+
171
+ }
172
+
173
+ }
174
+
175
+ return Result;
176
+
177
+ }
178
+
179
+
180
+
181
+ int main()
182
+
183
+ {
184
+
185
+ //原画(2値画像とする)
186
+
187
+ cv::Mat Src = cv::imread( "Blobs.png", cv::IMREAD_GRAYSCALE );
188
+
189
+ cv::imshow( "Src", Src );
190
+
191
+
192
+
193
+ {//形状が丸くなる処理
194
+
195
+ cv::Mat Blurred;
196
+
197
+ const int KernelSize = 41;
198
+
199
+ cv::GaussianBlur( Src, Blurred, cv::Size(KernelSize,KernelSize), 0 );
200
+
201
+ cv::imshow( "Blurred", Blurred );
202
+
203
+
204
+
205
+ cv::Mat Rounded;
206
+
207
+ cv::threshold( Blurred, Rounded, 128, 255, cv::THRESH_BINARY );
208
+
209
+ cv::imshow( "Rounded(Thresh128)", Rounded );
210
+
211
+ }
212
+
213
+
214
+
215
+ {//形状を強調したい
216
+
217
+ //外周画素座標をいじくってみるテスト
218
+
219
+ std::vector< std::vector< cv::Point > > Contours;
220
+
221
+ cv::findContours( Src, Contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE );
222
+
223
+ for( auto &Cont : Contours )
224
+
225
+ { Cont = EnhanceShape( Cont, 15, 4 ); }
226
+
227
+
228
+
229
+ {//結果表示
230
+
231
+ cv::Mat Show( Src.rows, Src.cols, CV_8UC3 );
232
+
233
+ Show = cv::Scalar(255,0,0);
234
+
235
+ Show.setTo( cv::Scalar(0,96,0), Src );
236
+
237
+ for( int i=0; i<(int)Contours.size(); ++i )
238
+
239
+ { cv::drawContours( Show, Contours, i, cv::Scalar(0,0,255) ); }
240
+
241
+ cv::imshow( "TestResult", Show );
242
+
243
+ }
244
+
245
+ }
246
+
247
+
248
+
249
+ cv::waitKey();
250
+
251
+ return 0;
252
+
253
+ }
254
+
255
+ ```

1

タイトル変更

2019/08/05 02:32

投稿

fana
fana

スコア11663

test CHANGED
@@ -1 +1 @@
1
- 2値画像の形状を強調する方法
1
+ 2値画像の形状を強調する方法
test CHANGED
File without changes