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

質問編集履歴

4

微修正

2019/08/06 02:34

投稿

fana
fana

スコア12299

title CHANGED
File without changes
body CHANGED
@@ -133,14 +133,14 @@
133
133
 
134
134
  > ぼかした結果に対して画素毎に異なる閾値を与えて2値化
135
135
 
136
- に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません
136
+ に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません
137
137
 
138
138
  各位置の閾値を高くすべきか低くすべきか?のヒントは,元画像と形状を丸めた画像との差分から得られるであろう,と考えました.
139
139
  (元画像で白だった部分が丸めた結果黒になったならば,その逆処理を行うにはその**付近**の閾値を小さく与えれば良く,元画像で黒だった部分が白に変わった箇所の**付近**では閾値を大きく与えればよい)
140
140
  問題は,「**付近**」にその情報をどのようにして伝達すればよいか?という部分で,ここがまだ未解決です.
141
141
 
142
142
  図3は,とりあえず簡単に試せる伝達手段として,モルフォロジとガウシアンフィルタを用いてみた結果です.
143
- 図3左が閾値マップで,図3右がそれを用いて図1右上の画像を2値化した結果です.
143
+ 図3左が閾値マップで,図3右がそれを用いて図1右上のぼかし画像を2値化した結果です.
144
144
  大まかな形はなんとなく図2の方向に向かっているようにも見えますが,
145
145
  元の形状でとがっていた部分が残念な形になっています→これは閾値マップ生成時の「付近への伝達」手段に点広がり的な方法を用いたためであると思います.
146
146
  何か指向性のある(?)伝達手段を用意できれば,改善するのかもしれません.

3

試行内容追記

2019/08/06 02:34

投稿

fana
fana

スコア12299

title CHANGED
File without changes
body CHANGED
@@ -125,4 +125,25 @@
125
125
  cv::waitKey();
126
126
  return 0;
127
127
  }
128
- ```
128
+ ```
129
+
130
+ ---
131
+
132
+ **やったことの追記**
133
+
134
+ > ぼかした結果に対して画素毎に異なる閾値を与えて2値化
135
+
136
+ に関して,質問後に試行した内容を追記しておきます.(もちろん,解決していません,)
137
+
138
+ 各位置の閾値を高くすべきか低くすべきか?のヒントは,元画像と形状を丸めた画像との差分から得られるであろう,と考えました.
139
+ (元画像で白だった部分が丸めた結果黒になったならば,その逆処理を行うにはその**付近**の閾値を小さく与えれば良く,元画像で黒だった部分が白に変わった箇所の**付近**では閾値を大きく与えればよい)
140
+ 問題は,「**付近**」にその情報をどのようにして伝達すればよいか?という部分で,ここがまだ未解決です.
141
+
142
+ 図3は,とりあえず簡単に試せる伝達手段として,モルフォロジとガウシアンフィルタを用いてみた結果です.
143
+ 図3左が閾値マップで,図3右がそれを用いて図1右上の画像を2値化した結果です.
144
+ 大まかな形はなんとなく図2の方向に向かっているようにも見えますが,
145
+ 元の形状でとがっていた部分が残念な形になっています→これは閾値マップ生成時の「付近への伝達」手段に点広がり的な方法を用いたためであると思います.
146
+ 何か指向性のある(?)伝達手段を用意できれば,改善するのかもしれません.
147
+
148
+ ##### 図3:変動閾値試行結果
149
+ ![イメージ説明](5d63b36e173a26f50de9ef771f9014ce.png)

2

コード追加

2019/08/06 02:32

投稿

fana
fana

スコア12299

title CHANGED
File without changes
body CHANGED
@@ -30,4 +30,99 @@
30
30
  また,できればこのような方法ではなくて,
31
31
  「丸く」する側の処理のような,輪郭座標値を陽に扱わない方法が希望です.
32
32
  (ぼかした結果に対して画素毎に異なる閾値を与えて2値化すれば所望の形状が得られるのではないか?と考えているのですが,
33
- 肝心の妥当な閾値を決める処理をどうすればよいのか?というところで行き詰っております.)
33
+ 肝心の妥当な閾値を決める処理をどうすればよいのか?というところで行き詰っております.)
34
+
35
+ ```C++
36
+ //思いつきでやってみた形状強調処理(結果は思わしくない)
37
+ //
38
+ //処理概要:
39
+ // 入力Contour[k]に関する,結果Result[k]は,
40
+ // 近隣(Contour[k-Wnd]~Contour[k+Wnd])の座標平均GとContour[k]との差deltaを用いて,
41
+ // Result[k] = Contour[k] + Rate*delta
42
+ // where delta = Contour[k] - G
43
+ // ただし,deltaが閾値以下の場合は
44
+ // Result[k] = Contour[k]
45
+ // とする.
46
+ //[Args]
47
+ // Contour : 入力形状(外周画素群の座標)
48
+ // WndR : 参照する近隣範囲
49
+ // Rate : 強調率
50
+ // IgnoreDeltaThresh : ごく小さい変化を強調しない用の閾値
51
+ //[Ret]
52
+ // 結果形状(外周画素群の座標)
53
+ std::vector<cv::Point> EnhanceShape( const std::vector< cv::Point > &Contour, int WndR, float Rate, float IgnoreDeltaThresh=1.0f )
54
+ {
55
+ WndR = std::max( 1, WndR );
56
+ const int WndSize = 2*WndR + 1;
57
+ const float SqThresh = IgnoreDeltaThresh * IgnoreDeltaThresh;
58
+
59
+ const int N = (int)Contour.size();
60
+ std::vector< cv::Point > Result = Contour;
61
+
62
+ for( int i=0; i<N; ++i )
63
+ {
64
+ //近隣重心G
65
+ int SumX=0;
66
+ int SumY=0;
67
+ for( int k=-WndR; k<=WndR; k++ )
68
+ {
69
+ int kk = i+k;
70
+ if( kk>=N )kk-=N;
71
+ if( kk<0 )kk+=N;
72
+
73
+ SumX += Contour[kk].x;
74
+ SumY += Contour[kk].y;
75
+ }
76
+ float GX = (float)SumX / WndSize;
77
+ float GY = (float)SumY / WndSize;
78
+ //delta
79
+ float dx = Contour[i].x - GX;
80
+ float dy = Contour[i].y - GY;
81
+ //Result
82
+ if( dx*dx + dy*dy > SqThresh )
83
+ {
84
+ Result[i].x += cvRound( Rate*dx );
85
+ Result[i].y += cvRound( Rate*dy );
86
+ }
87
+ }
88
+ return Result;
89
+ }
90
+
91
+ int main()
92
+ {
93
+ //原画(2値画像とする)
94
+ cv::Mat Src = cv::imread( "Blobs.png", cv::IMREAD_GRAYSCALE );
95
+ cv::imshow( "Src", Src );
96
+
97
+ {//形状が丸くなる処理
98
+ cv::Mat Blurred;
99
+ const int KernelSize = 41;
100
+ cv::GaussianBlur( Src, Blurred, cv::Size(KernelSize,KernelSize), 0 );
101
+ cv::imshow( "Blurred", Blurred );
102
+
103
+ cv::Mat Rounded;
104
+ cv::threshold( Blurred, Rounded, 128, 255, cv::THRESH_BINARY );
105
+ cv::imshow( "Rounded(Thresh128)", Rounded );
106
+ }
107
+
108
+ {//形状を強調したい
109
+ //外周画素座標をいじくってみるテスト
110
+ std::vector< std::vector< cv::Point > > Contours;
111
+ cv::findContours( Src, Contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE );
112
+ for( auto &Cont : Contours )
113
+ { Cont = EnhanceShape( Cont, 15, 4 ); }
114
+
115
+ {//結果表示
116
+ cv::Mat Show( Src.rows, Src.cols, CV_8UC3 );
117
+ Show = cv::Scalar(255,0,0);
118
+ Show.setTo( cv::Scalar(0,96,0), Src );
119
+ for( int i=0; i<(int)Contours.size(); ++i )
120
+ { cv::drawContours( Show, Contours, i, cv::Scalar(0,0,255) ); }
121
+ cv::imshow( "TestResult", Show );
122
+ }
123
+ }
124
+
125
+ cv::waitKey();
126
+ return 0;
127
+ }
128
+ ```

1

タイトル変更

2019/08/05 02:32

投稿

fana
fana

スコア12299

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