Aplicando Edge Filter en video usando Canvas en HTML5 pero obteniendo retraso en el video. ¿Hay alguna forma mejor de no tener retrasos?

I am using HTML5 Canvas and applying Edge Filter by pixel manipulation. But I am getting lag in the video. Is there any better way to achieve video with edge filter without any lag in video?

Following is the JavaScript I am using with canvas and HTML 5 to apply the effect:-

 function sobel (px) {
    px = greyScale(px);
        var vertical = convoluteFloat32(px,
        [-1, -2, -1,
          0, 0, 0,
          1, 2, 1], false);
        var horizontal = convoluteFloat32(px,
        [-1, 0, 1,
         -2, 0, 2,
         -1, 0, 1], false);
        var id = createImageData(vertical.width, vertical.height);
        for (var i = 0; i < id.data.length; i += 4) {
            var v = Math.abs(vertical.data[i]);
            id.data[i] = v;
            var h = Math.abs(horizontal.data[i]);
            id.data[i + 1] = h
            id.data[i + 2] = (v + h) / 4;
            id.data[i + 3] = 255;
        }
        return id;
    }

 function convoluteFloat32 (pixels, weights, opaque) {
    var side = Math.round(Math.sqrt(weights.length));
    var halfSide = Math.floor(side / 2);

    var src = pixels.data;
    var sw = pixels.width;
    var sh = pixels.height;

    var w = sw;
    var h = sh;
    var output = {
        width: w, height: h, data: new Float32Array(w * h * 4)
    };
    var dst = output.data;

    var alphaFac = opaque ? 1 : 0;

    for (var y = 0; y < h; y++) {
        for (var x = 0; x < w; x++) {
            var sy = y;
            var sx = x;
            var dstOff = (y * w + x) * 4;
            var r = 0, g = 0, b = 0, a = 0;
            for (var cy = 0; cy < side; cy++) {
                for (var cx = 0; cx < side; cx++) {
                    var scy = Math.min(sh - 1, Math.max(0, sy + cy - halfSide));
                    var scx = Math.min(sw - 1, Math.max(0, sx + cx - halfSide));
                    var srcOff = (scy * sw + scx) * 4;
                    var wt = weights[cy * side + cx];
                    r += src[srcOff] * wt;
                    g += src[srcOff + 1] * wt;
                    b += src[srcOff + 2] * wt;
                    a += src[srcOff + 3] * wt;
                }
            }
            dst[dstOff] = r;
            dst[dstOff + 1] = g;
            dst[dstOff + 2] = b;
            dst[dstOff + 3] = a + alphaFac * (255 - a);
        }
    }
    return output;
}

function draw() {
    // First, draw it into the backing canvas
    backcontext.drawImage(video, 0, 0, video.width, video.height);

     // Grab the pixel data from the backing canvas
    var idata = backcontext.getImageData(0, 0, video.width, video.height);

    idata = sobel(idata);
    context.putImageData(idata, 0, 0);

    // Start over!
    setTimeout(draw, 50);
}

preguntado el 09 de marzo de 12 a las 15:03

1 Respuestas

Instead of convolution with a 2D kernel, you can try 1D convolution with the separable convolution approach. This should increase the speed noticeably.

An explanation on how to use separable convolution using Sobel kernels can be found aquí.

You should change your code to something like this:

function convoluteFloat32 (pixels, weights1DHorizontal, weights1DVertical, opaque){
    convolveFloat321DHorizontal(pixels, weights1DHorizontal, opaque);
    convolveFloat321DVertical(pixels, weights1DVertical, opaque);
}

Y también debes convolveFloat321DHorizontal/convolveFloat321DVertical methods are just like the original convoluteFloat32 method, but they have 3 nested for loops instead of 4.

contestado el 18 de mayo de 12 a las 10:05

Thanks for replying... Actually can you send me the code for the above convoluteFloat32 method in 1D convolution . I am trying to understand the concept of 1D convolution but since i have just begun to work on this i am not getting how to transform the above method to 1D convolution. It would be of great help. Thanks - balraj singh

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.