質問編集履歴
4
微修正
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
試行内容追記
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
|
+

|
2
コード追加
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
タイトル変更
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
2値
|
1
|
+
2値画像の形状を強調する方法
|
body
CHANGED
File without changes
|