如何通过p5.js中的噪声使图像失真

问题描述 投票:1回答:1

我正在尝试产生一个以源图像开头的函数,产生噪声,然后使用噪声使图像失真。我首先创建噪声,然后将其转换为矢量场,然后重新映射坐标,并以正确的坐标将像素拉出图像。最后,我将提取的像素重新组合为图像。

到目前为止,我的代码如下:

function distort(sourceImage){
  let vectorField = [];
  var amount = 100;
  var scale = 0.01;
  for (x = 0; x < sourceImage.width; x++){
    let row = [];
    for (y = 0; y < sourceImage.height; y++){
      let vector = createVector(amount*(noise(scale*x,scale*y)-0.5), 4*amount*(noise(100+scale*x,scale*y)-0.5))
      row.push(vector);
    }
    vectorField.push(row);
  }

  var result = [];
  sourceImage.loadPixels();
  for (i = 0; i < sourceImage.width; i++){ //sourceImage.width
    for (j = 0; j < sourceImage.height; j += 4){ //sourceImage.height
      var res = vectorField[i][j];
      //console.log(res);

      var ii = constrain(floor(i + res.x), 0, sourceImage.width - 1);
      var jj = constrain(floor(j + res.y), 0, sourceImage.height - 1);
      //console.log(ii, jj);

      result[i * sourceImage.width + j] = color(sourceImage.pixels[ii * sourceImage.width + jj], sourceImage.pixels[ii * sourceImage.width + jj + 1], sourceImage.pixels[ii * sourceImage.width + jj + 2], sourceImage.pixels[ii * sourceImage.width + jj + 3]);
    }
  }
  //console.log(result)
  //console.log(sourceImage.pixels[0 + sourceImage.width * 0])

  for (n=0; n<sourceImage.width; n++) {
    for(m=0; m<sourceImage.height; m++){
      index = (n * sourceImage.width + m) * 4;
      if (index >= 4194300){
        index = 4194300;
      }
      sourceImage.pixels[index] = red(result[index]);
      sourceImage.pixels[index + 1] = green(result[index]);
      sourceImage.pixels[index + 2] = blue(result[index]);
      sourceImage.pixels[index + 3] = alpha(result[index]);
    }
  }


  sourceImage.updatePixels();
  image(sourceImage, 0, 0, size, size);
}

除了结果,我在画布的顶部第4层得到了4个噪点。噪点尤其包括许多我不知道在源图像中的像素(即蓝色像素;我要变形的图像是红色和白色)。可以将噪声识别为已开始作为源图像,但是会失真并且具有上述伪像。

作为比较:

originalresults

javascript image-processing processing p5.js
1个回答
1
投票

您没有完全处理矢量场,必须从该场读取每个矢量。实际上,您只读取了向量的每个第4个元素

for (j = 0; j < sourceImage.height; j += 4)

for (j = 0; j < sourceImage.height; j++)

此外,源索引的计算是错误的。请注意,必须将行(jj)的控制变量乘以高度。数组中像素的索引必须乘以4,因为每个像素包含4个颜色通道:

ii * sourceImage.width + jj

(jj * sourceImage.width + ii) * 4

目标索引的计算也是错误的:

index = (n * sourceImage.width + m) * 4;

index = (m * sourceImage.width + n) * 4;

注意,result每个像素包含1个元素,byut sourceImage.pixels每个像素包含4个元素。因此,从结果中读取的索引与访问目标的索引是不同的:

let result_i = m * sourceImage.width + n;
let target_i = result_i * 4;

例如:

let result = [];
for (let j = 0; j < sourceImage.height; j++) {
    for (let i = 0; i < sourceImage.width; i++) {

      let res = vectorField[i][j];

      let ii = constrain(floor(i + res.x), 0, sourceImage.width - 1);
      let jj = constrain(floor(j + res.y), 0, sourceImage.height - 1);

      let source_i = (jj * sourceImage.width + ii) * 4;
      let col = color(
          sourceImage.pixels[source_i],
          sourceImage.pixels[source_i + 1],
          sourceImage.pixels[source_i + 2],
          sourceImage.pixels[source_i + 3]);

      result.push(col);
    }
}

for(let m = 0; m < sourceImage.height; m++) {
    for (let n = 0; n < sourceImage.width; n++) {

        let result_i = m * sourceImage.width + n;
        let target_i = result_i * 4;

        let col = result[result_i];
        sourceImage.pixels[target_i]     = red(col);
        sourceImage.pixels[target_i + 1] = green(col);
        sourceImage.pixels[target_i + 2] = blue(col);
        sourceImage.pixels[target_i + 3] = alpha(col);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.