4
4
5
5
#include " precomp.hpp"
6
6
#include < limits>
7
- #include < vector>
8
7
#include < utility>
8
+ #include < vector>
9
9
10
10
namespace cv {
11
11
namespace stMorph {
@@ -93,8 +93,6 @@ std::vector<Point> findSeeds(const Mat& stNode, int rowDepth, int colDepth)
93
93
return p2Rects;
94
94
}
95
95
96
- // Generate list of rectangles whose width and height are power of 2.
97
- // (The width and height values of returned rects are the log2 of the actual values.)
98
96
std::vector<std::vector<std::vector<Point>>> genPow2RectsToCoverKernel (
99
97
const Mat& kernel, int rowDepthLim, int colDepthLim)
100
98
{
@@ -127,85 +125,107 @@ std::vector<std::vector<std::vector<Point>>> genPow2RectsToCoverKernel(
127
125
return p2Rects;
128
126
}
129
127
130
- std::vector<StStep> planSparseTableConstr (
131
- std::vector<std::vector<std::vector<Point>>> pow2Rects, int rowDepthLim, int colDepthLim,
132
- StStrategy strategy)
128
+ Mat SolveRSAPGreedy (const Mat& initialMap)
133
129
{
134
- // list up required sparse table nodes.
135
- std::vector<std::vector<bool >> sparseMatMap (rowDepthLim, std::vector<bool >(colDepthLim, false ));
136
- for (int r = 0 ; r < pow2Rects.size (); r++)
137
- {
138
- for (int c = 0 ; c < pow2Rects[r].size (); c++)
139
- {
140
- if (pow2Rects[r][c].size () > 0 ) sparseMatMap[r][c] = true ;
141
- }
142
- }
143
- sparseMatMap[0 ][0 ] = true ;
144
-
145
- switch (strategy)
146
- {
147
- case Faster:
130
+ /*
131
+ * Solves the rectilinear steiner arborescence problem
132
+ * https://link.springer.com/article/10.1007/BF01758762
133
+ */
134
+ CV_Assert (initialMap.type () == CV_8UC1);
135
+ std::vector<Point> pos;
136
+ for (int r = 0 ; r < initialMap.rows ; r++)
137
+ for (int c = 0 ; c < initialMap.cols ; c++)
138
+ if (initialMap.at <uchar>(r, c) == 1 ) pos.emplace_back (c, r);
139
+ Mat resMap = Mat::zeros (initialMap.size (), CV_8UC2);
140
+
141
+ while (pos.size () > 1 )
148
142
{
149
- /*
150
- *
151
- * AtCoder: https://atcoder.jp/contests/ahc037/tasks/ahc037_a
152
- *
153
- * The rectilinear steiner arborescence problem
154
- * https://link.springer.com/article/10.1007/BF01758762
155
- *
156
- */
157
- std::vector<Point> pos;
158
- for (int r = 0 ; r < sparseMatMap.size (); r++)
159
- for (int c = 0 ; c < sparseMatMap[r].size (); c++)
160
- if (sparseMatMap[r][c]) pos.emplace_back (c, r);
161
- std::vector<StStep> plan;
162
- while (pos.size () > 1 )
143
+ int maxCost = -1 ;
144
+ int maxI = 0 ;
145
+ int maxJ = 0 ;
146
+ int maxX = 0 ;
147
+ int maxY = 0 ;
148
+ for (int i = 0 ; i < pos.size (); i++)
163
149
{
164
- int maxCost = -1 ;
165
- int maxI = 0 ;
166
- int maxJ = 0 ;
167
- int maxX = 0 ;
168
- int maxY = 0 ;
169
- for (int i = 0 ; i < pos.size (); i++)
150
+ for (int j = i + 1 ; j < pos.size (); j++)
170
151
{
171
- for (int j = i + 1 ; j < pos.size (); j++)
152
+ int _x = std::min (pos[i].x , pos[j].x );
153
+ int _y = std::min (pos[i].y , pos[j].y );
154
+ int cost = _x + _y;
155
+ if (maxCost < cost)
172
156
{
173
- int _x = std::min (pos[i].x , pos[j].x );
174
- int _y = std::min (pos[i].y , pos[j].y );
175
- int cost = _x + _y;
176
- if (maxCost < cost)
177
- {
178
- maxCost = cost;
179
- maxI = i;
180
- maxJ = j;
181
- maxX = _x;
182
- maxY = _y;
183
- }
157
+ maxCost = cost;
158
+ maxI = i;
159
+ maxJ = j;
160
+ maxX = _x;
161
+ maxY = _y;
184
162
}
185
163
}
186
- for (int col = pos[maxI].x - 1 ; col >= maxX; col--)
187
- plan.emplace_back (Fill, pos[maxI].y , col, Dim::Col, pow2Rects[pos[maxI].y ][col]);
188
- for (int row = pos[maxI].y - 1 ; row >= maxY; row--)
189
- plan.emplace_back (Fill, row, maxX, Dim::Row, pow2Rects[row][maxX]);
190
- for (int col = pos[maxJ].x - 1 ; col >= maxX; col--)
191
- plan.emplace_back (Fill, pos[maxJ].y , col, Dim::Col, pow2Rects[pos[maxJ].y ][col]);
192
- for (int row = pos[maxJ].y - 1 ; row >= maxY; row--)
193
- plan.emplace_back (Fill, row, maxX, Dim::Row, pow2Rects[row][maxX]);
194
-
195
- pos[maxI] = Point (maxX, maxY);
196
- swap (pos[maxJ], pos[pos.size () - 1 ]);
197
- pos.pop_back ();
198
164
}
165
+ for (int col = pos[maxI].x - 1 ; col >= maxX; col--)
166
+ resMap.at <Vec2b>(pos[maxI].y , col)[1 ] = 1 ;
167
+ for (int row = pos[maxI].y - 1 ; row >= maxY; row--)
168
+ resMap.at <Vec2b>(row, maxX)[0 ] = 1 ;
169
+ for (int col = pos[maxJ].x - 1 ; col >= maxX; col--)
170
+ resMap.at <Vec2b>(pos[maxJ].y , col)[1 ] = 1 ;
171
+ for (int row = pos[maxJ].y - 1 ; row >= maxY; row--)
172
+ resMap.at <Vec2b>(row, maxX)[0 ] = 1 ;
173
+
174
+ pos[maxI] = Point (maxX, maxY);
175
+ swap (pos[maxJ], pos[pos.size () - 1 ]);
176
+ pos.pop_back ();
177
+ }
178
+ return resMap;
179
+ }
199
180
200
- reverse (plan.begin (), plan.end ());
201
- return plan;
181
+ Mat planSparseTableConstr (
182
+ std::vector<std::vector<std::vector<Point>>> pow2Rects, int rowDepthLim, int colDepthLim)
183
+ {
184
+ // list up required sparse table nodes.
185
+ Mat stMap = Mat::zeros (rowDepthLim, colDepthLim, CV_8UC1);
186
+ for (int rd = 0 ; rd < rowDepthLim; rd++)
187
+ for (int cd = 0 ; cd < colDepthLim; cd++)
188
+ if (pow2Rects[rd][cd].size () > 0 )
189
+ stMap.at <uchar>(rd, cd) = 1 ;
190
+ stMap.at <uchar>(0 , 0 ) = 1 ;
191
+ Mat path = SolveRSAPGreedy (stMap);
192
+ return path;
193
+ }
194
+
195
+ void morphDfs (int minmax, Mat& st, Mat& dst,
196
+ std::vector<std::vector<std::vector<Point>>> row2Rects, const Mat& stPlan,
197
+ int rowDepth, int colDepth)
198
+ {
199
+ for (Point p : row2Rects[rowDepth][colDepth])
200
+ {
201
+ Rect rect (p, dst.size ());
202
+ if (minmax == Op::Min) cv::min (dst, st (rect), dst);
203
+ else cv::max (dst, st (rect), dst);
202
204
}
203
- case StStrategy::SaveMemory:
205
+
206
+ // Fill col-direction first.
207
+ if (stPlan.at <Vec2b>(rowDepth, colDepth)[1 ] == 1 )
204
208
{
205
- // todo: implement.
206
- std::vector<StStep> plan;
207
- return plan;
209
+ // col direction
210
+ Mat st2 = st;
211
+ int ofs = 1 << colDepth;
212
+ Rect rect1 (0 , 0 , st2.cols - ofs, st2.rows );
213
+ Rect rect2 (ofs, 0 , st2.cols - ofs, st2.rows );
214
+
215
+ if (minmax == Op::Min) cv::min (st2 (rect1), st2 (rect2), st2);
216
+ else cv::max (st2 (rect1), st2 (rect2), st2);
217
+ morphDfs (minmax, st2, dst, row2Rects, stPlan, rowDepth, colDepth + 1 );
208
218
}
219
+ if (stPlan.at <Vec2b>(rowDepth, colDepth)[0 ] == 1 )
220
+ {
221
+ // row direction
222
+ int ofs = 1 << rowDepth;
223
+ Rect rect1 (0 , 0 , st.cols , st.rows - ofs);
224
+ Rect rect2 (0 , ofs, st.cols , st.rows - ofs);
225
+
226
+ if (minmax == Op::Min) cv::min (st (rect1), st (rect2), st);
227
+ else cv::max (st (rect1), st (rect2), st);
228
+ morphDfs (minmax, st, dst, row2Rects, stPlan, rowDepth + 1 , colDepth);
209
229
}
210
230
}
211
231
@@ -221,8 +241,8 @@ void morphOp(Op minmax, InputArray _src, OutputArray _dst, InputArray kernel,
221
241
int colDepthLim = log2 (longestColRunLength (_kernel)) + 1 ;
222
242
std::vector<std::vector<std::vector<Point>>> pow2Rects
223
243
= genPow2RectsToCoverKernel (_kernel, rowDepthLim, colDepthLim);
224
- std::vector<StStep> stPlan
225
- = planSparseTableConstr (pow2Rects, rowDepthLim, colDepthLim, Faster );
244
+ Mat stPlan
245
+ = planSparseTableConstr (pow2Rects, rowDepthLim, colDepthLim);
226
246
227
247
Mat src = _src.getMat ();
228
248
_dst.create (_src.size (), _src.type ());
@@ -239,53 +259,8 @@ void morphOp(Op minmax, InputArray _src, OutputArray _dst, InputArray kernel,
239
259
anchor.y , _kernel.cols - 1 - anchor.y ,
240
260
anchor.x , _kernel.rows - 1 - anchor.x ,
241
261
borderType, bV);
242
-
243
262
dst.setTo (nil);
244
-
245
- // TODO: keep only needed memories.
246
- std::vector<std::vector<Mat>> st (rowDepthLim, std::vector<Mat>(colDepthLim));
247
- st[0 ][0 ] = expandedSrc;
248
- for (int i = 0 ; i < stPlan.size (); i++)
249
- {
250
- StStep step = stPlan[i];
251
- Mat& curr = st[step.dimRow ][step.dimCol ];
252
- Mat* dst1;
253
- int ofsX = 0 , ofsY = 0 ;
254
- if (step.ax == Dim::Col)
255
- {
256
- ofsX = 1 << step.dimCol ;
257
- dst1 = &st[step.dimRow ][step.dimCol + 1 ];
258
- }
259
- else
260
- {
261
- ofsY = 1 << step.dimRow ;
262
- dst1 = &st[step.dimRow + 1 ][step.dimCol ];
263
- }
264
- int width = curr.cols - ofsX;
265
- int height = curr.rows - ofsY;
266
- Mat& src1 = st[step.dimRow ][step.dimCol ](Rect (0 , 0 , width, height));
267
- Mat& src2 = st[step.dimRow ][step.dimCol ](Rect (ofsX, ofsY, width, height));
268
- dst1->create (height, width, curr.type ());
269
- if (minmax == Op::Min) cv::min (src1, src2, *dst1);
270
- else cv::max (src1, src2, *dst1);
271
- }
272
-
273
- // result constructioin
274
- for (int r = 0 ; r < pow2Rects.size (); r++)
275
- {
276
- for (int c = 0 ; c < pow2Rects[r].size (); c++)
277
- {
278
- for (Point p : pow2Rects[r][c])
279
- {
280
- Rect rect (p, Size (1 << c, 1 << r));
281
- Rect srcRect (p, dst.size ());
282
- Mat& srcMat = st[r][c](srcRect);
283
- if (minmax == Op::Min) cv::min (dst, srcMat, dst);
284
- else cv::max (dst, srcMat, dst);
285
- }
286
- }
287
- }
288
-
263
+ morphDfs (minmax, expandedSrc, dst, pow2Rects, stPlan, 0 , 0 );
289
264
src = dst;
290
265
} while (--iterations > 0 );
291
266
}
0 commit comments