我有一个代码,应该通过分别对左上四分之一和左下四分之一应用拉普拉斯滤波器来影响图像。但这样做时,有时过滤器的第二次应用会影响右下角,有时会错过一个通道。我一生都无法理解为什么这样做时它显然是不确定的。
var canvas;
var canvasImageData;
var canvasContext;
main()
let kernel = [
[0.25, 0.5, 0.25],
[0.5, -3, 0.5],
[0.25, 0.5, 0.25]
]
async function main() {
var api = await fetch('https://dog.ceo/api/breeds/image/random')
.then(response => response.json())
var image = await fetch(api.message)
.then(response => response.blob())
const imageBitmap = await createImageBitmap(image);
var canvas = document.createElement('canvas');
canvas.width = imageBitmap.width;
canvas.height = imageBitmap.height;
canvas.id = 'image-canvas';
canvasContext = canvas.getContext('2d')
canvasContext.drawImage(imageBitmap, 0, 0);
document.body.appendChild(canvas);
canvasImageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
canvasImageData = applyLaplace(canvasImageData, 0, canvas.height / 2, 0, canvas.width / 2, canvas.width, canvas.height, kernel);
canvasImageData = applyLaplace(canvasImageData, canvas.height / 2, canvas.height, 0, canvas.width / 2, canvas.width, canvas.height, kernel);
canvasContext.putImageData(canvasImageData, 0, 0);
}
//applyLaplace(canvasImageData)
function applyLaplace(canvas, height_start, height_end, width_start, width_end, canvasWidth, canvasHeight, kernel) {
let data = new Uint8ClampedArray(canvas.data);
function pos(h, l) {
return h * canvasWidth * 4 + l * 4;
}
for (let height = height_start + 1; height < height_end - 1; height++) {
for (let width = width_start + 1; width < width_end - 1; width++) {
let sum1 = 0;
let sum2 = 0;
let sum3 = 0;
for (let kernel_height = -1; kernel_height <= 1; kernel_height++) {
for (let kernel_width = -1; kernel_width <= 1; kernel_width++) {
sum1 = sum1 + data[pos(height + kernel_height, width + kernel_width) + 0] * kernel[kernel_height + 1][kernel_width + 1];
sum2 = sum2 + data[pos(height + kernel_height, width + kernel_width) + 1] * kernel[kernel_height + 1][kernel_width + 1];
sum3 = sum3 + data[pos(height + kernel_height, width + kernel_width) + 2] * kernel[kernel_height + 1][kernel_width + 1];
}
}
canvas.data[pos(height, width) + 0] = 255 - sum1;
canvas.data[pos(height, width) + 1] = 255 - sum2;
canvas.data[pos(height, width) + 2] = 255 - sum3;
}
}
return canvas;
}
<div id="api-response"></div>
以及错误示例:
以及正确图像的示例:
当源图像的高度为奇数时,您的 y 轴坐标将落在
.5
浮点值上。在这种情况下,您的 pos
函数将返回一个偏离图像宽度一半的索引(因为每个像素有 4 个通道):
const canvasWidth = 10;
function pos(h, l) {
return h * canvasWidth * 4 + l * 4;
}
const test = (x, y) => {
console.log({ x, y, index: pos(y, x) });
}
test(0, 0); // 0
test(5, 0); // 4 * 5 -> 20
test(0, 0.5); // Same as x:5, y:0
div.as-console-wrapper { max-height: 100vh }
因此,您需要在执行此操作时对坐标进行四舍五入
canvas.height / 2
。