1
0

【JavaScript】画像/写真/イラストから輪郭を抽出する【Sobelフィルタ】【切り絵風】

Last updated at Posted at 2024-06-21

結論

Sobelフィルターを使う。

(2値化させるとより輪郭が分かりやすくなる。)

Canvasに画像を貼り付けた後にimageDataを取得して、sobelフィルターをかけた後に、putImageDataしてちょ。

純粋なsobelフィルターは輪郭が白になるので以下のコードでは反転させています。

function sobelFilter(imageData) {
    const data = imageData.data;
    const width = imageData.width;
    const height = imageData.height;

    for (let i = 0; i < data.length; i += 4) {
        const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
        data[i] = avg;
        data[i + 1] = avg;
        data[i + 2] = avg;
    }

    const sobelData = new Uint8ClampedArray(width * height);

    const kernelX = [
        [-1, 0, 1],
        [-2, 0, 2],
        [-1, 0, 1]
    ];
    const kernelY = [
        [-1, -2, -1],
        [0, 0, 0],
        [1, 2, 1]
    ];

    for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
            let pixelX = 0;
            let pixelY = 0;

            for (let ky = -1; ky <= 1; ky++) {
                for (let kx = -1; kx <= 1; kx++) {
                    const pixel = data[((y + ky) * width + (x + kx)) * 4];
                    pixelX += pixel * kernelX[ky + 1][kx + 1];
                    pixelY += pixel * kernelY[ky + 1][kx + 1];
                }
            }

            const magnitude = Math.round(Math.sqrt(pixelX * pixelX + pixelY * pixelY));
            sobelData[y * width + x] = magnitude;
        }
    }

    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const idx = (y * width + x) * 4;
            const invertedMagnitude = 255 - sobelData[y * width + x];
            data[idx] = invertedMagnitude;
            data[idx + 1] = invertedMagnitude;
            data[idx + 2] = invertedMagnitude;
            data[idx + 3] = 255;
        }
    }
}

サンプル

輪郭抽出との出会いとなった記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0