Skip to content

Commit 048f0db

Browse files
committed
カーネルの2べき長方形被覆をメソッドに分離、変数名リファクタ
1 parent c35d1cd commit 048f0db

File tree

1 file changed

+58
-46
lines changed

1 file changed

+58
-46
lines changed

modules/ximgproc/src/sparse_table_morphology.cpp

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,37 @@ struct StStep
7474
};
7575

7676
/*
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.
8980
*/
90-
static std::vector<Rect> getCoveringRectangles(InputArray _kernel)
81+
static std::vector<Rect> genPow2RectsToCoverKernel(InputArray _kernel)
9182
{
9283
std::vector<Rect> rects;
9384
Mat kernel = _kernel.getMat();
9485
int kCount = 0;
9586

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+
97108
for (int row = 0; row < kernel.rows; row++)
98109
{
99110
uchar pre = 0;
@@ -116,7 +127,25 @@ static std::vector<Rect> getCoveringRectangles(InputArray _kernel)
116127
kCount++;
117128
}
118129
}
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;
120149
}
121150

122151
/*
@@ -270,41 +299,24 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
270299
Mat expandedSrc(src.rows + kernel.rows, src.cols + kernel.cols, src.type());
271300
cv::copyMakeBorder(src, expandedSrc, anchor.y, kernel.cols - 1 - anchor.y, anchor.x, kernel.rows - 1 - anchor.x, borderType, bV);
272301

273-
// generating a set of rectangles that covers whole kernel
274-
std::vector<Rect> rects = getCoveringRectangles(kernel);
275-
276302
// log2 table construction
277303
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;
280306

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);
291310

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;
302314

303-
// スパーステーブルの生成計画を立てる; planning how to calculate required mats in sparsetable
315+
// スパーステーブルの生成計画を立てる; planning how to calculate required mats in sparse table
304316
std::vector<StStep> stProcess = makePlan(sparseMatMap);
305317

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));
308320
st[0][0] = &expandedSrc;
309321
for (int i = 0; i < stProcess.size(); i++)
310322
{
@@ -322,10 +334,10 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
322334
}
323335
}
324336

325-
// 結果構築
326-
for (int i = 0; i < powerOf2Rects.size(); i++)
337+
// 結果構築; construct the result
338+
for (int i = 0; i < pow2Rects.size(); i++)
327339
{
328-
Rect rect = powerOf2Rects[i];
340+
Rect rect = pow2Rects[i];
329341
Mat sparseMat = *st[rect.height][rect.width];
330342
int sideBorderSkipStep = (kernel.cols - 1) * sparseMat.step.p[1];
331343
int colChLim = src.cols * src.channels();

0 commit comments

Comments
 (0)