admin管理员组文章数量:1124163
I have a code that should affect an image by applying a laplace filter to the top left quarter and to the bottom left quarter separately. But when doing so, sometimes the second application of the filter affects the bottom right instead and sometimes misses a channel. I cannot for the life of me understand why it is apparently nondeterministic when doing so.
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('/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>
I have a code that should affect an image by applying a laplace filter to the top left quarter and to the bottom left quarter separately. But when doing so, sometimes the second application of the filter affects the bottom right instead and sometimes misses a channel. I cannot for the life of me understand why it is apparently nondeterministic when doing so.
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>
and example of incorrect:
and an example of correct image:
Share Improve this question edited yesterday Kaiido 136k14 gold badges254 silver badges317 bronze badges asked yesterday ion gigelion gigel 12 bronze badges 4 |1 Answer
Reset to default 0When the source image's height is odd, your y-axis coords will fall on a .5
float value. In this case, your pos
function will return an index that's off by half the width of the image (since there are 4 channels per pixel):
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 }
You thus need to round your coordinates when you do canvas.height / 2
.
本文标签:
版权声明:本文标题:javascript - Why does my code affect the imageData.data at times correctly and at other (random) times, in an unexpected way? - 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736603741a1945276.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
applyLaplace(canvasImageData, 0, canvas.height / 2, 0, canvas.width / 2, canvas.width, canvas.height, kernel);
, capture those arguments as variables, and log those, to see what values they have, so you can work your way back to why those are the values they have. – Mike 'Pomax' Kamermans Commented yesterdayundefined
because numerical values are treated as indices, and indices can only be integer. – Mike 'Pomax' Kamermans Commented 20 hours ago