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 boofcv-ip Show documentation
Show all versions of boofcv-ip Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2011-2018, 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.Arrays;
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++];
}
}
}
/**
* 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 ,
InterleavedI8 input , InterleavedI8 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, (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;
Arrays.fill(input.data,index,end, (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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedI8 input, int band , GrayI8 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedI8 input , InterleavedI8 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedI8 input , InterleavedI8 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++];
}
}
}
/**
* 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 ,
InterleavedI16 input , InterleavedI16 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, (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;
Arrays.fill(input.data,index,end, (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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedI16 input, int band , GrayI16 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedI16 input , InterleavedI16 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedI16 input , InterleavedI16 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++];
}
}
}
/**
* 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 ,
InterleavedS32 input , InterleavedS32 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, 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;
Arrays.fill(input.data,index,end, 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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedS32 input, int band , GrayS32 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedS32 input , InterleavedS32 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedS32 input , InterleavedS32 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++];
}
}
}
/**
* 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 ,
InterleavedS64 input , InterleavedS64 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, 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;
Arrays.fill(input.data,index,end, 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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedS64 input, int band , GrayS64 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedS64 input , InterleavedS64 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedS64 input , InterleavedS64 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++];
}
}
}
/**
* 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 ,
InterleavedF32 input , InterleavedF32 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, 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;
Arrays.fill(input.data,index,end, 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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedF32 input, int band , GrayF32 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedF32 input , InterleavedF32 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedF32 input , InterleavedF32 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++];
}
}
}
/**
* 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 ,
InterleavedF64 input , InterleavedF64 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");
if( output.numBands != input.numBands )
throw new IllegalArgumentException("Number of bands must match. "+input.numBands+" != "+output.numBands);
final int numBands = input.numBands;
for (int y = 0; y < height; y++) {
int indexSrc = input.startIndex + (srcY + y) * input.stride + srcX*numBands;
int indexDst = output.startIndex + (dstY + y) * output.stride + dstX*numBands;
System.arraycopy(input.data,indexSrc,output.data,indexDst,width*numBands);
}
}
/**
* 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();
Arrays.fill(input.data,index,index+input.width, 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;
Arrays.fill(input.data,index,end, 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 a multi-band image overwriting the original band
*
* @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];
}
}
}
/**
* Extracts a single band from a multi-band image
*
* @param input Multi-band image
* @param band which bad is to be extracted
* @param output The single band image
*/
public static void extractBand( InterleavedF64 input, int band , GrayF64 output) {
final int numBands = input.numBands;
for (int y = 0; y < input.height; y++) {
int indexIn = input.getStartIndex() + y * input.getStride() + band;
int indexOut = output.getStartIndex() + y * output.getStride();
int end = indexOut + output.width;
for (; indexOut < end; indexIn += numBands , indexOut++ ) {
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++]);
}
}
}
/**
* Rotates the image 90 degrees in the clockwise direction.
*/
public static void rotateCW( InterleavedF64 input , InterleavedF64 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int h = input.height-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(h-y,x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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++]);
}
}
}
/**
* Rotates the image 90 degrees in the counter-clockwise direction.
*/
public static void rotateCCW( InterleavedF64 input , InterleavedF64 output ) {
if( input.width != output.height || input.height != output.width || input.numBands != output.numBands )
throw new IllegalArgumentException("Incompatible shapes");
int w = input.width-1;
for( int y = 0; y < input.height; y++ ) {
int indexSrc = input.startIndex + y*input.stride;
for (int x = 0; x < input.width; x++) {
int indexDst = output.getIndex(y,w-x);
int end = indexSrc + input.numBands;
while( indexSrc != end ) {
output.data[indexDst++] = input.data[indexSrc++];
}
}
}
}
/**
* 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;
}
}
}
}