@@ -74,26 +74,37 @@ struct StStep
74
74
};
75
75
76
76
/*
77
- * Find a set of rectangles which coveres the kernel.
78
- *
79
- * The exact problem is defined and a not-optimal solution is proposed.
80
- * https://stackoverflow.com/questions/22769490/finding-the-smallest-set-of-rectangles-that-covers-the-given-rectilinear-simple
81
- *
82
- * Similer problem and a link to a paper.
83
- * https://stackoverflow.com/questions/31150398/maximal-rectangle-set-cover
84
- *
85
- * The paper. Names the problem "MISR".
86
- * https://home.ttic.edu/~cjulia/papers/rectangles-SODA.pdf ... x-approximation?
87
- * https://home.ttic.edu/~cjulia/papers/MISR.pdf ... (1-e)-approximation?
88
- *
77
+ * Find a smaller set of power-of-2 rectangles to cover the kernel.
78
+ * - The width and the height of each rectangles are power of 2.
79
+ * - Overlappings of rectangles are allowed.
89
80
*/
90
- static std::vector<Rect> getCoveringRectangles (InputArray _kernel)
81
+ static std::vector<Rect> genPow2RectsToCoverKernel (InputArray _kernel)
91
82
{
92
83
std::vector<Rect> rects;
93
84
Mat kernel = _kernel.getMat ();
94
85
int kCount = 0 ;
95
86
96
- // 行ごとで四角を作るだけの実装
87
+ // log2 table construction
88
+ int len = max (kernel.rows , kernel.cols ) + 1 ;
89
+ std::vector<int > log2 (len);
90
+ for (int i = 2 ; i < len; i++) log2[i] = log2[i >> 1 ] + 1 ;
91
+
92
+ // Development note.
93
+ // the strategy atm is to separate the kernel with arbitaly rectangles and then place po2Rects on each corners.
94
+ //
95
+ // Find a set of rectangles which coveres the kernel.
96
+ //
97
+ // The exact problem is defined and a not-optimal solution is proposed.
98
+ // https://stackoverflow.com/questions/22769490/finding-the-smallest-set-of-rectangles-that-covers-the-given-rectilinear-simple
99
+ //
100
+ // Similer problem and a link to a paper.
101
+ // https://stackoverflow.com/questions/31150398/maximal-rectangle-set-cover
102
+ //
103
+ // The paper. Names the problem "MISR".
104
+ // https://home.ttic.edu/~cjulia/papers/rectangles-SODA.pdf ... x-approximation?
105
+ // https://home.ttic.edu/~cjulia/papers/MISR.pdf ... (1-e)-approximation?
106
+ //
107
+
97
108
for (int row = 0 ; row < kernel.rows ; row++)
98
109
{
99
110
uchar pre = 0 ;
@@ -116,7 +127,25 @@ static std::vector<Rect> getCoveringRectangles(InputArray _kernel)
116
127
kCount ++;
117
128
}
118
129
}
119
- return rects;
130
+
131
+ std::vector<Rect> pow2Rects;
132
+ for (int i = 0 ; i < rects.size (); i++)
133
+ {
134
+ Rect rect = rects[i];
135
+ int lgCols = log2[rect.width ];
136
+ int lgRows = log2[rect.height ];
137
+ bool isColDivisionRequired = (1 << lgCols) < rect.width ;
138
+ bool isRowDivisionRequired = (1 << lgRows) < rect.height ;
139
+
140
+ pow2Rects.emplace_back (rect.x , rect.y , lgCols, lgRows);
141
+ if (isColDivisionRequired)
142
+ pow2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y , lgCols, lgRows);
143
+ if (isRowDivisionRequired)
144
+ pow2Rects.emplace_back (rect.x + rect.width , rect.y - (1 << lgRows), lgCols, lgRows);
145
+ if (isColDivisionRequired && isRowDivisionRequired)
146
+ pow2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y - (1 << lgRows), lgCols, lgRows);
147
+ }
148
+ return pow2Rects;
120
149
}
121
150
122
151
/*
@@ -270,41 +299,24 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
270
299
Mat expandedSrc (src.rows + kernel.rows , src.cols + kernel.cols , src.type ());
271
300
cv::copyMakeBorder (src, expandedSrc, anchor.y , kernel.cols - 1 - anchor.y , anchor.x , kernel.rows - 1 - anchor.x , borderType, bV);
272
301
273
- // generating a set of rectangles that covers whole kernel
274
- std::vector<Rect> rects = getCoveringRectangles (kernel);
275
-
276
302
// log2 table construction
277
303
int len = max (kernel.rows , kernel.cols ) + 1 ;
278
- std::vector<int > lg (len);
279
- for (int i = 2 ; i < len; i++) lg [i] = lg [i >> 1 ] + 1 ;
304
+ std::vector<int > log2 (len);
305
+ for (int i = 2 ; i < len; i++) log2 [i] = log2 [i >> 1 ] + 1 ;
280
306
281
- // 矩形を2冪矩形に分解 & 登場した2冪矩形の情報を位置と幅高さの指数で記録
282
- std::vector<std::vector<bool >> sparseMatMap (lg[kernel.rows ] + 1 , std::vector<bool >(lg[kernel.cols ] + 1 , false ));
283
- std::vector<Rect> powerOf2Rects;
284
- for (int i = 0 ; i < rects.size (); i++)
285
- {
286
- Rect rect = rects[i];
287
- int lgCols = lg[rect.width ];
288
- int lgRows = lg[rect.height ];
289
- bool isColDivisionRequired = (1 << lgCols) < rect.width ;
290
- bool isRowDivisionRequired = (1 << lgRows) < rect.height ;
307
+ // カーネルから幅と高さが2のべき乗の長方形リストを生成する
308
+ // - リストの width と height は log2 をとった値
309
+ std::vector<Rect> pow2Rects = genPow2RectsToCoverKernel (kernel);
291
310
292
- sparseMatMap[lgRows][lgCols] = true ;
293
-
294
- powerOf2Rects.emplace_back (rect.x , rect.y , lgCols, lgRows);
295
- if (isColDivisionRequired)
296
- powerOf2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y , lgCols, lgRows);
297
- if (isRowDivisionRequired)
298
- powerOf2Rects.emplace_back (rect.x + rect.width , rect.y - (1 << lgRows), lgCols, lgRows);
299
- if (isColDivisionRequired && isRowDivisionRequired)
300
- powerOf2Rects.emplace_back (rect.x + rect.width - (1 << lgCols), rect.y - (1 << lgRows), lgCols, lgRows);
301
- }
311
+ // 幅と高さが2のべき乗の長方形リストを幅と高さごとに集計
312
+ std::vector<std::vector<bool >> sparseMatMap (log2[kernel.rows ] + 1 , std::vector<bool >(log2[kernel.cols ] + 1 , false ));
313
+ for (int i = 0 ; i < pow2Rects.size (); i++) sparseMatMap[pow2Rects[i].height ][pow2Rects[i].width ] = true ;
302
314
303
- // スパーステーブルの生成計画を立てる; planning how to calculate required mats in sparsetable
315
+ // スパーステーブルの生成計画を立てる; planning how to calculate required mats in sparse table
304
316
std::vector<StStep> stProcess = makePlan (sparseMatMap);
305
317
306
- // スパーステーブルの生成
307
- std::vector<std::vector<Mat*>> st = std::vector<std::vector<Mat*>>(lg [kernel.rows ] + 1 , std::vector<Mat*>(lg [kernel.cols ] + 1 ));
318
+ // スパーステーブルの生成; generate sparse table
319
+ std::vector<std::vector<Mat*>> st = std::vector<std::vector<Mat*>>(log2 [kernel.rows ] + 1 , std::vector<Mat*>(log2 [kernel.cols ] + 1 ));
308
320
st[0 ][0 ] = &expandedSrc;
309
321
for (int i = 0 ; i < stProcess.size (); i++)
310
322
{
@@ -322,10 +334,10 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
322
334
}
323
335
}
324
336
325
- // 結果構築
326
- for (int i = 0 ; i < powerOf2Rects .size (); i++)
337
+ // 結果構築; construct the result
338
+ for (int i = 0 ; i < pow2Rects .size (); i++)
327
339
{
328
- Rect rect = powerOf2Rects [i];
340
+ Rect rect = pow2Rects [i];
329
341
Mat sparseMat = *st[rect.height ][rect.width ];
330
342
int sideBorderSkipStep = (kernel.cols - 1 ) * sparseMat.step .p [1 ];
331
343
int colChLim = src.cols * src.channels ();
0 commit comments