37
37
#include < math.h>
38
38
#include < vector>
39
39
#include < iostream>
40
+ #include < stack>
41
+ #include < algorithm>
40
42
41
43
namespace cv {
42
44
namespace ximgproc {
@@ -53,6 +55,133 @@ static inline Point normalizeAnchor(Point anchor, Size ksize)
53
55
return anchor;
54
56
}
55
57
58
+ static std::vector<Rect> GetCoveringRectangles (InputArray _kernel)
59
+ {
60
+ std::vector<Rect> rects;
61
+ Mat kernel = _kernel.getMat ();
62
+ int kCount = 0 ;
63
+
64
+ // 行ごとで四角を作るだけの実装
65
+ for (int row = 0 ; row < kernel.rows ; row++)
66
+ {
67
+ uchar pre = 0 ;
68
+ for (int col = 0 ; col < kernel.cols ; col++)
69
+ {
70
+ if (pre == 1 && kernel.ptr (row)[col] == 0 )
71
+ {
72
+ rects[kCount ].width = col - rects[kCount ].x ;
73
+ kCount ++;
74
+ }
75
+ if (pre == 0 && kernel.ptr (row)[col] == 1 )
76
+ {
77
+ rects.emplace_back (col, row, 0 , 1 );
78
+ }
79
+ pre = kernel.ptr (row)[col];
80
+ }
81
+ if (pre == 1 )
82
+ {
83
+ rects[kCount ].width = kernel.cols - rects[kCount ].x ;
84
+ kCount ++;
85
+ }
86
+ }
87
+ return rects;
88
+ }
89
+
90
+ enum Dim
91
+ {
92
+ Col, Row
93
+ };
94
+
95
+ struct StStep
96
+ {
97
+ StStep (int dimR, int dimC, Dim _ax)
98
+ {
99
+ dimRow = dimR;
100
+ dimCol = dimC;
101
+ ax = _ax;
102
+ }
103
+ int dimRow;
104
+ int dimCol;
105
+ Dim ax;
106
+ };
107
+
108
+ std::vector<StStep> makePlan (std::vector<std::vector<bool >> sparseMatMap)
109
+ {
110
+ std::vector<StStep> ans;
111
+ std::vector<std::vector<bool >> visitedMap (sparseMatMap.size (), std::vector<bool >(sparseMatMap[0 ].size (), false ));
112
+ visitedMap[0 ][0 ] = true ;
113
+ for (int row = 0 ; row < sparseMatMap.size (); row++)
114
+ {
115
+ for (int col = 0 ; col < sparseMatMap[row].size (); col++)
116
+ {
117
+ if (sparseMatMap[row][col])
118
+ {
119
+ for (int c = 0 ; c <= col; c++)
120
+ {
121
+ if (!visitedMap[0 ][c])
122
+ {
123
+ visitedMap[0 ][c] = true ;
124
+ ans.emplace_back (0 , c - 1 , Dim::Col);
125
+ }
126
+ }
127
+ for (int r = 0 ; r <= row; r++)
128
+ {
129
+ if (!visitedMap[r][col])
130
+ {
131
+ visitedMap[r][col] = true ;
132
+ ans.emplace_back (r - 1 , col, Dim::Row);
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ return ans;
139
+ }
140
+
141
+ void MakeMinStMat (InputArray src, OutputArray dst, int rowStep, int colStep)
142
+ {
143
+ CV_Assert (rowStep * colStep == 0 ); // one of "rowStep" or "colStep" is required to be 0.
144
+
145
+ Mat src_ = src.getMat ();
146
+ Mat dst_ = dst.getMat ();
147
+ uchar* srcPtr1 = src_.ptr <uchar>(0 , 0 );
148
+ uchar* srcPtr2 = src_.ptr <uchar>(rowStep, colStep);
149
+ uchar* dstPtr = dst_.ptr <uchar>(0 , 0 );
150
+ for (int row = 0 ; row < src.rows () - rowStep; row++)
151
+ {
152
+ for (int col = 0 ; col < src.cols () - colStep; col++)
153
+ {
154
+ for (int c = 0 ; c < src.channels (); c++)
155
+ {
156
+ *dstPtr = min (*srcPtr1, *srcPtr2);
157
+ srcPtr1++;
158
+ srcPtr2++;
159
+ dstPtr++;
160
+ }
161
+ }
162
+ srcPtr1 += colStep * src.channels ();
163
+ srcPtr2 += colStep * src.channels ();
164
+ dstPtr += colStep * src.channels ();
165
+ }
166
+ }
167
+ void MakeMaxStMat (InputArray src, OutputArray dst, int rowStep, int colStep)
168
+ {
169
+ CV_Assert (rowStep * colStep == 0 ); // one of "rowStep" or "colStep" is required to be 0.
170
+
171
+ Mat src_ = src.getMat ();
172
+ Mat dst_ = dst.getMat ();
173
+ uchar* srcPtr1 = src_.ptr <uchar>(0 , 0 );
174
+ uchar* srcPtr2 = src_.ptr <uchar>(rowStep, colStep);
175
+ uchar* dstPtr = dst_.ptr <uchar>(0 , 0 );
176
+ for (int row = 0 ; row < src.rows (); row++)
177
+ {
178
+ for (int col = 0 ; col < src.cols (); col++)
179
+ {
180
+ *dstPtr = max (*srcPtr1, *srcPtr2);
181
+ }
182
+ }
183
+ }
184
+
56
185
void dilate (InputArray src, OutputArray dst, InputArray kernel,
57
186
Point anchor, int iterations,
58
187
int borderType, const Scalar& borderValue)
@@ -66,7 +195,6 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
66
195
// ---------------------------
67
196
// checking input
68
197
uchar ZERO = 255 ;
69
- // op = ...?
70
198
71
199
Mat src = _src.getMat ();
72
200
Mat dst = _dst.getMat ();
@@ -94,180 +222,82 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
94
222
Mat expandedSrc (src.rows + kernel.rows , src.cols + kernel.cols , src.type ());
95
223
cv::copyMakeBorder (src, expandedSrc, anchor.y , kernel.cols - 1 - anchor.y , anchor.x , kernel.rows - 1 - anchor.x , borderType, bV);
96
224
225
+ // generating a set of rectangles that covers whole kernel
226
+ std::vector<Rect> rects = GetCoveringRectangles (kernel);
227
+
97
228
// log2 table construction
98
229
int len = max (kernel.rows , kernel.cols ) + 1 ;
99
- int * lg = new int [len];
100
- lg[1 ] = 0 ;
230
+ std::vector<int > lg (len);
101
231
for (int i = 2 ; i < len; i++) lg[i] = lg[i >> 1 ] + 1 ;
102
232
103
- // generating a set of rectangles that covers whole kernel
104
- // todo: implement good algorithm
105
- int kCount = 0 ;
106
- int buffSize = kernel.rows * 2 ;
107
- Rect* rects = new Rect[buffSize];
108
- if (rects != NULL )
233
+ // 矩形を2冪矩形に分解 & 登場した2冪矩形の情報を位置と幅高さの指数で記録
234
+ std::vector<std::vector<bool >> sparseMatMap (lg[kernel.rows ] + 1 , std::vector<bool >(lg[kernel.cols ] + 1 , false ));
235
+ std::vector<Rect> powerOf2Rects;
236
+ for (int i = 0 ; i < rects.size (); i++)
109
237
{
110
- // bad implementation; just separating by line.
111
- for (int row = 0 ; row < kernel.rows ; row++)
112
- {
113
- uchar pre = 0 ;
114
- for (int col = 0 ; col < kernel.cols ; col++)
115
- {
116
- if (kernel.ptr (row)[col] == 0 )
117
- {
118
- if (pre == 1 )
119
- {
120
- rects[kCount ].width = col - rects[kCount ].x ;
121
- kCount ++;
122
- }
123
- }
124
- else
125
- {
126
- if (pre == 0 )
127
- {
128
- rects[kCount ].y = row;
129
- rects[kCount ].height = 1 ;
130
- rects[kCount ].x = col;
131
- }
132
- }
133
- pre = kernel.ptr (row)[col];
134
- }
135
- if (pre == 1 )
136
- {
137
- rects[kCount ].width = kernel.cols - rects[kCount ].x ;
138
- kCount ++;
139
- }
140
- }
141
- }
238
+ Rect rect = rects[i];
239
+ int lgCols = lg[rect.width ];
240
+ int lgRows = lg[rect.height ];
241
+ bool isColDivisionRequired = (1 << lgCols) < rect.width ;
242
+ bool isRowDivisionRequired = (1 << lgRows) < rect.height ;
142
243
143
- // calculate required mats in sparsetable
144
- // sparseTable[lnKcol][lnKrow] can be calculated from
145
- // sparseTable[lnKcol - 1][lnKrow] or sparseTable[lnKcol][lnKrow - 1].
146
- //
147
- // todo: implement better algorithm.
148
- Mat stRequiredMatMap (lg[kernel.rows ] + 1 , lg[kernel.cols ] + 1 , CV_8UC1);
149
- stRequiredMatMap.setTo (0 );
150
- for (int i = 0 ; i < kCount ; i++)
151
- {
152
- stRequiredMatMap.ptr (lg[rects[i].height ])[lg[rects[i].width ]] = 1 ;
153
- }
154
- #if 0
155
- cv::resize(stRequiredMatMap, stRequiredMatMap, cv::Size(), 10, 10, 0);
156
- imshow("debug", stRequiredMatMap);
157
- #endif
158
-
159
- // temporary implementation; only row separation is supported.
160
- int szColDepth = stRequiredMatMap.cols ;
161
- int szRowDepth = 1 ;
162
-
163
- int stSizes[] = { szRowDepth, szColDepth, expandedSrc.rows , expandedSrc.cols };
164
- Mat sparseTable (4 , stSizes, src.type (), Scalar (0 ));
165
-
166
- // sparse table construction
167
- uchar* ptr = sparseTable.ptr ();
168
- uchar* refPtr = expandedSrc.ptr ();
244
+ sparseMatMap[lgRows][lgCols] = true ;
169
245
170
- for (int row = 0 ; row < expandedSrc.rows ; row++)
171
- {
172
- for (int col = 0 ; col < expandedSrc.cols ; col++)
173
- {
174
- for (unsigned int c = 0 ; c < src.channels (); c++)
175
- {
176
- *ptr = *refPtr;
177
- ptr++;
178
- refPtr++;
179
- }
180
- }
246
+ powerOf2Rects.emplace_back (rect.x , rect.y , lgCols, lgRows);
247
+ if (isColDivisionRequired)
248
+ powerOf2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y , lgCols, lgRows);
249
+ if (isRowDivisionRequired)
250
+ powerOf2Rects.emplace_back (rect.x + rect.width , rect.y - (1 << lgRows), lgCols, lgRows);
251
+ if (isColDivisionRequired && isRowDivisionRequired)
252
+ powerOf2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y - (1 << lgRows), lgCols, lgRows);
181
253
}
182
- for (int lgColCnt = 1 ; lgColCnt < szColDepth; lgColCnt++)
183
- {
184
- int b = (1 << lgColCnt) - 1 ;
185
- int colROfs = sparseTable.step .p [3 ] * (1 << (lgColCnt - 1 ));
186
- int colSkipOfs = b * sparseTable.step .p [3 ];
187
254
188
- for (int row = 0 ; row < expandedSrc.rows ; row++)
189
- {
190
- for (int col = 0 ; col < expandedSrc.cols - b; col++)
191
- {
192
- for (unsigned int c = 0 ; c < src.channels (); c++)
193
- {
194
- uchar* l = ptr - sparseTable.step .p [1 ];
195
- uchar* r = l + colROfs;
196
- *ptr = min (*l, *r);
197
- ptr++;
198
- }
199
- }
200
- ptr += colSkipOfs;
201
- }
202
- }
203
- for (int lgRowCnt = 1 ; lgRowCnt < szRowDepth; lgRowCnt++)
255
+ // スパーステーブルの生成計画を立てる; planning how to calculate required mats in sparsetable
256
+ std::vector<StStep> stProcess = makePlan (sparseMatMap);
257
+
258
+ // スパーステーブルの生成
259
+ std::vector<std::vector<Mat*>> st = std::vector<std::vector<Mat*>>(lg[kernel.rows ] + 1 , std::vector<Mat*>(lg[kernel.cols ] + 1 ));
260
+ st[0 ][0 ] = &expandedSrc;
261
+ for (int i = 0 ; i < stProcess.size (); i++)
204
262
{
205
- int a = (1 << lgRowCnt) - 1 ;
206
- int rowROfs = sparseTable.step .p [2 ] * (1 << (lgRowCnt - 1 ));
207
- for (int lgColCnt = 0 ; lgColCnt < szColDepth; lgColCnt++)
263
+ StStep step = stProcess[i];
264
+ switch (step.ax )
208
265
{
209
- int b = (1 << lgColCnt) - 1 ;
210
- int colROfs = sparseTable.step .p [3 ] * (1 << (lgColCnt - 1 ));
211
- int colSkipOfs = b * sparseTable.step .p [3 ];
212
-
213
- for (int row = 0 ; row < expandedSrc.rows - a; row++)
214
- {
215
- for (int col = 0 ; col < expandedSrc.cols - b; col++)
216
- {
217
- for (unsigned int c = 0 ; c < src.channels (); c++)
218
- {
219
- uchar* l = ptr - sparseTable.step .p [0 ];
220
- uchar* r = l + rowROfs;
221
- *ptr = min (*l, *r);
222
- ptr++;
223
- }
224
- }
225
- ptr += colSkipOfs;
226
- }
227
- ptr += a * sparseTable.step .p [2 ];
266
+ case Dim::Col:
267
+ st[step.dimRow ][step.dimCol + 1 ] = new Mat (expandedSrc.rows , expandedSrc.cols , expandedSrc.type ());
268
+ MakeMinStMat (*st[step.dimRow ][step.dimCol ], *st[step.dimRow ][step.dimCol + 1 ], 0 , 1 << step.dimCol );
269
+ break ;
270
+ case Dim::Row:
271
+ st[step.dimRow + 1 ][step.dimCol ] = new Mat (expandedSrc.rows , expandedSrc.cols , expandedSrc.type ());
272
+ MakeMinStMat (*st[step.dimRow ][step.dimCol ], *st[step.dimRow + 1 ][step.dimCol ], 1 << step.dimRow , 0 );
273
+ break ;
228
274
}
229
275
}
230
276
231
- // result construction
232
- for (int i = 0 ; i < kCount ; i++)
277
+ // 結果構築
278
+ int aaa; // ???
279
+ for (int i = 0 ; i < powerOf2Rects.size (); i++)
233
280
{
234
- int lgRectRows = lg[rects[i].height ];
235
- int lgRectCols = lg[rects[i].width ];
236
- int ofsTB = (rects[i].height - (1 << lgRectRows)) * sparseTable.step .p [2 ];
237
- int ofsLR = (rects[i].width - (1 << lgRectCols)) * sparseTable.step .p [3 ];
238
- int sideBorderSkipStep = (kernel.cols - 1 ) * sparseTable.step .p [3 ];
239
- uchar* vLT = sparseTable.ptr ()
240
- + sparseTable.step .p [0 ] * lgRectRows
241
- + sparseTable.step .p [1 ] * lgRectCols
242
- + rects[i].y * sparseTable.step .p [2 ]
243
- + rects[i].x * sparseTable.step .p [3 ];
244
- uchar* vLB = vLT + ofsTB;
245
- uchar* vRT = vLT + ofsLR;
246
- uchar* vRB = vRT + ofsTB;
281
+ Rect rect = powerOf2Rects[i];
282
+ Mat* sparseMat = st[rect.height ][rect.width ];
283
+ uchar* srcPtr = sparseMat->ptr () + sparseMat->step .p [0 ] * rect.y + sparseMat->step .p [1 ] * rect.x ;
247
284
uchar* dstPtr = dst.ptr ();
285
+ int sideBorderSkipStep = (kernel.cols - 1 ) * sparseMat->step .p [1 ];
248
286
249
287
for (int row = 0 ; row < src.rows ; row++)
250
288
{
251
289
for (int col = 0 ; col < src.cols ; col++)
252
290
{
253
291
for (int c = 0 ; c < src.channels (); c++)
254
292
{
255
- *dstPtr = min (*dstPtr, min (min (*vLT, *vLB), min (*vRT, *vRB)));
256
- vLT++;
257
- vLB++;
258
- vRT++;
259
- vRB++;
293
+ *dstPtr = min (*dstPtr, *srcPtr);
294
+ srcPtr++;
260
295
dstPtr++;
261
296
}
262
297
}
263
- vLT += sideBorderSkipStep;
264
- vLB += sideBorderSkipStep;
265
- vRT += sideBorderSkipStep;
266
- vRB += sideBorderSkipStep;
298
+ srcPtr += sideBorderSkipStep;
267
299
}
268
300
}
269
- delete[] lg;
270
- delete[] rects;
271
301
}
272
302
273
303
void morphologyEx (InputArray _src, OutputArray _dst, int op,
0 commit comments