如何通过 p5.js 中的噪声扭曲图像
How to distort an image by noise in p5.js
我正在尝试生成一个函数,该函数从源图像开始,生成噪声,然后使用噪声扭曲图像。
我从创建噪声开始,并将其转换为矢量场,然后我重新映射坐标,并在正确的坐标处将像素从图像中拉出。
最后,我将提取的像素重新组合成图像。
目前我的代码如下:
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);
}
除此之外,我在 canvas 的前 4 个区域收到了 4 个噪声面板。噪音特别包括很多我知道也不在源图像中的像素(即蓝色像素;我试图扭曲的图像是红色和白色)。噪点在某种程度上是可识别的,因为它最初是源图像,但失真并带有上述人工制品。
比较:
你没有完全处理矢量场,你必须从场中读取每个矢量。实际上你只读了向量的第 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 个元素,而 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);
}
}
我正在尝试生成一个函数,该函数从源图像开始,生成噪声,然后使用噪声扭曲图像。
我从创建噪声开始,并将其转换为矢量场,然后我重新映射坐标,并在正确的坐标处将像素从图像中拉出。
最后,我将提取的像素重新组合成图像。
目前我的代码如下:
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);
}
除此之外,我在 canvas 的前 4 个区域收到了 4 个噪声面板。噪音特别包括很多我知道也不在源图像中的像素(即蓝色像素;我试图扭曲的图像是红色和白色)。噪点在某种程度上是可识别的,因为它最初是源图像,但失真并带有上述人工制品。
比较:
你没有完全处理矢量场,你必须从场中读取每个矢量。实际上你只读了向量的第 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 个元素,而 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);
}
}