如何在JavaScript矩阵运算中实现最近邻插值?

约翰·杜

以下代码使用GPU.js(WebGL的包装器),通过简单地编写JS函数,可以轻松地使用WebGL运行矩阵运算,我在画布上渲染图像,但我想调整其大小。读过有关最近邻插值的信息,但是我对如何实现它感到困惑。我已经设置了调整大小内核,剩下要做的就是内插逻辑。

笔记:

  • 在内核函数中this.thread.x当前索引在this.thread.y,和中可用this.thread.z,具体取决于内核正在计算的矩阵的维数。

  • 您会注意到画布的尺寸很奇怪。这是与WebGL纹理处理相关的GPU.js的“功能”(我认为他们计划稍后进行修复)。

  • 编辑:取得了进步,但还不够完善:http : //jsfiddle.net/0dusaytk/59/

const canvas1 = document.createElement("canvas");
const context1 = canvas1.getContext("webgl2");
document.body.appendChild(canvas1);
const canvas2 = document.createElement("canvas");
const context2 = canvas2.getContext("2d");
const gpu = new GPU({
  canvas: canvas1,
  webGl: context1
});

const image = new Image();
image.crossOrigin = "Anonymous";
image.src = "https://i.imgur.com/sl2J6jm.jpg";
image.onload = function() {
	const length = 4 * image.height * image.width;
  const gpuTexturize = gpu
    .createKernel(function(sprite) {
      return sprite[this.thread.x];
    })
    .setOutput([length])
    .setOutputToTexture(true);
  const gpuResize = gpu
    .createKernel(function(sprite, w, h) {
      return sprite[this.thread.x];
    })
    .setOutput([length])
    .setOutputToTexture(true);
  const gpuRender = gpu
    .createKernel(function(sprite, w, h) {
    	var index = this.thread.x * 4 + (h - this.thread.y) * w * 4;
      var r = sprite[index];
      var g = sprite[index + 1];
      var b = sprite[index + 2];
      this.color(r / 255, g / 255, b / 255);
    })
    .setOutput([image.width, image.height])
    .setGraphical(true);
  canvas2.width = image.width;
  canvas2.height = image.height;
  context2.drawImage(image, 0, 0);
  const imgData = context2.getImageData(
    0,
    0,
    canvas2.width,
    canvas2.height
  );
  
  const texture = gpuTexturize(imgData.data);
  const resized = gpuResize(texture, 100, 100);
  gpuRender(resized, image.width, image.height);
};
body {
  background-color: #3a4659;
}

canvas {
  background-color: #bcc8db;
}
<script src="https://rawgit.com/gpujs/gpu.js/develop/bin/gpu.js"></script>

拉斐尔卡斯特罗库托

我将第二个画布添加了像素化渲染,以便将该实现与浏览器的CSS默认方法进行比较。

演示:https : //codepen.io/rafaelcastrocouto/pen/pOaaEd

const scale = 4;

// canvas1 will be handled by the gpu
const canvas1 = document.createElement("canvas");
canvas1.className = 'c1';
const context1 = canvas1.getContext("webgl2");
const gpu = new GPU({
  canvas: canvas1,
  webGl: context1
});
document.body.appendChild(canvas1);

// canvas2 will render the image
const canvas2 = document.createElement("canvas");
canvas2.className = 'c2';
const context2 = canvas2.getContext("2d");
document.body.appendChild(canvas2);
canvas2.style.transform = 'scale('+scale+')';

// load the image
const image = new Image();
image.crossOrigin = "Anonymous";
image.src = "https://placeholdit.imgix.net/~text?txtsize=20&txtpad=1&bg=000&txtclr=fff&txt=64x32&w=64&h=32";

image.onload = function() {
  // render image to canvas2
  canvas2.width = image.width;
  canvas2.height = image.height;
  context2.drawImage(image, 0, 0);
  // scale imageData
  const imgData = context2.getImageData(0,0,image.width,image.height);
  const gpuRender = gpu
    .createKernel(function(sprite) {
      var x = floor(this.thread.x/this.constants.s) * 4;
      var y = floor(this.constants.h - this.thread.y/this.constants.s) * 4 * this.constants.w;
      var index = x + y;
      var r = sprite[ index ]/255;
      var g = sprite[index+1]/255;
      var b = sprite[index+2]/255;
      var a = sprite[index+3]/255;
      this.color(r, g, b, a);
    },{
      constants: {
        w: image.width,
        h: image.height,
        s: scale
      }
    })
    .setOutput([image.width*scale, image.height*scale])
    .setGraphical(true);
  gpuRender(imgData.data);
};
body {
  background-color: #3a4659;
}

canvas {
  background-color: #bcc8db;
  display: block;
  margin: 4em;
}
.c2 {
  image-rendering: pixelated;
  transform-origin: 0;
}
<script src="https://rawgit.com/gpujs/gpu.js/develop/bin/gpu.js"></script>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章