javascriptgraphicscomputer-vision

Bilateral filter algorithm


I'm trying to implement a simple bilateral filter in javascript. This is what I've come up with so far:

// For each pixel
for (var y = kernelSize; y < height-kernelSize; y++) {
    for (var x = kernelSize; x < width-kernelSize; x++) {
        var pixel = (y*width + x)*4;
        var sumWeight = 0;
        outputData[pixel] = 0;
        outputData[pixel+1] = 0;
        outputData[pixel+2] = 0;
        outputData[pixel+3] = inputData[pixel+3];

        // For each neighbouring pixel
        for(var i=-kernelSize; i<=kernelSize; i++) {
            for(var j=-kernelSize; j<=kernelSize; j++) {
                var kernel = ((y+i)*width+x+j)*4;
                var dist = Math.sqrt(i*i+j*j);
                var colourDist = Math.sqrt((inputData[kernel]-inputData[pixel])*(inputData[kernel]-inputData[pixel])+
                        (inputData[kernel+1]-inputData[pixel+1])*(inputData[kernel+1]-inputData[pixel+1])+
                        (inputData[kernel+2]-inputData[pixel+2])*(inputData[kernel+2]-inputData[pixel+2]));
                var curWeight = 1/(Math.exp(dist*dist/72)*Math.exp(colourDist*colourDist*8));
                sumWeight += curWeight;
                outputData[pixel] += curWeight*inputData[pixel];
                outputData[pixel+1] += curWeight*inputData[pixel+1];
                outputData[pixel+2] += curWeight*inputData[pixel+2];
            }
        }

        outputData[pixel] /= sumWeight;
        outputData[pixel+1] /= sumWeight;
        outputData[pixel+2] /= sumWeight;
    }
}

inputData is from a html5 canvas object and is in the form of rgba. My images are either coming up with no changes or with patches of black around edges depending on how i change this formula:

var curWeight = 1/(Math.exp(dist*dist/72)*Math.exp(colourDist*colourDist*8));

Unfortunately I'm still new to html/javascript and image vision algorithms and my search have come up with no answers. My guess is there is something wrong with the way curWeight is calculated. What am I doing wrong here? Should I have converted the input image to CIElab/hsv first?


Solution

  • I've found the error in the code. The problem was I was adding each pixel to itself instead of its surrounding neighbours. I'll leave the corrected code here in case anyone needs a bilateral filter algorithm.

    outputData[pixel] += curWeight*inputData[kernel];
    outputData[pixel+1] += curWeight*inputData[kernel+1];
    outputData[pixel+2] += curWeight*inputData[kernel+2];