Skip to content

Commit 1acc393

Browse files
committed
dilateユニットテスト、実装追加
1 parent 9bf1663 commit 1acc393

File tree

2 files changed

+223
-25
lines changed

2 files changed

+223
-25
lines changed

modules/ximgproc/src/sparse_table_morphology.cpp

Lines changed: 157 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ std::vector<StStep> planSparseTableConstr(std::vector<std::vector<bool>> sparseM
180180
return plan;
181181
}
182182

183+
#pragma region Dilation
184+
183185
template <typename T>
184-
void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int colStep)
186+
void makeMaxSparseTableMat(InputArray src, OutputArray dst, int rowStep, int colStep)
185187
{
186188
CV_Assert(rowStep * colStep == 0); // one of "rowStep" or "colStep" is required to be 0.
187189

@@ -199,8 +201,8 @@ void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
199201
{
200202
for (int colCh = 0; colCh < colChLim; colCh++)
201203
{
202-
// Somehow std::min(a,b) or a<b?a:b are slower.
203-
if (*srcPtr1 < *srcPtr2)
204+
// Somehow std::max(a,b) or a>b?a:b are slower.
205+
if (*srcPtr1 > *srcPtr2)
204206
{
205207
*dstPtr++ = *srcPtr1++;
206208
srcPtr2++;
@@ -218,10 +220,157 @@ void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
218220
}
219221

220222
template <typename T>
221-
void makeMaxSparseTableMat(InputArray src, OutputArray dst, int rowStep, int colStep)
223+
void _dilate(InputArray _src, OutputArray _dst, InputArray _kernel,
224+
Point anchor, int iterations,
225+
int borderType, const Scalar& borderValue)
226+
{
227+
Mat kernel = _kernel.getMat();
228+
229+
// Generate list of rectangles whose width and height are power of 2.
230+
// (The width and height values of returned rects ​​are the log2 of the actual values.)
231+
std::vector<Rect> pow2Rects = genPow2RectsToCoverKernel(kernel);
232+
233+
// get the depth limits
234+
int rowDepthLim = 0, colDepthLim = 0;
235+
for (int i = 0; i < pow2Rects.size(); i++)
236+
{
237+
if (rowDepthLim < pow2Rects[i].height) rowDepthLim = pow2Rects[i].height;
238+
if (colDepthLim < pow2Rects[i].width) colDepthLim = pow2Rects[i].width;
239+
}
240+
rowDepthLim++;
241+
colDepthLim++;
242+
243+
// list up required sparse table nodes.
244+
std::vector<std::vector<bool>> sparseMatMap(rowDepthLim, std::vector<bool>(colDepthLim, false));
245+
for (int i = 0; i < pow2Rects.size(); i++)
246+
sparseMatMap[pow2Rects[i].height][pow2Rects[i].width] = true;
247+
248+
// plan how to calculate required nodes of 2D sparse table.
249+
std::vector<StStep> stPlan = planSparseTableConstr(sparseMatMap);
250+
251+
Mat src = _src.getMat();
252+
253+
do
254+
{
255+
// adding border to the source.
256+
Scalar bV = borderValue;
257+
if (borderType == BorderTypes::BORDER_CONSTANT
258+
&& borderValue == morphologyDefaultBorderValue())
259+
bV = Scalar::all(0);
260+
Mat expandedSrc(src.rows + kernel.rows, src.cols + kernel.cols, src.type());
261+
copyMakeBorder(src, expandedSrc,
262+
anchor.y, kernel.cols - 1 - anchor.y,
263+
anchor.x, kernel.rows - 1 - anchor.x,
264+
borderType, bV);
265+
266+
_dst.create(_src.size(), _src.type());
267+
Mat dst = _dst.getMat();
268+
269+
std::vector<std::vector<Mat>> st(rowDepthLim, std::vector<Mat>(colDepthLim));
270+
st[0][0] = expandedSrc;
271+
for (int i = 0; i < stPlan.size(); i++)
272+
{
273+
StStep step = stPlan[i];
274+
switch (step.ax)
275+
{
276+
case Dim::Col:
277+
makeMaxSparseTableMat<T>(st[step.dimRow][step.dimCol], st[step.dimRow][step.dimCol + 1],
278+
0, 1 << step.dimCol);
279+
break;
280+
case Dim::Row:
281+
makeMaxSparseTableMat<T>(st[step.dimRow][step.dimCol], st[step.dimRow + 1][step.dimCol],
282+
1 << step.dimRow, 0);
283+
break;
284+
}
285+
}
286+
287+
// result constructioin
288+
dst.setTo(0);
289+
int colChLim = dst.cols * dst.channels();
290+
for (int i = 0; i < pow2Rects.size(); i++)
291+
{
292+
Rect rect = pow2Rects[i];
293+
Mat sparseMat = st[rect.height][rect.width];
294+
int sideBorderSkipStep = (kernel.cols - 1) * sparseMat.channels();
295+
T* srcPtr = sparseMat.ptr<T>(rect.y, rect.x);
296+
T* dstPtr = dst.ptr<T>();
297+
for (int row = 0; row < dst.rows; row++)
298+
{
299+
for (int col = 0; col < colChLim; col++)
300+
{
301+
if (*srcPtr > *dstPtr) *dstPtr = *srcPtr;
302+
srcPtr++;
303+
dstPtr++;
304+
}
305+
srcPtr += sideBorderSkipStep;
306+
}
307+
}
308+
309+
src = dst;
310+
} while (--iterations > 0);
311+
}
312+
313+
void dilate(InputArray _src, OutputArray _dst, InputArray _kernel,
314+
Point anchor, int iterations,
315+
int borderType, const Scalar& borderValue)
316+
{
317+
Mat kernel = _kernel.getMat();
318+
if (iterations == 0 || kernel.rows * kernel.cols == 1)
319+
{
320+
_src.copyTo(_dst);
321+
return;
322+
}
323+
// Fix kernel in case of it is empty.
324+
if (kernel.empty())
325+
{
326+
kernel = getStructuringElement(MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2));
327+
anchor = Point(iterations, iterations);
328+
iterations = 1;
329+
}
330+
if (countNonZero(kernel) == 0)
331+
{
332+
kernel.at<uchar>(0, 0) = 1;
333+
}
334+
// Fix anchor to the center of the kernel.
335+
anchor = stMorph::normalizeAnchor(anchor, kernel.size());
336+
337+
// dilate operation
338+
switch (_src.depth())
339+
{
340+
case CV_8U:
341+
_dilate<uchar>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
342+
return;
343+
case CV_8S:
344+
_dilate<char>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
345+
return;
346+
case CV_16U:
347+
_dilate<ushort>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
348+
return;
349+
case CV_16S:
350+
_dilate<short>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
351+
return;
352+
case CV_32S:
353+
_dilate<int>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
354+
return;
355+
case CV_32F:
356+
_dilate<float>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
357+
return;
358+
case CV_64F:
359+
_dilate<double>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
360+
return;
361+
}
362+
}
363+
364+
#pragma endregion
365+
366+
#pragma region Erosion
367+
368+
template <typename T>
369+
void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int colStep)
222370
{
223371
CV_Assert(rowStep * colStep == 0); // one of "rowStep" or "colStep" is required to be 0.
224372

373+
dst.create(src.size(), src.type());
225374
Mat src_ = src.getMat();
226375
Mat dst_ = dst.getMat();
227376
int rowLim = src.rows() - rowStep;
@@ -235,7 +384,8 @@ void makeMaxSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
235384
{
236385
for (int colCh = 0; colCh < colChLim; colCh++)
237386
{
238-
if (*srcPtr1 > *srcPtr2)
387+
// Somehow std::min(a,b) or a<b?a:b are slower.
388+
if (*srcPtr1 < *srcPtr2)
239389
{
240390
*dstPtr++ = *srcPtr1++;
241391
srcPtr2++;
@@ -343,12 +493,6 @@ void _erode(InputArray _src, OutputArray _dst, InputArray _kernel,
343493
} while (--iterations > 0);
344494
}
345495

346-
void dilate(InputArray src, OutputArray dst, InputArray kernel,
347-
Point anchor, int iterations,
348-
int borderType, const Scalar& borderValue)
349-
{
350-
}
351-
352496
void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
353497
Point anchor, int iterations,
354498
int borderType, const Scalar& borderValue)
@@ -400,6 +544,8 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
400544
}
401545
}
402546

547+
#pragma endregion
548+
403549
void morphologyEx(InputArray _src, OutputArray _dst, int op,
404550
InputArray _kernel, Point anchor, int iterations,
405551
int borderType, const Scalar& borderValue)

modules/ximgproc/test/test_sparse_table_morphology.cpp

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,67 @@ Mat knAsymm (){
195195
return (Mat_<uchar>(5, 5) << 0,0,0,0,0, 0,0,1,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,1,0,0);
196196
}
197197

198+
#pragma region dilasion
199+
200+
/*
201+
* dilate regression tests.
202+
*/
203+
void dilate_rgr(InputArray src, InputArray kernel, Point anchor = Point(-1, -1),
204+
int iterations = 1,
205+
BorderTypes bdrType = BorderTypes::BORDER_CONSTANT, Scalar& bdrVal = Scalar::all(DBL_MAX))
206+
{
207+
Mat expected, actual;
208+
dilate(src, expected, kernel, anchor, iterations, bdrType, bdrVal);
209+
stMorph::dilate(src, actual, kernel, anchor, iterations, bdrType, bdrVal);
210+
assertArraysIdentical(expected, actual);
211+
}
212+
TEST(ximgproc_StMorph_dilate, regression_8UC1) { dilate_rgr(im(CV_8UC1), kn5()); }
213+
TEST(ximgproc_StMorph_dilate, regression_8UC3) { dilate_rgr(im(CV_8UC3), kn5()); }
214+
TEST(ximgproc_StMorph_dilate, regression_16UC1) { dilate_rgr(im(CV_16UC1), kn5()); }
215+
TEST(ximgproc_StMorph_dilate, regression_16UC3) { dilate_rgr(im(CV_16UC3), kn5()); }
216+
TEST(ximgproc_StMorph_dilate, regression_16SC1) { dilate_rgr(im(CV_16SC1), kn5()); }
217+
TEST(ximgproc_StMorph_dilate, regression_16SC3) { dilate_rgr(im(CV_16SC3), kn5()); }
218+
TEST(ximgproc_StMorph_dilate, regression_32FC1) { dilate_rgr(im(CV_32FC1), kn5()); }
219+
TEST(ximgproc_StMorph_dilate, regression_32FC3) { dilate_rgr(im(CV_32FC3), kn5()); }
220+
TEST(ximgproc_StMorph_dilate, regression_64FC1) { dilate_rgr(im(CV_64FC1), kn5()); }
221+
TEST(ximgproc_StMorph_dilate, regression_64FC3) { dilate_rgr(im(CV_64FC3), kn5()); }
222+
TEST(ximgproc_StMorph_dilate, regression_kn5) { dilate_rgr(im(CV_8UC3), kn5()); }
223+
TEST(ximgproc_StMorph_dilate, regression_kn4) { dilate_rgr(im(CV_8UC3), kn4()); }
224+
TEST(ximgproc_StMorph_dilate, wtf_regression_kn1Zero) { dilate_rgr(im(CV_8UC3), kn1Zero()); }
225+
TEST(ximgproc_StMorph_dilate, regression_kn1One) { dilate_rgr(im(CV_8UC3), kn1One()); }
226+
TEST(ximgproc_StMorph_dilate, wtf_regression_knEmpty) { dilate_rgr(im(CV_8UC3), knEmpty()); }
227+
TEST(ximgproc_StMorph_dilate, wtf_regression_knZeros) { dilate_rgr(im(CV_8UC3), knZeros()); }
228+
TEST(ximgproc_StMorph_dilate, regression_knOnes) { dilate_rgr(im(CV_8UC3), knOnes()); }
229+
TEST(ximgproc_StMorph_dilate, regression_knBig) { dilate_rgr(im(CV_8UC3), knBig()); }
230+
TEST(ximgproc_StMorph_dilate, regression_knAsymm) { dilate_rgr(im(CV_8UC3), knAsymm()); }
231+
TEST(ximgproc_StMorph_dilate, regression_ancMid) { dilate_rgr(im(CV_8UC3), kn5(), Point(-1, -1)); }
232+
TEST(ximgproc_StMorph_dilate, regression_ancEdge1) { dilate_rgr(im(CV_8UC3), kn5(), Point(0, 0)); }
233+
TEST(ximgproc_StMorph_dilate, regression_ancEdge2) { dilate_rgr(im(CV_8UC3), kn5(), Point(4, 4)); }
234+
TEST(ximgproc_StMorph_dilate, wtf_regression_it0) { dilate_rgr(im(CV_8UC3), kn5(), Point(-1, -1), 0); }
235+
TEST(ximgproc_StMorph_dilate, regression_it1) { dilate_rgr(im(CV_8UC3), kn5(), Point(-1, -1), 1); }
236+
TEST(ximgproc_StMorph_dilate, regression_it2) { dilate_rgr(im(CV_8UC3), kn5(), Point(-1, -1), 2); }
237+
/*
238+
* dilate feature tests.
239+
*/
240+
void dilate_ftr(InputArray src, InputArray kernel, Point anchor = Point(-1, -1),
241+
int iterations = 1,
242+
BorderTypes bdrType = BorderTypes::BORDER_CONSTANT, Scalar& bdrVal = Scalar::all(DBL_MAX))
243+
{
244+
Mat expected, actual;
245+
stMorph::dilate(src, actual, kernel, anchor, iterations, bdrType, bdrVal);
246+
// todo: generate expected result.
247+
// assertArraysIdentical(expected, actual);
248+
}
249+
/* CV_8S, CV_16F are not supported by morph.simd::getMorphologyFilter */
250+
TEST(ximgproc_StMorph_dilate, feature_8SC1) { dilate_ftr(im(CV_8SC1), kn5()); }
251+
TEST(ximgproc_StMorph_dilate, feature_8SC3) { dilate_ftr(im(CV_8SC3), kn5()); }
252+
TEST(ximgproc_StMorph_dilate, feature_32SC1) { dilate_ftr(im(CV_32SC1), kn5()); }
253+
TEST(ximgproc_StMorph_dilate, feature_32SC3) { dilate_ftr(im(CV_32SC3), kn5()); }
254+
255+
#pragma endregion
256+
257+
#pragma region erosion
258+
198259
/*
199260
* erode regression tests.
200261
*/
@@ -250,20 +311,9 @@ TEST(ximgproc_StMorph_erode, feature_8SC3) { erode_ftr(im(CV_8SC3), kn5()); }
250311
TEST(ximgproc_StMorph_erode, feature_32SC1) { erode_ftr(im(CV_32SC1), kn5()); }
251312
TEST(ximgproc_StMorph_erode, feature_32SC3) { erode_ftr(im(CV_32SC3), kn5()); }
252313

253-
/*
254-
* dilate regression tests.
255-
*/
256-
void dilate_rgr(InputArray src, InputArray kernel, Point anchor = Point(-1, -1),
257-
int iterations = 1,
258-
BorderTypes bdrType = BorderTypes::BORDER_CONSTANT, Scalar& bdrVal = Scalar::all(DBL_MAX))
259-
{
260-
Mat expected, actual;
261-
dilate(src, expected, kernel, anchor, iterations, bdrType, bdrVal);
262-
stMorph::dilate(src, actual, kernel, anchor, iterations, bdrType, bdrVal);
263-
assertArraysIdentical(expected, actual);
264-
}
265-
TEST(ximgproc_StMorph_dilate, regression_8UC3) { dilate_rgr(im(CV_8UC3), kn5()); }
266-
TEST(ximgproc_StMorph_dilate, regression_8UC1) { dilate_rgr(im(CV_8UC1), kn5()); }
314+
#pragma endregion
315+
316+
#pragma region morphologyEx
267317

268318
/*
269319
* morphologyEx regression tests.
@@ -286,4 +336,6 @@ TEST(ximgproc_StMorph_ex, regression_tophat) { ex_rgr(im(CV_8UC3), MORPH_TOPHAT,
286336
TEST(ximgproc_StMorph_ex, regression_blackhat) { ex_rgr(im(CV_8UC3), MORPH_BLACKHAT, kn5()); }
287337
TEST(ximgproc_StMorph_ex, regression_hitmiss) { ex_rgr(im(CV_8UC3), MORPH_HITMISS, kn5()); }
288338

339+
#pragma endregion
340+
289341
}} // ::opencv_test::

0 commit comments

Comments
 (0)