我有一個中間有一個紅色實心圓圈的影像。我想讀取該影像,分析像素,然后僅將圓圈的輪廓寫回畫布。所以我正在檢查該像素是否被紅色通道值為 255 的像素包圍。如果是,我將其設為透明。如果沒有,我將像素著色為青色。
我使用了這篇文章,作為撰寫腳本的參考。
我做錯了什么。它不是用青色勾勒出圓圈并使中心透明,而是將所有白色像素著色為青色。
我真的很感激一些幫助!
代碼:
<img alt="input" height="170" id="input" src="img/input.png" width="170">
<canvas height="170" id="myCanvas" style="border:1px solid #d3d3d3;" width="170"></canvas>
let neighbors = []
function isSurrounded(index, imageData, data) {
neighbors = [] // clear array
neighbors[0] = data[index - imageData.width * 4 - 4] // Upper left
neighbors[1] = data[index - imageData.width * 4] // Upper middle
neighbors[2] = data[index - imageData.width * 4 4] // Upper right
neighbors[3] = data[index - 4] // left
neighbors[4] = data[index 4] // right
neighbors[5] = data[index imageData.width * 4 - 4] // Lower left
neighbors[6] = data[index imageData.width * 4] // lower middle
neighbors[7] = data[index imageData.width * 4 4] // Lower right
// check red channel
for (let i = 0; i < neighbors.length; i ) {
let redPixel = neighbors[i]
if (redPixel !== 255) {
return false
}
}
return true
}
let img = document.getElementById("input")
img.onload = function () {
let c = document.getElementById("myCanvas")
let ctx = c.getContext("2d")
ctx.drawImage(img, 0, 0)
let imgData = ctx.getImageData(0, 0, c.width, c.height)
let pxl = imgData.data
for (let i = 0; i < pxl.length; i = 4) {
if (isSurrounded(i, imgData, pxl)) {
pxl[i] = 0
pxl[i 1] = 255
pxl[i 2] = 255
pxl[i 3] = 255
} else {
pxl[i 3] = 0
}
}
ctx.putImageData(imgData, 0, 0)
}
uj5u.com熱心網友回復:
也許不同的方法會奏效。我沒有為此使用實際影像來處理安全問題,但該程序應該仍然有效。
處理時我喜歡做的第一件事img.data是創建一個陣列,為每個像素提供自己的陣列;一個二維陣列。即 [[0, 0, 0, 0,], [255, 0, 255, 0]...]。就我個人而言,它更容易處理。
let imgData = ctx.getImageData(0, 0, c.width, c.height);
let data = imgData.data.reduce(
(pixel, key, index) =>
(index % 4 == 0
? pixel.push([key])
: pixel[pixel.length - 1].push(key)) && pixel,
[]
);
無論您如何處理data陣列(1d 或 2d),您都需要檢查左-右-上-下的像素的透明度是否為 0。現在,如果您使用的影像沒有透明度,那么您我需要糾正這一點。畫布會自動透明,直到您在其上著色。
for (let i = 0; i < data.length; i ) {
if (data[i][0] >= 250 && data[i 1][3] === 0) {
data[i][0] = 0;
data[i][1] = 0;
data[i][2] = 255;
data[i][3] = 255;
}
雖然我用純紅色給我的圓圈涂上了顏色,但在邊緣附近的情況下,該r值不會是 255,但可能會略低一些。我也想看看右邊的像素是否透明。如果是,那么這意味著它必須在圓的邊緣。對所有方面都這樣做,如果為真,我將像素設定為藍色。
完成后,我可以遍歷陣列并將所有剩余的紅色像素更改為透明。
data.forEach((px) => {
if (px[0] >= 250) {
px[0] = 0;
px[1] = 0;
px[2] = 0;
px[3] = 0;
}
});
現在我們需要創建一個新的影像資料,并在繪制它之前將我們的新陣列設定為它的資料。我flat()在這里使用是因為我的資料陣列是 2d 的,為此我們需要它是 1d。
let newImage = ctx.createImageData(170, 170);
newImage.data.set(data.flat());
ctx.putImageData(newImage, 0, 0);
現在你應該有一個輪廓圓
let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
function drawCircle() {
ctx.fillStyle = "red";
ctx.arc(c.width / 2, c.height / 2, 70, 0, Math.PI * 2);
ctx.fill();
}
drawCircle();
window.onload = function () {
let imgData = ctx.getImageData(0, 0, c.width, c.height);
let data = imgData.data.reduce(
(pixel, key, index) =>
(index % 4 == 0
? pixel.push([key])
: pixel[pixel.length - 1].push(key)) && pixel,
[]
);
for (let i = 0; i < data.length; i ) {
if (data[i][0] >= 250 && data[i 1][3] === 0) {
data[i][0] = 0;
data[i][1] = 0;
data[i][2] = 255;
data[i][3] = 255;
}
if (data[i][0] >= 250 && data[i - 1][3] === 0) {
// console.log(data[i-1])
data[i][0] = 0;
data[i][1] = 0;
data[i][2] = 255;
data[i][3] = 255;
}
if (data[i][0] >= 250 && data[i - 170][3] === 0) {
data[i][0] = 0;
data[i][1] = 0;
data[i][2] = 255;
data[i][3] = 255;
}
if (data[i][0] >= 250 && data[i 170][3] === 0) {
data[i][0] = 0;
data[i][1] = 0;
data[i][2] = 255;
data[i][3] = 255;
}
}
data.forEach((px) => {
if (px[0] >= 250) {
px[0] = 0;
px[1] = 0;
px[2] = 0;
px[3] = 0;
}
});
let newImage = ctx.createImageData(170, 170);
newImage.data.set(data.flat());
ctx.putImageData(newImage, 0, 0);
};
<canvas height="170" id="myCanvas" style="border:1px solid #d3d3d3;" width="170"></canvas>
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/374899.html
