回答編集履歴

1

やってみたことを追記

2021/02/04 06:30

投稿

fana
fana

スコア11675

test CHANGED
@@ -19,3 +19,177 @@
19
19
  【カーネルをでかくする ≒ 画像を縮小する】という方向で何かしら考えてやれば良いのではないかと.
20
20
 
21
21
  (例えば,縮小結果の画素値を決める際に,元の画像の黒画素を無視するような)
22
+
23
+
24
+
25
+ ---
26
+
27
+
28
+
29
+ とりあえず原始的なのを何の工夫も無くやってみた.
30
+
31
+ 色を見るのは面倒なので,画像はグレースケールで扱った.
32
+
33
+ 画像は左から
34
+
35
+
36
+
37
+ * グレースケールの原画
38
+
39
+ * でかいSobel (X方向) の結果をてきとーに可視化したもの
40
+
41
+ * 同 y方向
42
+
43
+ * {x方向, y方向}の2つから得たエッジ強度をてきとーに可視化したもの
44
+
45
+
46
+
47
+ カーネルがでかい分だけ,結果も太いが.
48
+
49
+
50
+
51
+ ![イメージ説明](5a67086bc7063f476a3f274406240e09.png)
52
+
53
+
54
+
55
+ ```C++
56
+
57
+ //作業関数.正方形領域内の,輝度値0でない画素群の輝度平均値を算出.
58
+
59
+ double AreaAve( const cv::Mat &Src8U, int left, int top, int S )
60
+
61
+ {
62
+
63
+ unsigned int Sum=0, n=0;
64
+
65
+ for( int dy=0; dy<S; ++dy )
66
+
67
+ {
68
+
69
+ const unsigned char *p = Src8U.ptr<unsigned char>( top + dy, left );
70
+
71
+ for( int dx=0; dx<S; ++dx, ++p )
72
+
73
+ { if( *p ){ Sum += *p; ++n; } }
74
+
75
+ }
76
+
77
+ return ( n ? double(Sum)/n : 0 );
78
+
79
+ }
80
+
81
+
82
+
83
+ //32bit float 画像をてきとーに表示するためのヘルパ.
84
+
85
+ void Show32F( const std::string &WndName, cv::Mat &Img )
86
+
87
+ {
88
+
89
+ double Min,Max;
90
+
91
+ cv::minMaxLoc( Img, &Min,&Max );
92
+
93
+ cv::Mat ShowImg( Img.size(), CV_8U );
94
+
95
+ double alpha = 255 / (Max-Min);
96
+
97
+ double beta = -Min * alpha;
98
+
99
+ Img.convertTo( ShowImg, ShowImg.type(), alpha,beta );
100
+
101
+ cv::imshow( WndName, ShowImg );
102
+
103
+ }
104
+
105
+
106
+
107
+ //main
108
+
109
+ int main()
110
+
111
+ {
112
+
113
+ cv::Mat SrcImg = cv::imread( "Dots.png", cv::IMREAD_GRAYSCALE );
114
+
115
+ if( SrcImg.empty() )return 0;
116
+
117
+
118
+
119
+ const int S = 7; //1マスのサイズ
120
+
121
+ const int KernelR = (S * 3) / 2;
122
+
123
+ const int dx[8] = { -1,0,1, -1,1, -1,0,1 };
124
+
125
+ const int dy[8] = { -1,-1,-1, 0,0, 1,1,1 };
126
+
127
+ const int wx[8] = { -1,0,1, -2,2, -1,0,1 };
128
+
129
+ const int wy[8] = { -1,-2,-1, 0,0, 1,2,1 };
130
+
131
+
132
+
133
+ cv::Mat SX = cv::Mat::zeros( SrcImg.size(), CV_32F );
134
+
135
+ cv::Mat SY = cv::Mat::zeros( SrcImg.size(), CV_32F );
136
+
137
+ cv::Mat Mag = cv::Mat::zeros( SrcImg.size(), CV_32F );
138
+
139
+
140
+
141
+ for( int cy=KernelR; cy+KernelR<SrcImg.rows; ++cy )
142
+
143
+ {
144
+
145
+ float *pSY = SY.ptr<float>( cy );
146
+
147
+ float *pSX = SX.ptr<float>( cy );
148
+
149
+ float *pMag = Mag.ptr<float>( cy );
150
+
151
+ for( int cx=KernelR; cx+KernelR<SrcImg.cols; ++cx )
152
+
153
+ {
154
+
155
+ double Xdir=0, Ydir=0;
156
+
157
+ for( int i=0; i<8; ++i )
158
+
159
+ {
160
+
161
+ double Ave = AreaAve( SrcImg, cx + dx[i]*S - S/2, cy + dy[i]*S - S/2, S );
162
+
163
+ Xdir += Ave * wx[i];
164
+
165
+ Ydir += Ave * wy[i];
166
+
167
+ }
168
+
169
+ pSX[cx] = (float)(Xdir);
170
+
171
+ pSY[cx] = (float)(Ydir);
172
+
173
+ pMag[cx] = (float)sqrt( Xdir*Xdir + Ydir*Ydir );
174
+
175
+ }
176
+
177
+ }
178
+
179
+
180
+
181
+ cv::imshow( "Src", SrcImg );
182
+
183
+ Show32F( "SX", SX );
184
+
185
+ Show32F( "SY", SY );
186
+
187
+ Show32F( "Mag", Mag );
188
+
189
+ cv::waitKey();
190
+
191
+ return 0;
192
+
193
+ }
194
+
195
+ ```