Применение Edge Filter к видео с использованием Canvas в HTML5, но с задержкой в ​​видео.Есть ли лучший способ, чтобы я не получил отставание? - PullRequest
1 голос
/ 09 марта 2012

Я использую HTML5 Canvas и применяю Edge Filter с помощью пиксельных манипуляций. Но я получаю отставание в видео. Есть ли лучший способ добиться видео с краевым фильтром без задержки в видео?

Ниже приведен код JavaScript, который я использую с canvas и HTML 5 для применения эффекта: -

 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);
}

1 Ответ

1 голос
/ 18 мая 2012

Вместо свертки с двумерным ядром вы можете попробовать 1D свертку с подходом раздельной свертки.Это должно заметно увеличить скорость.

Объяснение того, как использовать отделимую свертку с использованием ядер Собеля, можно найти здесь .

Вам следует изменить код на что-то вроде:

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

И convolveFloat321DHorizontal/convolveFloat321DVertical методы аналогичны оригинальному методу convoluteFloat32, но они имеют 3 вложенных цикла вместо 4.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...