/******************************************************* * Copyright (c) 2014, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. * The complete license agreement can be obtained at: * http://arrayfire.com/licenses/BSD-3-Clause ********************************************************/ #include #include #include #include #include #include #include #include using std::string; using std::vector; using std::abs; template class Morph : public ::testing::Test { public: virtual void SetUp() {} }; // create a list of types to be tested typedef ::testing::Types TestTypes; // register the type list TYPED_TEST_CASE(Morph, TestTypes); template void morphTest(string pTestFile) { if (noDoubleTests()) return; vector numDims; vector > in; vector > tests; readTests(pTestFile, numDims, in, tests); af::dim4 dims = numDims[0]; af::dim4 maskDims = numDims[1]; af_array outArray = 0; af_array inArray = 0; af_array maskArray = 0; inType *outData; ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(in[0].front()), dims.ndims(), dims.get(), (af_dtype)af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &(in[1].front()), maskDims.ndims(), maskDims.get(), (af_dtype)af::dtype_traits::af_type)); if (isDilation) { if (isVolume) ASSERT_EQ(AF_SUCCESS, af_dilate3(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_SUCCESS, af_dilate(&outArray, inArray, maskArray)); } else { if (isVolume) ASSERT_EQ(AF_SUCCESS, af_erode3(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_SUCCESS, af_erode(&outArray, inArray, maskArray)); } outData = new inType[dims.elements()]; ASSERT_EQ(AF_SUCCESS, af_get_data_ptr((void*)outData, outArray)); for (size_t testIter=0; testIter currGoldBar = tests[testIter]; size_t nElems = currGoldBar.size(); for (size_t elIter=0; elIter(string(TEST_DIR"/morph/dilate3x3.test")); } TYPED_TEST(Morph, Erode3x3) { morphTest(string(TEST_DIR"/morph/erode3x3.test")); } TYPED_TEST(Morph, Dilate3x3_Batch) { morphTest(string(TEST_DIR"/morph/dilate3x3_batch.test")); } TYPED_TEST(Morph, Erode3x3_Batch) { morphTest(string(TEST_DIR"/morph/erode3x3_batch.test")); } TYPED_TEST(Morph, Dilate3x3x3) { morphTest(string(TEST_DIR"/morph/dilate3x3x3.test")); } TYPED_TEST(Morph, Erode3x3x3) { morphTest(string(TEST_DIR"/morph/erode3x3x3.test")); } template void morphImageTest(string pTestFile) { if (noDoubleTests()) return; if (noImageIOTests()) return; using af::dim4; vector inDims; vector inFiles; vector outSizes; vector outFiles; readImageTests(pTestFile, inDims, inFiles, outSizes, outFiles); size_t testCount = inDims.size(); for (size_t testId=0; testId::af_type)); ASSERT_EQ(AF_SUCCESS, af_load_image(&inArray, inFiles[testId].c_str(), isColor)); ASSERT_EQ(AF_SUCCESS, af_load_image(&goldArray, outFiles[testId].c_str(), isColor)); ASSERT_EQ(AF_SUCCESS, af_get_elements(&nElems, goldArray)); if (isDilation) ASSERT_EQ(AF_SUCCESS, af_dilate(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_SUCCESS, af_erode(&outArray, inArray, maskArray)); T * outData = new T[nElems]; ASSERT_EQ(AF_SUCCESS, af_get_data_ptr((void*)outData, outArray)); T * goldData= new T[nElems]; ASSERT_EQ(AF_SUCCESS, af_get_data_ptr((void*)goldData, goldArray)); ASSERT_EQ(true, compareArraysRMSD(nElems, goldData, outData, 0.018f)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(outArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(goldArray)); } } TEST(Morph, Grayscale) { morphImageTest(string(TEST_DIR"/morph/gray.test")); } TEST(Morph, ColorImage) { morphImageTest(string(TEST_DIR"/morph/color.test")); } template void morphInputTest(void) { if (noDoubleTests()) return; af_array inArray = 0; af_array maskArray = 0; af_array outArray = 0; vector in(100,1); vector mask(9,1); // Check for 1D inputs af::dim4 dims = af::dim4(100,1,1,1); af::dim4 mdims(3,3,1,1); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &mask.front(), mdims.ndims(), mdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &in.front(), dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); if (isDilation) ASSERT_EQ(AF_ERR_SIZE, af_dilate(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_ERR_SIZE, af_erode(&outArray, inArray, maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); } TYPED_TEST(Morph, DilateInvalidInput) { morphInputTest(); } TYPED_TEST(Morph, ErodeInvalidInput) { morphInputTest(); } template void morphMaskTest(void) { if (noDoubleTests()) return; af_array inArray = 0; af_array maskArray = 0; af_array outArray = 0; vector in(100,1); vector mask(16,1); // Check for 4D mask af::dim4 dims(10,10,1,1); af::dim4 mdims(2,2,2,2); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &in.front(), dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &mask.front(), mdims.ndims(), mdims.get(), (af_dtype) af::dtype_traits::af_type)); if (isDilation) ASSERT_EQ(AF_ERR_SIZE, af_dilate(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_ERR_SIZE, af_erode(&outArray, inArray, maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); // Check for 1D mask mdims = af::dim4(16,1,1,1); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &mask.front(), mdims.ndims(), mdims.get(), (af_dtype) af::dtype_traits::af_type)); if (isDilation) ASSERT_EQ(AF_ERR_SIZE, af_dilate(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_ERR_SIZE, af_erode(&outArray, inArray, maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); } TYPED_TEST(Morph, DilateInvalidMask) { morphMaskTest(); } TYPED_TEST(Morph, ErodeInvalidMask) { morphMaskTest(); } template void morph3DMaskTest(void) { if (noDoubleTests()) return; af_array inArray = 0; af_array maskArray = 0; af_array outArray = 0; vector in(1000,1); vector mask(81,1); // Check for 2D mask af::dim4 dims(10,10,10,1); af::dim4 mdims(9,9,1,1); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &in.front(), dims.ndims(), dims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &mask.front(), mdims.ndims(), mdims.get(), (af_dtype) af::dtype_traits::af_type)); if (isDilation) ASSERT_EQ(AF_ERR_SIZE, af_dilate3(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_ERR_SIZE, af_erode3(&outArray, inArray, maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); // Check for 4D mask mdims = af::dim4(3,3,3,3); ASSERT_EQ(AF_SUCCESS, af_create_array(&maskArray, &mask.front(), mdims.ndims(), mdims.get(), (af_dtype) af::dtype_traits::af_type)); if (isDilation) ASSERT_EQ(AF_ERR_SIZE, af_dilate3(&outArray, inArray, maskArray)); else ASSERT_EQ(AF_ERR_SIZE, af_erode3(&outArray, inArray, maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(maskArray)); ASSERT_EQ(AF_SUCCESS, af_release_array(inArray)); } TYPED_TEST(Morph, DilateVolumeInvalidMask) { morph3DMaskTest(); } TYPED_TEST(Morph, ErodeVolumeInvalidMask) { morph3DMaskTest(); } ////////////////////////////////////// CPP ////////////////////////////////// // template void cppMorphImageTest(string pTestFile) { if (noDoubleTests()) return; if (noImageIOTests()) return; using af::dim4; vector inDims; vector inFiles; vector outSizes; vector outFiles; readImageTests(pTestFile, inDims, inFiles, outSizes, outFiles); size_t testCount = inDims.size(); for (size_t testId=0; testId(string(TEST_DIR"/morph/gray.test")); } TEST(Morph, ColorImage_CPP) { cppMorphImageTest(string(TEST_DIR"/morph/color.test")); } using namespace af; TEST(Morph, GFOR) { dim4 dims = dim4(10, 10, 3); array A = iota(dims); array B = constant(0, dims); array mask = randu(3,3) > 0.3; gfor(seq ii, 3) { B(span, span, ii) = erode(A(span, span, ii), mask); } for(int ii = 0; ii < 3; ii++) { array c_ii = erode(A(span, span, ii), mask); array b_ii = B(span, span, ii); ASSERT_EQ(max(abs(c_ii - b_ii)) < 1E-5, true); } }