In MATLAB there is an option for doing 2D convolutions, that you can use it so you can have each area where convolution happened. for example if you have done a 3x3 convolution you can say that save the result of each 3x3 window and use it. the command is like this:
X = conv2(A,B,'same');
the 'same' keyword is going to return the central part of the convolution of the same size as A.
I want to know is there anyway were I can do something like this with renderscript in Android? I will put a picture from MATLAB documentation so you can get a better understanding of what I mean. again the picture is from MATLAB documentation which is free.
You can use the Script.LaunchOptions
class.
Using this class you can set limits of execution of kernels.
Example: you want to run a kernel on a "rectangle" of your data (so, in 2 dimensions), starting at x-index (0-based, inclusive) 3
and ending at the x-index (exclusive) 8
and, on the y side the limits are 11
and 22
:
Script.LaunchOptions launchOptions;
launchOptions = new Script.LaunchOptions();
launchOptions.setX(3, 8);
launchOptions.setY(11, 22);
// Kernel run
myScript.forEach_myKernelName(inAlloc, outAlloc, launchOptions);
Example: you want to apply a kernel over an image, with a 3-pixel-wide border (example directly taken from the FASTExample sample project):
Script.LaunchOptions fastLaunchOptions;
fastLaunchOptions = new Script.LaunchOptions();
fastLaunchOptions.setX(3, inputImageSize.width - 3);
fastLaunchOptions.setY(3, inputImageSize.height - 3);
// ...
scriptCFast.forEach_fastOptimized(
grayAllocation, fastKpAllocation, fastLaunchOptions);
Example: you want to apply a ScriptIntrinsicConvolve3x3
kernel over a restricted range:
// Define the convolution
ScriptIntrinsicConvolve3x3 convolve3x3 =
ScriptIntrinsicConvolve3x3.create(mRS, Element.RGBA_8888(mRS));
// Some coefficients
float[] coefficients = {
0.7f, 0, 0.5f,
0, 1.0f, 0,
0.5f, 0, 1.0f
};
convolve3x3.setCoefficients(coefficients);
// Execute the allocation with limits
Script.LaunchOptions launchOptions;
launchOptions = new Script.LaunchOptions();
launchOptions.setX(3, 8);
launchOptions.setY(11, 22);
convolve3x3.setInput(inputAllocation);
convolve3x3.forEach(convolvedAllocation, launchOptions);
Note: this process just executes a kernel over a certain range, but it is NOT going to create a new, smaller allocation. So, after having executed a kernel over certain limits, you should copy the result of it using a copy kernel, like the following one:
// Store the input allocation
rs_allocation inputAllocation;
// Offset indices, which define the start point for
// the copy in the input allocation.
int inputOffsetX;
int inputOffsetY;
uchar4 __attribute__((kernel)) copyAllocation(int x, int y) {
return rsGetElementAt_uchar4(
inputAllocation, x + inputOffsetX, y + inputOffsetY);
}
Invoked with:
scriptC_main.set_inputAllocation(convolvedAllocation);
scriptC_main.set_inputOffsetX(offsetX);
scriptC_main.set_inputOffsetY(offsetY);
scriptC_main.forEach_copyAllocation(outputAllocation);
Edit: I specifically created an example for this case, where you can see the following process:
Reference: RenderScript: parallel computing on Android, the easy way