一尘不染

如何更好地获得fisheye算法?

javascript

我想做简单的fisheye算法,让它看起来像屏幕镜头。这是画布的简单javascript代码。

    var frame = context.getImageData(0, 0, canvas.width, canvas.height);
    var source = new Uint8ClampedArray(frame.data);

    context2.clearRect(0, 0, canvas.width, canvas.height);
    const SIZE = 80;
    for (var i = 0; i < frame.data.length; i += 4) {
        var x = (i / 4) % frame.width;
        var y = Math.floor(i / 4 / frame.width);

        let mouseX = frame.width / 2;
        let mouseY = frame.height / 2;

        var dx = mouseX - x;
        var dy = mouseY - y;
        var dist = Math.sqrt(dx * dx + dy * dy);

        var i2 = i;
        if (dist <= SIZE) {
            var x2 = Math.round(
                mouseX - dx * Math.sin(((dist / SIZE) * Math.PI) / 2)
            );
            var y2 = Math.round(
                mouseY - dy * Math.sin(((dist / SIZE) * Math.PI) / 2)
            );
            var i2 = (y2 * frame.width + x2) * 4;
        }
        frame.data[i] = source[i2];
        frame.data[i + 1] = source[i2 + 1];
        frame.data[i + 2] = source[i2 + 2];
        frame.data[i + 3] = source[i2 + 3];
    }
    context2.putImageData(frame, 0, 0);

在此处输入图像描述


阅读 93

收藏
2022-07-26

共1个答案

一尘不染

您看到的是被镜头效果放大的源像素。它们具有硬边,因为您照此复制像素值,所以保留了这些边。您正在做的事情被称为“最近邻插值”。

您将通过“双线性插值”获得更平滑的结果。

  • 将 x2, y2 计算为浮点数,不要四舍五入;
  • 使用整数部分并获取 x2、y2 周围的四个像素;
  • 使用小数部分计算四个像素的加权平均值。

公式是

(1-v) ((1-u) V00 + u V10) + v ((1-u) V01 + u V11)

其中 u、v 是小数部分,V 是像素值(对 R、G 和 B 重复)。

2022-07-26