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

boofcv.alg.misc.impl.ImplImageMiscOps_MT Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

The newest version!
/*
 * Copyright (c) 2023, 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.impl;

import boofcv.concurrency.BoofConcurrency;

import boofcv.alg.misc.ImageMiscOps;
import boofcv.misc.BoofLambdas;
import boofcv.misc.BoofMiscOps;
import boofcv.struct.border.ImageBorder_F32;
import boofcv.struct.border.ImageBorder_F64;
import boofcv.struct.border.ImageBorder_S32;
import boofcv.struct.border.ImageBorder_S64;
import boofcv.struct.image.*;

import javax.annotation.Generated;
import java.util.Arrays;
import java.util.Random;

/**
 * Implementations of functions for {@link ImageMiscOps}
 *
 *
 * 

DO NOT MODIFY. Automatically generated code created by GenerateImplImageMiscOps

* * @author Peter Abeles */ @Generated("boofcv.alg.misc.impl.ImplImageMiscOps") public class ImplImageMiscOps_MT { public static > void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, T input, ImageBorder_S32 border, GrayI8 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = (byte)border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayI8 input, int value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, (byte)value); }); } public static void maskFill( GrayI8 image, GrayU8 mask, int maskTarget, int value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = (byte)value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedI8 input, int[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedI8 input, int band, int value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayI8 input, int band, InterleavedI8 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedI8 input, int band, GrayI8 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayI8 input, int value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayI8 input, int value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = (byte)value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = (byte)value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = (byte)value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = (byte)value; srcIdx += input.stride; } } } public static void fillRectangle( GrayI8 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, (byte)value); }); } public static void fillRectangle( InterleavedI8 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, (byte)value); }); } public static void fillUniform( GrayI8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = (byte)(rand.nextInt(range) + min); } } } public static void fillUniform( InterleavedI8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = (byte)(rand.nextInt(range) + min); } } } public static void fillGaussian( GrayI8 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { byte[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (int)(rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = (byte)value; } } } public static void fillGaussian( InterleavedI8 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { byte[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayI8 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (byte)tmp; } }); } public static void flipHorizontal( GrayI8 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (byte)tmp; } }); } public static void transpose( GrayI8 input, GrayI8 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedI8 input, InterleavedI8 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayI8 input, GrayI8 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedI8 input, InterleavedI8 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayI8 input, GrayI8 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedI8 input, InterleavedI8 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static > void growBorder( T src, ImageBorder_S32 border, int borderX0, int borderY0, int borderX1, int borderY1, T dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = (byte)border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = (byte)border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = (byte)border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = (byte)border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayI8 input, BoofLambdas.Match_I8 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static > void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, T input, ImageBorder_S32 border, GrayI16 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = (short)border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayI16 input, int value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, (short)value); }); } public static void maskFill( GrayI16 image, GrayU8 mask, int maskTarget, int value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = (short)value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedI16 input, int[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedI16 input, int band, int value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayI16 input, int band, InterleavedI16 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedI16 input, int band, GrayI16 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayI16 input, int value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayI16 input, int value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = (short)value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = (short)value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = (short)value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = (short)value; srcIdx += input.stride; } } } public static void fillRectangle( GrayI16 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, (short)value); }); } public static void fillRectangle( InterleavedI16 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, (short)value); }); } public static void fillUniform( GrayI16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = (short)(rand.nextInt(range) + min); } } } public static void fillUniform( InterleavedI16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = (short)(rand.nextInt(range) + min); } } } public static void fillGaussian( GrayI16 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { short[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (int)(rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = (short)value; } } } public static void fillGaussian( InterleavedI16 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { short[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayI16 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (short)tmp; } }); } public static void flipHorizontal( GrayI16 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (short)tmp; } }); } public static void transpose( GrayI16 input, GrayI16 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedI16 input, InterleavedI16 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayI16 input, GrayI16 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedI16 input, InterleavedI16 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayI16 input, GrayI16 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedI16 input, InterleavedI16 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static > void growBorder( T src, ImageBorder_S32 border, int borderX0, int borderY0, int borderX1, int borderY1, T dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = (short)border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = (short)border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = (short)border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = (short)border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayI16 input, BoofLambdas.Match_I16 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, GrayS32 input, ImageBorder_S32 border, GrayS32 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayS32 input, int value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, value); }); } public static void maskFill( GrayS32 image, GrayU8 mask, int maskTarget, int value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedS32 input, int[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedS32 input, int band, int value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayS32 input, int band, InterleavedS32 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedS32 input, int band, GrayS32 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayS32 input, int value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayS32 input, int value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } } public static void fillRectangle( GrayS32 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, value); }); } public static void fillRectangle( InterleavedS32 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, value); }); } public static void fillUniform( GrayS32 image, Random rand, int min, int max ) { int range = max - min; int[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = rand.nextInt((int)range) + min; } } } public static void fillUniform( InterleavedS32 image, Random rand, int min, int max ) { int range = max - min; int[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = rand.nextInt((int)range) + min; } } } public static void fillGaussian( GrayS32 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { int[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (int)(rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = value; } } } public static void fillGaussian( InterleavedS32 image, Random rand, double mean, double sigma, int lowerBound, int upperBound ) { int[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayS32 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (int)tmp; } }); } public static void flipHorizontal( GrayS32 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { int tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (int)tmp; } }); } public static void transpose( GrayS32 input, GrayS32 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedS32 input, InterleavedS32 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayS32 input, GrayS32 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedS32 input, InterleavedS32 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayS32 input, GrayS32 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedS32 input, InterleavedS32 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static void growBorder( GrayS32 src, ImageBorder_S32 border, int borderX0, int borderY0, int borderX1, int borderY1, GrayS32 dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayS32 input, BoofLambdas.Match_S32 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, GrayS64 input, ImageBorder_S64 border, GrayS64 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayS64 input, long value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, value); }); } public static void maskFill( GrayS64 image, GrayU8 mask, int maskTarget, long value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedS64 input, long[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedS64 input, int band, long value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayS64 input, int band, InterleavedS64 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedS64 input, int band, GrayS64 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayS64 input, long value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayS64 input, long value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } } public static void fillRectangle( GrayS64 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, value); }); } public static void fillRectangle( InterleavedS64 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, value); }); } public static void fillUniform( GrayS64 image, Random rand, long min, long max ) { long range = max - min; long[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = (long)(rand.nextDouble()*0.9999*range) + min; } } } public static void fillUniform( InterleavedS64 image, Random rand, long min, long max ) { long range = max - min; long[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = (long)(rand.nextDouble()*0.9999*range) + min; } } } public static void fillGaussian( GrayS64 image, Random rand, double mean, double sigma, long lowerBound, long upperBound ) { long[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { long value = (long)(rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = value; } } } public static void fillGaussian( InterleavedS64 image, Random rand, double mean, double sigma, long lowerBound, long upperBound ) { long[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayS64 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { long tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (long)tmp; } }); } public static void flipHorizontal( GrayS64 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { long tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (long)tmp; } }); } public static void transpose( GrayS64 input, GrayS64 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedS64 input, InterleavedS64 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayS64 input, GrayS64 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedS64 input, InterleavedS64 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayS64 input, GrayS64 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedS64 input, InterleavedS64 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static void growBorder( GrayS64 src, ImageBorder_S64 border, int borderX0, int borderY0, int borderX1, int borderY1, GrayS64 dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayS64 input, BoofLambdas.Match_S64 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, GrayF32 input, ImageBorder_F32 border, GrayF32 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayF32 input, float value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, value); }); } public static void maskFill( GrayF32 image, GrayU8 mask, int maskTarget, float value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedF32 input, float[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedF32 input, int band, float value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayF32 input, int band, InterleavedF32 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedF32 input, int band, GrayF32 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayF32 input, float value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayF32 input, float value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } } public static void fillRectangle( GrayF32 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, value); }); } public static void fillRectangle( InterleavedF32 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, value); }); } public static void fillUniform( GrayF32 image, Random rand, float min, float max ) { float range = max - min; float[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = rand.nextFloat()*range + min; } } } public static void fillUniform( InterleavedF32 image, Random rand, float min, float max ) { float range = max - min; float[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = rand.nextFloat()*range + min; } } } public static void fillGaussian( GrayF32 image, Random rand, double mean, double sigma, float lowerBound, float upperBound ) { float[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { float value = (float)(rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = value; } } } public static void fillGaussian( InterleavedF32 image, Random rand, double mean, double sigma, float lowerBound, float upperBound ) { float[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayF32 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { float tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (float)tmp; } }); } public static void flipHorizontal( GrayF32 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { float tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (float)tmp; } }); } public static void transpose( GrayF32 input, GrayF32 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedF32 input, InterleavedF32 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayF32 input, GrayF32 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedF32 input, InterleavedF32 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayF32 input, GrayF32 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedF32 input, InterleavedF32 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static void growBorder( GrayF32 src, ImageBorder_F32 border, int borderX0, int borderY0, int borderX1, int borderY1, GrayF32 dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayF32 input, BoofLambdas.Match_F32 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static void copy( int srcX, int srcY, int dstX, int dstY, int width, int height, GrayF64 input, ImageBorder_F64 border, GrayF64 output ) { if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image. w=" + output.width + " < " + (dstX + width) + " or y=" + output.height + " < " + (dstY + height)); // Check to see if it's entirely contained inside the input image if (srcX >= 0 && srcX + width <= input.width && srcY >= 0 && srcY + height <= input.height) { BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } else { // If any part is outside use the border. This isn't terribly efficient. A better approach is to // handle all the possible outside regions independently. That code is significantly more complex so I'm // punting it for a future person to write since this is good enough as it. border.setImage(input); BoofConcurrency.loopFor(0, height, y->{ int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; for (int x = 0; x < width; x++) { output.data[indexDst++] = border.get(srcX + x, srcY + y); } }); } } 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 in the input image"); if (output.width < dstX + width || output.height < dstY + height) throw new IllegalArgumentException("Copy region must be contained in the output image"); BoofConcurrency.loopFor(0, height, y->{ int indexSrc = input.startIndex + (srcY + y)*input.stride + srcX; int indexDst = output.startIndex + (dstY + y)*output.stride + dstX; System.arraycopy(input.data, indexSrc, output.data, indexDst, width); }); } 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; BoofConcurrency.loopFor(0, 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); }); } public static void fill( GrayF64 input, double value ) { BoofConcurrency.loopFor(0, input.height, y->{ int index = input.getStartIndex() + y*input.getStride(); Arrays.fill(input.data, index, index + input.width, value); }); } public static void maskFill( GrayF64 image, GrayU8 mask, int maskTarget, double value ) { BoofMiscOps.checkEq(image.width, mask.width); BoofMiscOps.checkEq(image.height, mask.height); BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + image.width; int indexMask = mask.startIndex + y*image.stride; while (index < indexEnd) { if (mask.data[indexMask] == maskTarget) { image.data[index] = value; } index++; indexMask++; } }); } 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); } } public static void fill( InterleavedF64 input, double[] values ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } } }); } public static void fillBand( InterleavedF64 input, int band, double value ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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; } }); } public static void insertBand( GrayF64 input, int band, InterleavedF64 output ) { final int numBands = output.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void extractBand( InterleavedF64 input, int band, GrayF64 output ) { final int numBands = input.numBands; BoofConcurrency.loopFor(0, 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]; } }); } public static void fillBorder( GrayF64 input, double value, int radius ) { // top and bottom BoofConcurrency.loopFor(0,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; BoofConcurrency.loopFor(0,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; } }); } public static void fillBorder( GrayF64 input, double value, int borderX0, int borderY0, int borderX1, int borderY1 ) { // top and bottom for (int y = 0; y < borderY0; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } for (int y = input.height - borderY1; y < input.height; y++) { int srcIdx = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { input.data[srcIdx++] = value; } } // left and right int h = input.height - borderY1; for (int x = 0; x < borderX0; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } for (int x = input.width - borderX1; x < input.width; x++) { int srcIdx = input.startIndex + borderY0*input.stride + x; for (int y = borderY0; y < h; y++) { input.data[srcIdx] = value; srcIdx += input.stride; } } } public static void fillRectangle( GrayF64 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; final int _x1 = x1; BoofConcurrency.loopFor(y0, y1 , y->{ int index = image.startIndex + y*image.stride + _x0; Arrays.fill(image.data, index, index + _x1 - _x0, value); }); } public static void fillRectangle( InterleavedF64 image, 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 > image.width) x1 = image.width; if (y0 < 0) y0 = 0; if (y1 > image.height) y1 = image.height; final int _x0 = x0; int length = (x1 - x0)*image.numBands; BoofConcurrency.loopFor(y0, y1, y->{ int index = image.startIndex + y*image.stride + _x0*image.numBands; Arrays.fill(image.data, index, index + length, value); }); } public static void fillUniform( GrayF64 image, Random rand, double min, double max ) { double range = max - min; double[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { data[index++] = rand.nextDouble()*range + min; } } } public static void fillUniform( InterleavedF64 image, Random rand, double min, double max ) { double range = max - min; double[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int end = index + image.width*image.numBands; for (; index < end; index++) { data[index] = rand.nextDouble()*range + min; } } } public static void fillGaussian( GrayF64 image, Random rand, double mean, double sigma, double lowerBound, double upperBound ) { double[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { double value = (rand.nextGaussian()*sigma + mean); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; data[index++] = value; } } } public static void fillGaussian( InterleavedF64 image, Random rand, double mean, double sigma, double lowerBound, double upperBound ) { double[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void flipVertical( GrayF64 image ) { int h2 = image.height/2; BoofConcurrency.loopFor(0, h2, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = image.getStartIndex() + (image.height - y - 1)*image.getStride(); int end = index1 + image.width; while (index1 < end) { double tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2++] = (double)tmp; } }); } public static void flipHorizontal( GrayF64 image ) { int w2 = image.width/2; BoofConcurrency.loopFor(0, image.height, y->{ int index1 = image.getStartIndex() + y*image.getStride(); int index2 = index1 + image.width - 1; int end = index1 + w2; while (index1 < end) { double tmp = image.data[index1]; image.data[index1++] = image.data[index2]; image.data[index2--] = (double)tmp; } }); } public static void transpose( GrayF64 input, GrayF64 output ) { output.reshape(input.height, input.width); BoofConcurrency.loopFor(0, input.height, y->{ int indexIn = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { output.unsafe_set(y, x, input.data[indexIn++]); } }); } public static void transpose( InterleavedF64 input, InterleavedF64 output ) { output.reshape(input.height, input.width, input.numBands); BoofConcurrency.loopFor(0, input.height, y->{ int indexSrc = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++) { int indexDst = output.getIndex(y, x); int end = indexSrc + input.numBands; while (indexSrc != end) { output.data[indexDst++] = input.data[indexSrc++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCW( GrayF64 input, GrayF64 output ) { output.reshape(input.height, input.width); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCW( InterleavedF64 input, InterleavedF64 output ) { output.reshape(input.height, input.width, input.numBands); int h = input.height - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } 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; BoofConcurrency.loopFor(0, 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; } }); } public static void rotateCCW( GrayF64 input, GrayF64 output ) { output.reshape(input.height, input.width); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]); } }); } public static void rotateCCW( InterleavedF64 input, InterleavedF64 output ) { output.reshape(input.height, input.width, input.numBands); int w = input.width - 1; BoofConcurrency.loopFor(0, 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++]; } } }); } public static void growBorder( GrayF64 src, ImageBorder_F64 border, int borderX0, int borderY0, int borderX1, int borderY1, GrayF64 dst ) { dst.reshape(src.width + borderX0 + borderX1, src.height + borderY0 + borderY1); border.setImage(src); // Copy src into the inner portion of dst ImageMiscOps.copy(0, 0, borderX0, borderY0, src.width, src.height, src, dst); // Top border for (int y = 0; y < borderY0; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } } // Bottom border for (int y = 0; y < borderY1; y++) { int idxDst = dst.startIndex + (dst.height - borderY1 + y)*dst.stride; for (int x = 0; x < dst.width; x++) { dst.data[idxDst++] = border.get(x - borderX0, src.height + y); } } // Left and right border for (int y = borderY0; y < dst.height - borderY1; y++) { int idxDst = dst.startIndex + y*dst.stride; for (int x = 0; x < borderX0; x++) { dst.data[idxDst++] = border.get(x - borderX0, y - borderY0); } idxDst = dst.startIndex + y*dst.stride + src.width + borderX0; for (int x = 0; x < borderX1; x++) { dst.data[idxDst++] = border.get(src.width + x, y - borderY0); } } } public static void findAndProcess( GrayF64 input, BoofLambdas.Match_F64 finder, BoofLambdas.ProcessIIB process ) { for (int y = 0; y < input.height; y++) { int index = input.startIndex + y*input.stride; for (int x = 0; x < input.width; x++, index++) { if (finder.process(input.data[index])) { if (!process.process(x, y)) return; } } } } public static void filter( GrayU8 image, BoofLambdas.FilterPixel_S32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = (byte)op.filter(index - indexStart, y, image.data[index] & 0xFF); index++; } }); } public static void addUniform( GrayU8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.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; } } } public static void addUniform( InterleavedU8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void addGaussian( GrayU8 image, Random rand, double sigma, int lowerBound, int upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (image.data[index] & 0xFF) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (byte)value; } } } public static void addGaussian( InterleavedU8 image, Random rand, double sigma, int lowerBound, int upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (image.data[index] & 0xFF) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (byte)value; } } } public static void filter( GrayS8 image, BoofLambdas.FilterPixel_S32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = (byte)op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayS8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (data[index]) + rand.nextInt(range) + min; if (value < -128) value = -128; if (value > 127) value = 127; data[index++] = (byte)value; } } } public static void addUniform( InterleavedS8 image, Random rand, int min, int max ) { int range = max - min; byte[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void addGaussian( GrayS8 image, Random rand, double sigma, int lowerBound, int upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (byte)value; } } } public static void addGaussian( InterleavedS8 image, Random rand, double sigma, int lowerBound, int upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (byte)value; } } } public static void filter( GrayU16 image, BoofLambdas.FilterPixel_S32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = (short)op.filter(index - indexStart, y, image.data[index] & 0xFFFF); index++; } }); } public static void addUniform( GrayU16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.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; } } } public static void addUniform( InterleavedU16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void addGaussian( GrayU16 image, Random rand, double sigma, int lowerBound, int upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (image.data[index] & 0xFFFF) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (short)value; } } } public static void addGaussian( InterleavedU16 image, Random rand, double sigma, int lowerBound, int upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (image.data[index] & 0xFFFF) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (short)value; } } } public static void filter( GrayS16 image, BoofLambdas.FilterPixel_S32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = (short)op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayS16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (data[index]) + rand.nextInt(range) + min; if (value < -32768) value = -32768; if (value > 32767) value = 32767; data[index++] = (short)value; } } } public static void addUniform( InterleavedS16 image, Random rand, int min, int max ) { int range = max - min; short[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.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; } } } public static void addGaussian( GrayS16 image, Random rand, double sigma, int lowerBound, int upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (short)value; } } } public static void addGaussian( InterleavedS16 image, Random rand, double sigma, int lowerBound, int upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = (short)value; } } } public static void filter( GrayS32 image, BoofLambdas.FilterPixel_S32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayS32 image, Random rand, int min, int max ) { int range = max - min; int[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (data[index]) + rand.nextInt(range) + min; data[index++] = value; } } } public static void addUniform( InterleavedS32 image, Random rand, int min, int max ) { int range = max - min; int[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (data[index]) + rand.nextInt(range) + min; data[index++] = value; } } } public static void addGaussian( GrayS32 image, Random rand, double sigma, int lowerBound, int upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void addGaussian( InterleavedS32 image, Random rand, double sigma, int lowerBound, int upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { int value = (image.data[index]) + (int)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void filter( GrayS64 image, BoofLambdas.FilterPixel_S64 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayS64 image, Random rand, long min, long max ) { long range = max - min; long[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { long value = data[index] + rand.nextInt((int)range) + min; data[index++] = value; } } } public static void addUniform( InterleavedS64 image, Random rand, long min, long max ) { long range = max - min; long[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { long value = data[index] + rand.nextInt((int)range) + min; data[index++] = value; } } } public static void addGaussian( GrayS64 image, Random rand, double sigma, long lowerBound, long upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { long value = (image.data[index]) + (long)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void addGaussian( InterleavedS64 image, Random rand, double sigma, long lowerBound, long upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { long value = (image.data[index]) + (long)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void filter( GrayF32 image, BoofLambdas.FilterPixel_F32 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayF32 image, Random rand, float min, float max ) { float range = max - min; float[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { float value = data[index] + rand.nextFloat()*range + min; data[index++] = value; } } } public static void addUniform( InterleavedF32 image, Random rand, float min, float max ) { float range = max - min; float[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { float value = data[index] + rand.nextFloat()*range + min; data[index++] = value; } } } public static void addGaussian( GrayF32 image, Random rand, double sigma, float lowerBound, float upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { float value = (image.data[index]) + (float)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void addGaussian( InterleavedF32 image, Random rand, double sigma, float lowerBound, float upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { float value = (image.data[index]) + (float)(rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void filter( GrayF64 image, BoofLambdas.FilterPixel_F64 op ) { BoofConcurrency.loopFor(0, image.height, y->{ int index = image.getStartIndex() + y*image.getStride(); int indexStart = index; int indexEnd = index + image.width; while (index < indexEnd) { image.data[index] = op.filter(index - indexStart, y, image.data[index]); index++; } }); } public static void addUniform( GrayF64 image, Random rand, double min, double max ) { double range = max - min; double[] data = image.data; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { double value = data[index] + rand.nextDouble()*range + min; data[index++] = value; } } } public static void addUniform( InterleavedF64 image, Random rand, double min, double max ) { double range = max - min; double[] data = image.data; int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { double value = data[index] + rand.nextDouble()*range + min; data[index++] = value; } } } public static void addGaussian( GrayF64 image, Random rand, double sigma, double lowerBound, double upperBound ) { for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); for (int x = 0; x < image.width; x++) { double value = (image.data[index]) + (rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } public static void addGaussian( InterleavedF64 image, Random rand, double sigma, double lowerBound, double upperBound ) { int length = image.width*image.numBands; for (int y = 0; y < image.height; y++) { int index = image.getStartIndex() + y*image.getStride(); int indexEnd = index + length; while (index < indexEnd) { double value = (image.data[index]) + (rand.nextGaussian()*sigma); if (value < lowerBound) value = lowerBound; if (value > upperBound) value = upperBound; image.data[index++] = value; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy