boofcv.alg.misc.ImageMiscOps Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ip Show documentation
Show all versions of ip Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* 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 - 2025 Weber Informatics LLC | Privacy Policy