From 1c14360163bd3299deb61f7f3b01c3692d5a6ce1 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Wed, 17 Mar 2021 18:52:29 +0300 Subject: [PATCH] doc: std-bits --- .../src/Image/Data/Matrix/Internal.enso | 2 +- .../src/main/java/org/enso/image/Image.java | 23 ++- .../main/java/org/enso/image/data/Matrix.java | 134 ++++++++++++++++-- 3 files changed, 143 insertions(+), 16 deletions(-) diff --git a/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso b/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso index f5658adec1425..27b09b51c916a 100644 --- a/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso +++ b/distribution/std-lib/Standard/src/Image/Data/Matrix/Internal.enso @@ -13,7 +13,7 @@ create rows cols mat_type values = ## PRIVATE core_op mat value function = - new_mat = Java_Matrix.create mat + new_mat = Java_Matrix.zeros mat scalar = case value of Vector.Vector arr -> Scalar.new arr diff --git a/std-bits/src/main/java/org/enso/image/Image.java b/std-bits/src/main/java/org/enso/image/Image.java index 6a20d7f4a37eb..4f03d1cb31a84 100644 --- a/std-bits/src/main/java/org/enso/image/Image.java +++ b/std-bits/src/main/java/org/enso/image/Image.java @@ -2,7 +2,6 @@ import org.enso.image.opencv.OpenCV; import org.opencv.core.Core; -import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfInt; import org.opencv.imgcodecs.Imgcodecs; @@ -16,6 +15,7 @@ public class Image { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } + /** An error occurred when reading a file. */ public static class ReadFailedException extends Exception { public ReadFailedException(String path) { @@ -23,6 +23,7 @@ public ReadFailedException(String path) { } } + /** An error occurred when writing a file */ public static class WriteFailedException extends Exception { public WriteFailedException(String path) { @@ -30,6 +31,14 @@ public WriteFailedException(String path) { } } + /** + * Read an image from the file. + * + * @param path the file path to read from. + * @param flags the read flags. + * @return the matrix holding the image data. + * @throws ReadFailedException + */ public static Mat read(String path, int flags) throws ReadFailedException { Mat input; if (flags == READ_FLAG_EMPTY) { @@ -45,6 +54,14 @@ public static Mat read(String path, int flags) throws ReadFailedException { return input; } + /** + * Write an image to the file. + * + * @param path the file path to write to. + * @param image the matrix representing the image. + * @param flags the write flags. + * @throws WriteFailedException + */ public static void write(String path, Mat image, MatOfInt flags) throws WriteFailedException { boolean result; if (flags.empty()) { @@ -58,8 +75,4 @@ public static void write(String path, Mat image, MatOfInt flags) throws WriteFai } } - public static Double normalize(byte pixelValue) { - return ((int) pixelValue + 128) / 255.0; - } - } diff --git a/std-bits/src/main/java/org/enso/image/data/Matrix.java b/std-bits/src/main/java/org/enso/image/data/Matrix.java index 5f321288b5da4..b0ca3448b3135 100644 --- a/std-bits/src/main/java/org/enso/image/data/Matrix.java +++ b/std-bits/src/main/java/org/enso/image/data/Matrix.java @@ -6,6 +6,7 @@ import java.util.Base64; +/** Methods for operations on Matrix. */ public class Matrix { static { @@ -18,18 +19,36 @@ public class Matrix { private static final String EXTENSION_PNG = ".png"; - public static Mat create(Mat mat) { - return Mat.zeros(mat.size(), mat.type()); - } - + /** + * Create a matrix filled with zeros. + * + * @param rows the number of rows. + * @param cols the number of columns + * @param channels the number of channels. + * @return the zero matrix. + */ public static Mat zeros(int rows, int cols, int channels) { return Mat.zeros(rows, cols, CvType.CV_8UC(channels)); } + /** + * Create a matrix filled with zeros. + * + * @param m the matrix defining the shape. + * @return the matrix of zeros with the same shape as the provided one. + */ public static Mat zeros(Mat m) { return Matrix.zeros(m.channels(), m.rows(), m.cols()); } + /** + * Create a matrix filled with ones. + * + * @param rows the number of rows. + * @param cols the number of columns. + * @param channels the number of channels. + * @return the matrix of ones. + */ public static Mat ones(int rows, int cols, int channels) { byte[] bytes = new byte[channels * rows * cols]; for (int i = 0; i < channels * rows * cols; i++) { @@ -38,6 +57,14 @@ public static Mat ones(int rows, int cols, int channels) { return new MatOfByte(bytes).reshape(channels, rows); } + /** + * Create an identity matrix. + * + * @param rows the number of rows. + * @param cols the number of columns. + * @param channels the number of channels. + * @return the identity matrix. + */ public static Mat eye(int rows, int cols, int channels) { Mat ones = Matrix.ones(rows, cols, channels); Mat eye = Mat.eye(rows, cols, CvType.CV_8UC(channels)); @@ -47,6 +74,14 @@ public static Mat eye(int rows, int cols, int channels) { return dst; } + /** + * Create a matrix from the vector. + * + * @param values the array of input values. + * @param channels the number of channels. + * @param rows the number of rows. + * @return the new matrix created from array. + */ public static Mat from_vector(double[] values, int channels, int rows) { byte[] bytes = new byte[values.length]; for (int i = 0; i < values.length; i++) { @@ -55,20 +90,39 @@ public static Mat from_vector(double[] values, int channels, int rows) { return new MatOfByte(bytes).reshape(channels, rows); } + /** + * Get the values of a matris as an array. + * + * @param mat the matrix. + * @return the array of the matrix values. + */ public static Object to_vector(Mat mat) { byte[] data = new byte[(int) mat.total() * mat.channels()]; mat.get(0, 0, data); return Matrix.normalize(data); } - public static String to_base64(Mat image) { + /** + * Encode the matrix into the base64 string. + * + * @param mat the matrix to encode. + * @return the base64 string representing the matrix data. + */ + public static String to_base64(Mat mat) { MatOfByte buf = new MatOfByte(); - Imgcodecs.imencode(EXTENSION_PNG, image, buf); + Imgcodecs.imencode(EXTENSION_PNG, mat, buf); byte[] bufData = new byte[(int) buf.total() * buf.channels()]; buf.get(0, 0, bufData); return Base64.getEncoder().encodeToString(bufData); } + /** + * Compare two matrices for equality. + * + * @param mat1 the first matrix to compare. + * @param mat2 the second matrix to compare. + * @return {@code true} when two matrices contain the same elements and {@code false} otherwise. + */ public static boolean is_equals(Mat mat1, Mat mat2) { if (mat1.size().equals(mat2.size()) && mat1.type() == mat2.type()) { Mat dst = Mat.zeros(mat1.size(), mat1.type()); @@ -78,6 +132,14 @@ public static boolean is_equals(Mat mat1, Mat mat2) { return false; } + /** + * Get the matrices' element by the row and the column. + * + * @param mat the matrix. + * @param row the row index. + * @param column the column index. + * @return the value located at the given row and the column of the matrix. + */ public static Object get(Mat mat, int row, int column) { byte[] data = new byte[mat.channels()]; int[] idx = new int[] { row, column }; @@ -86,22 +148,54 @@ public static Object get(Mat mat, int row, int column) { return Matrix.normalize(data); } + /** + * Add the scalar to each element of the matrix. + * + * @param mat the matrix. + * @param scalar the scalar to add. + * @param dst the matrix holding the result of the operation. + */ public static void add(Mat mat, Scalar scalar, Mat dst) { Core.add(mat, denormalize(scalar), dst); } + /** + * Subtract the scalar from each element of the matrix. + * @param mat the matrix. + * @param scalar the scalar to subtract. + * @param dst the matrix holding the result of the operation. + */ public static void subtract(Mat mat, Scalar scalar, Mat dst) { Core.subtract(mat, denormalize(scalar), dst); } + /** + * Multiply the scalar with each element of the matrix. + * @param mat the matrix. + * @param scalar the scalar to multiply with. + * @param dst the matrix holding the result of the operation. + */ public static void multiply(Mat mat, Scalar scalar, Mat dst) { Core.multiply(mat, scalar, dst); } + /** + * Divite each element of the matrix by the scalar. + * + * @param mat the matrix + * @param scalar the scalar to divide on. + * @param dst the matrix holding the result of the operation. + */ public static void divide(Mat mat, Scalar scalar, Mat dst) { Core.divide(mat, scalar, dst); } + /** + * Normalize the byte array. + * + * @param bytes the byte array to normalize. + * @return return normalized values in the range of 0.0 to 1.0. + */ private static double[] normalize(byte[] bytes) { double[] buf = new double[bytes.length]; for (int i = 0; i < bytes.length; i++) { @@ -110,16 +204,36 @@ private static double[] normalize(byte[] bytes) { return buf; } - private static double normalize(byte pixelValue) { - return (pixelValue & 0xff) / MAX_UNSIGNED_BYTE; + /** + * Normalize the byte value. + * + * @param value the value to normalize. + * @return return the normalized value in the range of [0.0 .. 1.0]. + */ + private static double normalize(byte value) { + return (value & 0xff) / MAX_UNSIGNED_BYTE; } + /** + * Denormalize the value into the byte range. + * + * @param scalar the normalized scalar. + * @return the scalar scaled from normalized range [0.0 .. 1.0] to a byte range. + */ private static Scalar denormalize(Scalar scalar) { return scalar.mul(Scalar.all(MAX_UNSIGNED_BYTE)); } - private static byte denormalize(double pixelValue) { - return (byte) (pixelValue * MAX_UNSIGNED_BYTE); + /** + * Denormalized the value into a byte range. + * + *

The following holds: {@code denormalize(normalize(value)) == value}. + * + * @param value the normalized value + * @return the value scaled from normalized range [0.0 .. 1.0] to a byte range. + */ + private static byte denormalize(double value) { + return (byte) (value * MAX_UNSIGNED_BYTE); } }