I am trying to execute a Median filter on an image in Java, but it is terribly slow. Firstly, if one of you knows about self-implementation, I could use it would be fantastic if you could tell me about it. I am implementing on Android trying to reproduce a small part of JAI.
In my method, I take every pixel, extract the values ββof R, G and B using
r = pixel >> 16 & 0xFF
Or similarly, find the median for the kernel and end with
pixel = a | r <<16 | g << 8 | b
Is there any way to capture bytes from int so that it is faster?
Yours faithfully,
Gavin
EDIT: complete code to help diagnose my poor performance on demand
For the actual source file, please go here where my implementation of medianFilter can be found.
width and height values ββfor size dest and are available as class member variables. Pixels are linearized into a one-dimensional array.
private void medianFilterSquare(int[] source, int[] dest, int rWidth, int rHeight, int radius) { // Source has been reflected into a border of size radius // This makes it radius * 2 pixels wider and taller than the dest int r,g,b; int destOffset, rOffset, kOffset; // The first offset into the source to calculate a median for // This corresponds to the first pixel in dest int rFirst = radius + (rWidth*radius); // We use a square kernel with the radius passed int neighbours = (radius+radius+1)*(radius+radius+1); int index; // Arrays to accumulate the values for median calculation int[] rs = new int[neighbours]; int[] gs = new int[neighbours]; int[] bs = new int[neighbours]; // Declaring outside the loop helps speed? I'm sure this is done for me // by the compiler int pixel; // Iterate over the destination pixels for(int x = 0; x < height; x++){ for(int y = 0; y < width; y++){ // Offset into destination destOffset = x + (y * width); // Offset into source with border size radius rOffset = destOffset + rFirst + (y * (radius *2)); index = 0; // Iterate over kernel for(int xk = -radius; xk < radius ; xk ++){ for(int yk = -radius; yk < radius ; yk ++){ kOffset = rOffset + (xk + (rWidth*yk)); pixel = source[kOffset]; // Color.red is equivalent to (pixel>>16) & 0xFF rs[index] = Color.red(pixel); gs[index] = Color.green(pixel); bs[index] = Color.blue(pixel); index++; } } r = medianFilter(rs); g = medianFilter(gs); b = medianFilter(bs); dest[destOffset] = Color.rgb(r, g, b); } } }
source share