diff --git a/scripts/builtin/img_crop_linearized.dml b/scripts/builtin/img_crop_linearized.dml new file mode 100644 index 00000000000..b2c2c03fd18 --- /dev/null +++ b/scripts/builtin/img_crop_linearized.dml @@ -0,0 +1,67 @@ +#------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#------------------------------------------------------------- + +# The img_crop_linearized cuts out a rectangular section of multiple linearized images. +# +# INPUT: +# ---------------------------------------------------------------------------------------- +# img_in Linearized input images as 2D matrix +# w The width of the subregion required +# h The height of the subregion required +# x_offset The horizontal offset for the center of the crop region +# y_offset The vertical offset for the center of the crop region +# s_cols Width of a single image +# s_rows Height of a single image +# ---------------------------------------------------------------------------------------- +# +# OUTPUT: +# -------------------------------------------------------------------------------------------------- +# img_out Cropped images as linearized 2D matrix +# -------------------------------------------------------------------------------------------------- + +m_img_crop_linearized = function(Matrix[Double] img_in, Integer w, Integer h, Integer x_offset, Integer y_offset, + Integer s_cols, Integer s_rows) return (Matrix[Double] img_out) { + + orig_w = s_cols + orig_h = s_rows + + nrows = nrow(img_in) # number of images + + start_h = (ceil((orig_h - h) / 2)) + y_offset + end_h = (start_h + h - 1) + start_w = (ceil((orig_w - w) / 2)) + x_offset + end_w = (start_w + w - 1) + + if((start_h < 0) | (end_h > orig_h) | (start_w < 0) | (end_w > orig_w)) { + print("Offset out of bounds! Returning input.") + img_out = img_in + } + else { + mask = matrix(0, rows=orig_h, cols=orig_w) + temp_mask = matrix(1, rows=h , cols=w ) + mask[start_h:end_h, start_w:end_w] = temp_mask + + linear_mask = matrix(mask, rows=1, cols=orig_w * orig_h) + + img_out = matrix(removeEmpty(target=(matrix(img_in+1, nrow(img_in), ncol(img_in))), margin="cols", select=linear_mask) - 1, nrows, w * h) + } +} + diff --git a/src/main/java/org/apache/sysds/common/Builtins.java b/src/main/java/org/apache/sysds/common/Builtins.java index 883e57aa22f..052481a97e0 100644 --- a/src/main/java/org/apache/sysds/common/Builtins.java +++ b/src/main/java/org/apache/sysds/common/Builtins.java @@ -157,6 +157,7 @@ public enum Builtins { IMG_MIRROR("img_mirror", true), IMG_BRIGHTNESS("img_brightness", true), IMG_CROP("img_crop", true), + IMG_CROP_LINEARIZED("img_crop_linearized", true), IMG_TRANSFORM("img_transform", true), IMG_TRANSLATE("img_translate", true), IMG_ROTATE("img_rotate", true), diff --git a/src/test/java/org/apache/sysds/test/functions/builtin/part1/BuiltinImageCropLinTest.java b/src/test/java/org/apache/sysds/test/functions/builtin/part1/BuiltinImageCropLinTest.java new file mode 100644 index 00000000000..4f6e8c20e66 --- /dev/null +++ b/src/test/java/org/apache/sysds/test/functions/builtin/part1/BuiltinImageCropLinTest.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysds.test.functions.builtin.part1; + +import org.junit.Test; +import org.apache.sysds.common.Types.ExecMode; +import org.apache.sysds.common.Types.ExecType; +import org.apache.sysds.runtime.matrix.data.MatrixValue; +import org.apache.sysds.test.AutomatedTestBase; +import org.apache.sysds.test.TestConfiguration; +import org.apache.sysds.test.TestUtils; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.HashMap; +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@net.jcip.annotations.NotThreadSafe + +public class BuiltinImageCropLinTest extends AutomatedTestBase { + private final static String TEST_NAME = "image_crop_linearized"; + private final static String TEST_DIR = "functions/builtin/"; + private final static String TEST_CLASS_DIR = TEST_DIR + BuiltinImageCropLinTest.class.getSimpleName() + "/"; + + private final static double eps = 1e-10; + private final static double spSparse = 0.1; + private final static double spDense = 0.9; + + @Parameterized.Parameter(0) + public int s_cols; + @Parameterized.Parameter(1) + public int s_rows; + @Parameterized.Parameter(2) + public int rows; + @Parameterized.Parameter(3) + public int x_offset; + @Parameterized.Parameter(4) + public int y_offset; + @Parameterized.Parameter(5) + public double size; + + public int cols; + public int new_w; + public int new_h; + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList(new Object[][] { + { 10, 12, 20, 2, 3, 0.5 }, + { 12, 12, 40, 5, 5, 0.4 }, + { 32, 32, 200, 13, 10, 0.2 }, + { 31, 33, 200, 7, 10, 0.2 }, + { 64, 64, 50, 2, 0, 0.8 }, + { 125, 123, 32, 7, 37, 0.3 }, + { 128, 128, 83, 23, 14, 0.123 }, + { 256, 50, 2, 0, 0, 0.8 }, + { 256, 255, 2, 0, 0, 0.8 }, + { 512, 300, 47, 6, 7, 0.7 } + }); + } + + @Override + public void setUp() { + cols = s_cols * s_rows; + new_w = (int) Math.floor(s_cols * size); + new_h = (int) Math.floor(s_rows * size); + addTestConfiguration(TEST_NAME, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] { "B" })); + } + + @Test + public void testImageCropMatrixDenseCP() { + runImageCropLinTest(false, ExecType.CP); + } + + @Test + public void testImageCropMatrixSparseCP() { + runImageCropLinTest(true, ExecType.CP); + } + + @Test + public void testImageCropMatrixDenseSP() { + runImageCropLinTest(false, ExecType.SPARK); + } + + @Test + public void testImageCropMatrixSparseSP() { + runImageCropLinTest(true, ExecType.SPARK); + } + + private void runImageCropLinTest(boolean sparse, ExecType instType) { + ExecMode platformOld = setExecMode(instType); + disableOutAndExpectedDeletion(); + + try { + loadTestConfiguration(getTestConfiguration(TEST_NAME)); + double sparsity = sparse ? spSparse : spDense; + + String HOME = SCRIPT_DIR + TEST_DIR; + fullDMLScriptName = HOME + TEST_NAME + ".dml"; + programArgs = new String[] { "-nvargs", + "in_file=" + input("A"), "out_file=" + output("B"), + "x_offset=" + x_offset, "y_offset=" + y_offset, "cols=" + cols, "rows=" + rows, + "s_cols=" + s_cols, "s_rows=" + s_rows, "new_w=" + new_w, "new_h=" + new_h }; + + // generate actual dataset + double[][] A = getRandomMatrix(rows, cols, 0, 255, sparsity, 7); + writeInputMatrixWithMTD("A", A, true); + + // crop functionality in java + double[][] ref = new double[rows][new_h * new_w]; + int start_h = (int) Math.ceil((double) (s_rows - new_h) / 2) + y_offset; + int start_w = (int) Math.ceil((double) (s_cols - new_w) / 2) + x_offset; + + for (int i = 0; i < rows; i++) { + if (start_w == 0 && start_h == 0) { + ref[i] = A[i]; + } else { + for (int j = 0; j < new_h * new_w; j++) { + int ja = ((j / new_w) + start_h - 1) * s_cols + (j % new_w) + start_w - 1; + ref[i][j] = A[i][ja]; + } + } + } + + writeInputMatrixWithMTD("ref", ref, true); + + runTest(true, false, null, -1); + + HashMap dmlfile = readDMLMatrixFromOutputDir("B"); + double[][] dml_res = TestUtils.convertHashMapToDoubleArray(dmlfile, rows, + (new_h * new_w)); + TestUtils.compareMatrices(ref, dml_res, eps, "Java vs. DML"); + + } finally { + rtplatform = platformOld; + } + + } + +} diff --git a/src/test/scripts/functions/builtin/image_crop_linearized.dml b/src/test/scripts/functions/builtin/image_crop_linearized.dml new file mode 100644 index 00000000000..6cfe7b3ba82 --- /dev/null +++ b/src/test/scripts/functions/builtin/image_crop_linearized.dml @@ -0,0 +1,36 @@ +#------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +#------------------------------------------------------------- + +input = read($in_file); + +x_offset = ifdef($x_offset, 0) +y_offset = ifdef($y_offset, 0) +cols = ifdef($cols, 512) +rows = ifdef($rows, 512) +s_cols = ifdef($s_cols, 512) +s_rows = ifdef($s_rows, 512) +new_w = ifdef($new_w, 512) +new_h = ifdef($new_h, 512) + +input = matrix(input, rows=rows, cols=cols) + +crop2 = img_crop_linearized(input, new_w, new_h, x_offset, y_offset, s_cols, s_rows) +write(crop2, $out_file);