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

回答編集履歴

1

やってみたことを追記

2021/02/04 06:30

投稿

fana
fana

スコア12286

answer CHANGED
@@ -8,4 +8,91 @@
8
8
 
9
9
  で,ほんとにでかいカーネルで計算するのは処理時間とかが嫌な感じでしょうから
10
10
  【カーネルをでかくする ≒ 画像を縮小する】という方向で何かしら考えてやれば良いのではないかと.
11
- (例えば,縮小結果の画素値を決める際に,元の画像の黒画素を無視するような)
11
+ (例えば,縮小結果の画素値を決める際に,元の画像の黒画素を無視するような)
12
+
13
+ ---
14
+
15
+ とりあえず原始的なのを何の工夫も無くやってみた.
16
+ 色を見るのは面倒なので,画像はグレースケールで扱った.
17
+ 画像は左から
18
+
19
+ * グレースケールの原画
20
+ * でかいSobel (X方向) の結果をてきとーに可視化したもの
21
+ * 同 y方向
22
+ * {x方向, y方向}の2つから得たエッジ強度をてきとーに可視化したもの
23
+
24
+ カーネルがでかい分だけ,結果も太いが.
25
+
26
+ ![イメージ説明](5a67086bc7063f476a3f274406240e09.png)
27
+
28
+ ```C++
29
+ //作業関数.正方形領域内の,輝度値0でない画素群の輝度平均値を算出.
30
+ double AreaAve( const cv::Mat &Src8U, int left, int top, int S )
31
+ {
32
+ unsigned int Sum=0, n=0;
33
+ for( int dy=0; dy<S; ++dy )
34
+ {
35
+ const unsigned char *p = Src8U.ptr<unsigned char>( top + dy, left );
36
+ for( int dx=0; dx<S; ++dx, ++p )
37
+ { if( *p ){ Sum += *p; ++n; } }
38
+ }
39
+ return ( n ? double(Sum)/n : 0 );
40
+ }
41
+
42
+ //32bit float 画像をてきとーに表示するためのヘルパ.
43
+ void Show32F( const std::string &WndName, cv::Mat &Img )
44
+ {
45
+ double Min,Max;
46
+ cv::minMaxLoc( Img, &Min,&Max );
47
+ cv::Mat ShowImg( Img.size(), CV_8U );
48
+ double alpha = 255 / (Max-Min);
49
+ double beta = -Min * alpha;
50
+ Img.convertTo( ShowImg, ShowImg.type(), alpha,beta );
51
+ cv::imshow( WndName, ShowImg );
52
+ }
53
+
54
+ //main
55
+ int main()
56
+ {
57
+ cv::Mat SrcImg = cv::imread( "Dots.png", cv::IMREAD_GRAYSCALE );
58
+ if( SrcImg.empty() )return 0;
59
+
60
+ const int S = 7; //1マスのサイズ
61
+ const int KernelR = (S * 3) / 2;
62
+ const int dx[8] = { -1,0,1, -1,1, -1,0,1 };
63
+ const int dy[8] = { -1,-1,-1, 0,0, 1,1,1 };
64
+ const int wx[8] = { -1,0,1, -2,2, -1,0,1 };
65
+ const int wy[8] = { -1,-2,-1, 0,0, 1,2,1 };
66
+
67
+ cv::Mat SX = cv::Mat::zeros( SrcImg.size(), CV_32F );
68
+ cv::Mat SY = cv::Mat::zeros( SrcImg.size(), CV_32F );
69
+ cv::Mat Mag = cv::Mat::zeros( SrcImg.size(), CV_32F );
70
+
71
+ for( int cy=KernelR; cy+KernelR<SrcImg.rows; ++cy )
72
+ {
73
+ float *pSY = SY.ptr<float>( cy );
74
+ float *pSX = SX.ptr<float>( cy );
75
+ float *pMag = Mag.ptr<float>( cy );
76
+ for( int cx=KernelR; cx+KernelR<SrcImg.cols; ++cx )
77
+ {
78
+ double Xdir=0, Ydir=0;
79
+ for( int i=0; i<8; ++i )
80
+ {
81
+ double Ave = AreaAve( SrcImg, cx + dx[i]*S - S/2, cy + dy[i]*S - S/2, S );
82
+ Xdir += Ave * wx[i];
83
+ Ydir += Ave * wy[i];
84
+ }
85
+ pSX[cx] = (float)(Xdir);
86
+ pSY[cx] = (float)(Ydir);
87
+ pMag[cx] = (float)sqrt( Xdir*Xdir + Ydir*Ydir );
88
+ }
89
+ }
90
+
91
+ cv::imshow( "Src", SrcImg );
92
+ Show32F( "SX", SX );
93
+ Show32F( "SY", SY );
94
+ Show32F( "Mag", Mag );
95
+ cv::waitKey();
96
+ return 0;
97
+ }
98
+ ```