All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.alg.misc.ImageMiscOps Maven / Gradle / Ivy

/*
 * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed 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 boofcv.alg.misc;

import boofcv.struct.image.*;

import java.util.Random;


/**
 * Basic image operations which have no place better to go.
 *
 * 

DO NOT MODIFY: Generated by GenerateImageMiscOps.

* * @author Peter Abeles */ public class ImageMiscOps { /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayI8 input , GrayI8 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayI8 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = (byte)value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedI8 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = (byte)value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedI8 input, int[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; int value = values[band]; for (; index < end; index += numBands ) { input.data[index] = (byte)value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedI8 input, int band , int value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = (byte)value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayI8 input, int band , InterleavedI8 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayI8 input, int value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = (byte)value; input.data[indexBottom++] = (byte)value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = (byte)value; input.data[indexRight] = (byte)value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayI8 img, int value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedI8 img, byte value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(GrayI8 img, Random rand , int min , int max) { int range = max-min; byte[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = (byte)(rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(InterleavedI8 img, Random rand , int min , int max) { int range = max-min; byte[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = (byte)(rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayI8 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { byte[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = (byte)value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedI8 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { byte[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = (byte)value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayI8 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (byte)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayI8 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (byte)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayI8 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (byte)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayI8 input , GrayI8 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayI8 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (byte)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayI8 input , GrayI8 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayI16 input , GrayI16 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayI16 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = (short)value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedI16 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = (short)value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedI16 input, int[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; int value = values[band]; for (; index < end; index += numBands ) { input.data[index] = (short)value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedI16 input, int band , int value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = (short)value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayI16 input, int band , InterleavedI16 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayI16 input, int value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = (short)value; input.data[indexBottom++] = (short)value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = (short)value; input.data[indexRight] = (short)value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayI16 img, int value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedI16 img, short value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(GrayI16 img, Random rand , int min , int max) { int range = max-min; short[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = (short)(rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(InterleavedI16 img, Random rand , int min , int max) { int range = max-min; short[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = (short)(rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayI16 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { short[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = (short)value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedI16 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { short[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = (short)value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayI16 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (short)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayI16 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (short)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayI16 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (short)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayI16 input , GrayI16 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayI16 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (short)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayI16 input , GrayI16 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayS32 input , GrayS32 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayS32 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedS32 input, int value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedS32 input, int[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; int value = values[band]; for (; index < end; index += numBands ) { input.data[index] = value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedS32 input, int band , int value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayS32 input, int band , InterleavedS32 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayS32 input, int value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = value; input.data[indexBottom++] = value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = value; input.data[indexRight] = value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayS32 img, int value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedS32 img, int value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(GrayS32 img, Random rand , int min , int max) { int range = max-min; int[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = (rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(InterleavedS32 img, Random rand , int min , int max) { int range = max-min; int[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = (rand.nextInt(range)+min); } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayS32 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { int[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedS32 input, Random rand , double mean , double sigma , int lowerBound , int upperBound ) { int[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (int)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayS32 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (int)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayS32 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { int tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (int)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayS32 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (int)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayS32 input , GrayS32 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayS32 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; int tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (int)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayS32 input , GrayS32 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayS64 input , GrayS64 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayS64 input, long value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedS64 input, long value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedS64 input, long[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; long value = values[band]; for (; index < end; index += numBands ) { input.data[index] = value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedS64 input, int band , long value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayS64 input, int band , InterleavedS64 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayS64 input, long value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = value; input.data[indexBottom++] = value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = value; input.data[indexRight] = value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayS64 img, long value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedS64 img, long value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(GrayS64 img, Random rand , long min , long max) { long range = max-min; long[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = rand.nextInt((int)range)+min; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, exclusive */ public static void fillUniform(InterleavedS64 img, Random rand , long min , long max) { long range = max-min; long[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = rand.nextInt((int)range)+min; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayS64 input, Random rand , double mean , double sigma , long lowerBound , long upperBound ) { long[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { long value = (long)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedS64 input, Random rand , double mean , double sigma , long lowerBound , long upperBound ) { long[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { long value = (long)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayS64 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { long tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (long)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayS64 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { long tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (long)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayS64 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; long tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (long)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayS64 input , GrayS64 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayS64 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; long tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (long)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayS64 input , GrayS64 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayF32 input , GrayF32 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayF32 input, float value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedF32 input, float value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedF32 input, float[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; float value = values[band]; for (; index < end; index += numBands ) { input.data[index] = value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedF32 input, int band , float value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayF32 input, int band , InterleavedF32 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayF32 input, float value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = value; input.data[indexBottom++] = value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = value; input.data[indexRight] = value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayF32 img, float value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedF32 img, float value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, inclusive */ public static void fillUniform(GrayF32 img, Random rand , float min , float max) { float range = max-min; float[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = rand.nextFloat()*range+min; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, inclusive */ public static void fillUniform(InterleavedF32 img, Random rand , float min , float max) { float range = max-min; float[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = rand.nextFloat()*range+min; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayF32 input, Random rand , double mean , double sigma , float lowerBound , float upperBound ) { float[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { float value = (float)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedF32 input, Random rand , double mean , double sigma , float lowerBound , float upperBound ) { float[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { float value = (float)(rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayF32 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { float tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (float)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayF32 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { float tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (float)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayF32 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; float tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (float)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayF32 input , GrayF32 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayF32 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; float tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (float)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayF32 input , GrayF32 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Copies a rectangular region from one image into another.
* output[dstX:(dstX+width) , dstY:(dstY+height-1)] = input[srcX:(srcX+width) , srcY:(srcY+height-1)] * * @param srcX x-coordinate of corner in input image * @param srcY y-coordinate of corner in input image * @param dstX x-coordinate of corner in output image * @param dstY y-coordinate of corner in output image * @param width Width of region to be copied * @param height Height of region to be copied * @param input Input image * @param output output image */ public static void copy(int srcX , int srcY , int dstX , int dstY , int width , int height , GrayF64 input , GrayF64 output ) { if( input.width < srcX+width || input.height < srcY+height ) throw new IllegalArgumentException("Copy region must be contained input image"); if( output.width < dstX+width || output.height < dstY+height ) throw new IllegalArgumentException("Copy region must be contained output image"); for (int y = 0; y < height; y++) { int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX; int indexDst = output.startIndex + (dstY + y) * output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = input.data[indexSrc++]; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(GrayF64 input, double value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { input.data[index++] = value; } } } /** * Fills the whole image with the specified value * * @param input An image. * @param value The value that the image is being filled with. */ public static void fill(InterleavedF64 input, double value) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int end = index + input.width*input.numBands; for (; index < end; index++ ) { input.data[index] = value; } } } /** * Fills each band in the image with the specified values * * @param input An image. * @param values Array which contains the values each band is to be filled with. */ public static void fill(InterleavedF64 input, double[] values) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { for( int band = 0; band < numBands; band++ ) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; double value = values[band]; for (; index < end; index += numBands ) { input.data[index] = value; } } } } /** * Fills one band in the image with the specified value * * @param input An image. * @param band Which band is to be filled with the specified value * @param value The value that the image is being filled with. */ public static void fillBand(InterleavedF64 input, int band , double value) { final int numBands = input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride() + band; int end = index + input.width*numBands - band; for (; index < end; index += numBands ) { input.data[index] = value; } } } /** * Inserts a single band into into one of the bands in a multi-band image * * @param input Single band image * @param band Which band the image is to be inserted into * @param output The multi-band image which the input image is to be inserted into */ public static void insertBand(GrayF64 input, int band , InterleavedF64 output) { final int numBands = output.numBands; for (int y = 0; y < input.height; y++) { int indexIn = input.getStartIndex() + y * input.getStride(); int indexOut = output.getStartIndex() + y * output.getStride() + band; int end = indexOut + output.width*numBands - band; for (; indexOut < end; indexOut += numBands , indexIn++ ) { output.data[indexOut] = input.data[indexIn]; } } } /** * Fills the outside border with the specified value * * @param input An image. * @param value The value that the image is being filled with. * @param radius Border width. */ public static void fillBorder(GrayF64 input, double value, int radius ) { // top and bottom for (int y = 0; y < radius; y++) { int indexTop = input.startIndex + y * input.stride; int indexBottom = input.startIndex + (input.height-y-1) * input.stride; for (int x = 0; x < input.width; x++) { input.data[indexTop++] = value; input.data[indexBottom++] = value; } } // left and right int h = input.height-radius; int indexStart = input.startIndex + radius*input.stride; for (int x = 0; x < radius; x++) { int indexLeft = indexStart + x; int indexRight = indexStart + input.width-1-x; for (int y = radius; y < h; y++) { input.data[indexLeft] = value; input.data[indexRight] = value; indexLeft += input.stride; indexRight += input.stride; } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(GrayF64 img, double value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; for (int y = y0; y < y1; y++) { for (int x = x0; x < x1; x++) { img.set(x, y, value); } } } /** * Draws a filled rectangle that is aligned along the image axis inside the image. All bands * are filled with the same value. * * @param img Image the rectangle is drawn in. Modified * @param value Value of the rectangle * @param x0 Top left x-coordinate * @param y0 Top left y-coordinate * @param width Rectangle width * @param height Rectangle height */ public static void fillRectangle(InterleavedF64 img, double value, int x0, int y0, int width, int height) { int x1 = x0 + width; int y1 = y0 + height; if( x0 < 0 ) x0 = 0; if( x1 > img.width ) x1 = img.width; if( y0 < 0 ) y0 = 0; if( y1 > img.height ) y1 = img.height; int length = (x1-x0)*img.numBands; for (int y = y0; y < y1; y++) { int index = img.startIndex + y*img.stride + x0*img.numBands; int indexEnd = index + length; while( index < indexEnd ) { img.data[index++] = value; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, inclusive */ public static void fillUniform(GrayF64 img, Random rand , double min , double max) { double range = max-min; double[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); for (int x = 0; x < img.width; x++) { data[index++] = rand.nextDouble()*range+min; } } } /** * Sets each value in the image to a value drawn from an uniform distribution that has a range of min ≤ X < max. * * @param img Image which is to be filled. Modified, * @param rand Random number generator * @param min Minimum value of the distribution, inclusive * @param max Maximum value of the distribution, inclusive */ public static void fillUniform(InterleavedF64 img, Random rand , double min , double max) { double range = max-min; double[] data = img.data; for (int y = 0; y < img.height; y++) { int index = img.getStartIndex() + y * img.getStride(); int end = index + img.width*img.numBands; for (; index < end; index++) { data[index] = rand.nextDouble()*range+min; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(GrayF64 input, Random rand , double mean , double sigma , double lowerBound , double upperBound ) { double[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { double value = (rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Sets each value in the image to a value drawn from a Gaussian distribution. A user * specified lower and upper bound is provided to ensure that the values are within a legal * range. A drawn value outside the allowed range will be set to the closest bound. * * @param input Input image. Modified. * @param rand Random number generator * @param mean Distribution's mean. * @param sigma Distribution's standard deviation. * @param lowerBound Lower bound of value clip * @param upperBound Upper bound of value clip */ public static void fillGaussian(InterleavedF64 input, Random rand , double mean , double sigma , double lowerBound , double upperBound ) { double[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { double value = (rand.nextGaussian()*sigma+mean); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; data[index++] = value; } } } /** * Flips the image from top to bottom */ public static void flipVertical( GrayF64 input ) { int h2 = input.height/2; for( int y = 0; y < h2; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = input.getStartIndex() + (input.height - y - 1) * input.getStride(); int end = index1 + input.width; while( index1 < end ) { double tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2++] = (double)tmp; } } } /** * Flips the image from left to right */ public static void flipHorizontal( GrayF64 input ) { int w2 = input.width/2; for( int y = 0; y < input.height; y++ ) { int index1 = input.getStartIndex() + y * input.getStride(); int index2 = index1 + input.width-1; int end = index1 + w2; while( index1 < end ) { double tmp = input.data[index1]; input.data[index1++] = input.data[index2]; input.data[index2--] = (double)tmp; } } } /** * In-place 90 degree image rotation in the clockwise direction. Only works on * square images. */ public static void rotateCW( GrayF64 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; double tmp3 = image.data[index3]; image.data[index3] = image.data[index2]; image.data[index2] = image.data[index1]; image.data[index1] = image.data[index0]; image.data[index0] = (double)tmp3; } } } /** * Rotates the image 90 degrees in the clockwise direction. */ public static void rotateCW(GrayF64 input , GrayF64 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int h = input.height-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(h-y,x,input.data[indexIn++]); } } } /** * In-place 90 degree image rotation in the counter-clockwise direction. Only works on * square images. */ public static void rotateCCW( GrayF64 image ) { if( image.width != image.height ) throw new IllegalArgumentException("Image must be square"); int w = image.height/2 + image.height%2; int h = image.height/2; for( int y0 = 0; y0 < h; y0++ ) { int y1 = image.height-y0-1; for( int x0 = 0; x0 < w; x0++ ) { int x1 = image.width-x0-1; int index0 = image.startIndex + y0*image.stride + x0; int index1 = image.startIndex + x0*image.stride + y1; int index2 = image.startIndex + y1*image.stride + x1; int index3 = image.startIndex + x1*image.stride + y0; double tmp0 = image.data[index0]; image.data[index0] = image.data[index1]; image.data[index1] = image.data[index2]; image.data[index2] = image.data[index3]; image.data[index3] = (double)tmp0; } } } /** * Rotates the image 90 degrees in the counter-clockwise direction. */ public static void rotateCCW(GrayF64 input , GrayF64 output ) { if( input.width != output.height || input.height != output.width ) throw new IllegalArgumentException("Incompatible shapes"); int w = input.width-1; for( int y = 0; y < input.height; y++ ) { int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y,w-x,input.data[indexIn++]); } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayU8 input, Random rand , int min , int max) { int range = max-min; byte[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (data[index] & 0xFF) + rand.nextInt(range)+min; if( value < 0 ) value = 0; if( value > 255 ) value = 255; data[index++] = (byte) value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedU8 input, Random rand , int min , int max) { int range = max-min; byte[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (data[index] & 0xFF) + rand.nextInt(range)+min; if( value < 0 ) value = 0; if( value > 255 ) value = 255; data[index++] = (byte) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayU8 input, Random rand , double sigma , int lowerBound , int upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (input.data[index] & 0xFF) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (byte) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedU8 input, Random rand , double sigma , int lowerBound , int upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (input.data[index]& 0xFF) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (byte)value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayS8 input, Random rand , int min , int max) { int range = max-min; byte[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (data[index] ) + rand.nextInt(range)+min; if( value < -128 ) value = -128; if( value > 127 ) value = 127; data[index++] = (byte) value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedS8 input, Random rand , int min , int max) { int range = max-min; byte[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (data[index] ) + rand.nextInt(range)+min; if( value < -128 ) value = -128; if( value > 127 ) value = 127; data[index++] = (byte) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayS8 input, Random rand , double sigma , int lowerBound , int upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (input.data[index] ) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (byte) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedS8 input, Random rand , double sigma , int lowerBound , int upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (input.data[index]) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (byte)value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayU16 input, Random rand , int min , int max) { int range = max-min; short[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (data[index] & 0xFFFF) + rand.nextInt(range)+min; if( value < 0 ) value = 0; if( value > 65535 ) value = 65535; data[index++] = (short) value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedU16 input, Random rand , int min , int max) { int range = max-min; short[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (data[index] & 0xFFFF) + rand.nextInt(range)+min; if( value < 0 ) value = 0; if( value > 65535 ) value = 65535; data[index++] = (short) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayU16 input, Random rand , double sigma , int lowerBound , int upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (input.data[index] & 0xFFFF) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (short) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedU16 input, Random rand , double sigma , int lowerBound , int upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (input.data[index]& 0xFFFF) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (short)value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayS16 input, Random rand , int min , int max) { int range = max-min; short[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (data[index] ) + rand.nextInt(range)+min; if( value < -32768 ) value = -32768; if( value > 32767 ) value = 32767; data[index++] = (short) value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedS16 input, Random rand , int min , int max) { int range = max-min; short[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (data[index] ) + rand.nextInt(range)+min; if( value < -32768 ) value = -32768; if( value > 32767 ) value = 32767; data[index++] = (short) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayS16 input, Random rand , double sigma , int lowerBound , int upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (input.data[index] ) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (short) value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedS16 input, Random rand , double sigma , int lowerBound , int upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (input.data[index]) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = (short)value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayS32 input, Random rand , int min , int max) { int range = max-min; int[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (data[index] ) + rand.nextInt(range)+min; data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedS32 input, Random rand , int min , int max) { int range = max-min; int[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (data[index] ) + rand.nextInt(range)+min; data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayS32 input, Random rand , double sigma , int lowerBound , int upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { int value = (input.data[index] ) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedS32 input, Random rand , double sigma , int lowerBound , int upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { int value = (input.data[index]) + (int)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayS64 input, Random rand , long min , long max) { long range = max-min; long[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { long value = data[index] + rand.nextInt((int)range)+min; data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedS64 input, Random rand , long min , long max) { long range = max-min; long[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { long value = data[index] + rand.nextInt((int)range)+min; data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayS64 input, Random rand , double sigma , long lowerBound , long upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { long value = (input.data[index] ) + (long)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedS64 input, Random rand , double sigma , long lowerBound , long upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { long value = (input.data[index]) + (long)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayF32 input, Random rand , float min , float max) { float range = max-min; float[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { float value = data[index] + rand.nextFloat()*range+min; data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedF32 input, Random rand , float min , float max) { float range = max-min; float[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { float value = data[index] + rand.nextFloat()*range+min; data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayF32 input, Random rand , double sigma , float lowerBound , float upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { float value = (input.data[index] ) + (float)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedF32 input, Random rand , double sigma , float lowerBound , float upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { float value = (input.data[index]) + (float)(rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(GrayF64 input, Random rand , double min , double max) { double range = max-min; double[] data = input.data; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { double value = data[index] + rand.nextDouble()*range+min; data[index++] = value; } } } /** * Adds uniform i.i.d noise to each pixel in the image. Noise range is min ≤ X < max. */ public static void addUniform(InterleavedF64 input, Random rand , double min , double max) { double range = max-min; double[] data = input.data; int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { double value = data[index] + rand.nextDouble()*range+min; data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(GrayF64 input, Random rand , double sigma , double lowerBound , double upperBound ) { for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); for (int x = 0; x < input.width; x++) { double value = (input.data[index] ) + (rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } /** * Adds Gaussian/normal i.i.d noise to each pixel in the image. If a value exceeds the specified * it will be set to the closest bound. * @param input Input image. Modified. * @param rand Random number generator. * @param sigma Distributions standard deviation. * @param lowerBound Allowed lower bound * @param upperBound Allowed upper bound */ public static void addGaussian(InterleavedF64 input, Random rand , double sigma , double lowerBound , double upperBound ) { int length = input.width*input.numBands; for (int y = 0; y < input.height; y++) { int index = input.getStartIndex() + y * input.getStride(); int indexEnd = index+length; while( index < indexEnd ) { double value = (input.data[index]) + (rand.nextGaussian()*sigma); if( value < lowerBound ) value = lowerBound; if( value > upperBound ) value = upperBound; input.data[index++] = value; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy