回答編集履歴
1
追記
test
CHANGED
@@ -31,3 +31,157 @@
|
|
31
31
|
度数分布を求めるだけですから,難しい話ではありません。
|
32
32
|
|
33
33
|
画像のy方向サイズ分の配列でも用意して(要素は全0に初期化しておき),画像の全画素を走査して,エッジ点のy座標に対応する配列要素をインクリメントすることを繰り返せばよいでしょう.
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
---
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
とりあえず,ものすごーく雑に実装してみました.
|
42
|
+
|
43
|
+
(当方,pythonがダメなので,C++ですが)
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
```ここに言語を入力
|
48
|
+
|
49
|
+
int main(void)
|
50
|
+
|
51
|
+
{
|
52
|
+
|
53
|
+
//画像読込
|
54
|
+
|
55
|
+
cv::Mat Src = cv::imread( "SrcImg.png", CV_LOAD_IMAGE_GRAYSCALE );
|
56
|
+
|
57
|
+
if( Src.empty() )return 0;
|
58
|
+
|
59
|
+
cv::imshow( "Src", Src );
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
//ヒストグラム作成
|
64
|
+
|
65
|
+
std::vector< unsigned int > Hist( Src.rows, 0 ); //y方向サイズ分の配列.全要素0で初期化.
|
66
|
+
|
67
|
+
for( int y=1; y+1<Src.rows; ++y )
|
68
|
+
|
69
|
+
{
|
70
|
+
|
71
|
+
const unsigned char *pU = Src.ptr<unsigned char>( y-1 );
|
72
|
+
|
73
|
+
const unsigned char *pC = Src.ptr<unsigned char>( y );
|
74
|
+
|
75
|
+
const unsigned char *pD = Src.ptr<unsigned char>( y+1 );
|
76
|
+
|
77
|
+
for( int x=1; x+1<Src.cols; ++x )
|
78
|
+
|
79
|
+
{
|
80
|
+
|
81
|
+
int Dx = std::max( abs( pC[x]-pC[x-1] ), abs( pC[x]-pC[x+1] ) );
|
82
|
+
|
83
|
+
int Dy = std::max( abs( pC[x]-pU[x] ), abs( pC[x]-pD[x] ) );
|
84
|
+
|
85
|
+
if( Dy>32 && Dy > Dx*4 ) //※エッジ点判定.雑すぎるが.
|
86
|
+
|
87
|
+
{ ++Hist[y]; }
|
88
|
+
|
89
|
+
}
|
90
|
+
|
91
|
+
}
|
92
|
+
|
93
|
+
unsigned int MaxVal = *std::max_element( Hist.begin(), Hist.end() ); //ヒストグラムの最大値
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
{//表示:ヒストグラム画像
|
98
|
+
|
99
|
+
cv::Mat HistImg = cv::Mat::zeros( Src.rows, 100, CV_8U );
|
100
|
+
|
101
|
+
for( int y=0; y<Src.rows; ++y ){ cv::line( HistImg, cv::Point(0,y), cv::Point(100,y), cv::Scalar( 255.0 * Hist[y] / MaxVal ) ); }
|
102
|
+
|
103
|
+
cv::imshow( "Hist", HistImg );
|
104
|
+
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
//てきとー処理でヒストグラムの山(=線のy座標)を見つける
|
110
|
+
|
111
|
+
std::vector< int > LineY; //ここに見つけた山のy座標群を格納
|
112
|
+
|
113
|
+
{
|
114
|
+
|
115
|
+
unsigned int Thresh = MaxVal * 0.75; //閾値
|
116
|
+
|
117
|
+
int RiseY = -1; //閾値を越えた箇所記憶用.越えてないときは-1
|
118
|
+
|
119
|
+
for( int y=0; y<Hist.size(); ++y )
|
120
|
+
|
121
|
+
{
|
122
|
+
|
123
|
+
if( RiseY < 0 )
|
124
|
+
|
125
|
+
{
|
126
|
+
|
127
|
+
if( Hist[y]>=Thresh )
|
128
|
+
|
129
|
+
{ RiseY = y; }
|
130
|
+
|
131
|
+
}
|
132
|
+
|
133
|
+
else
|
134
|
+
|
135
|
+
{
|
136
|
+
|
137
|
+
if( Hist[y]<Thresh )
|
138
|
+
|
139
|
+
{
|
140
|
+
|
141
|
+
LineY.push_back( (RiseY + y)/2 );
|
142
|
+
|
143
|
+
RiseY = -1;
|
144
|
+
|
145
|
+
}
|
146
|
+
|
147
|
+
}
|
148
|
+
|
149
|
+
}
|
150
|
+
|
151
|
+
}
|
152
|
+
|
153
|
+
{//表示:線検出結果
|
154
|
+
|
155
|
+
cv::Mat Result;
|
156
|
+
|
157
|
+
cv::cvtColor( Src, Result, CV_GRAY2BGR );
|
158
|
+
|
159
|
+
for( int y : LineY ){ cv::line( Result, cv::Point(0,y), cv::Point(Result.cols,y), cv::Scalar( 0,0,255 ) ); }
|
160
|
+
|
161
|
+
cv::imshow( "Lines", Result );
|
162
|
+
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
//
|
168
|
+
|
169
|
+
cv::waitKey();
|
170
|
+
|
171
|
+
return 0;
|
172
|
+
|
173
|
+
}
|
174
|
+
|
175
|
+
```
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
結果の絵.
|
180
|
+
|
181
|
+
左から,原画,ヒストグラムを可視化したもの,線の位置を赤色で書いたもの.
|
182
|
+
|
183
|
+
(原画はてきとーにペイントで手書きしました.
|
184
|
+
|
185
|
+
線だけだと微秒なので,雑音として,小学校のときにこんな記号習ったような…?というのを何となく散りばめました.)
|
186
|
+
|
187
|
+
![イメージ説明](7dd2d2bd34c6ccd9fd52d94dfba55252.png)
|