0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenCV.jsでK-meansするメモ

Last updated at Posted at 2025-04-15

はじめに

OpenCVのドキュメントやサンプルって基本的にC++かPythonなのでJavaScriptでやるときにちょっと調べないといけないんですよね。
私はK-meansやるときにちょっと苦戦したので、備忘録としてやり方載せておきます。
本記事ではK-meansについては解説しませんのであしからず。

FloatをUint8に変換

こうすると若干早くなります。

        // Convert Float to UInt8
        const floatToUint8 = x => Math.min(Math.max(Math.round(x), 0), 255);
        const ui8Centers = new Uint8Array(k * 3);
        for(let c = 0; c < k; c += 1) {
            for(let z = 0; z < 3; z += 1) {
                ui8Centers[c * 3 + z] = floatToUint8(centers.floatAt(c, z));
            }
        }        
        centers.delete();

ソース

自作クラスのstatic メソッドを貼り付けておきます。

    /**
     * Color reduction processing using K-means
     * @param {Mat} src source mat 
     * @param {Mat} dst destination mat
     * @param {number} k cluster count
     * @param {number} attempts number of attempts 
     * @param {number} maxCount the maximum number of iterations/elements
     * @param {number} epsilon the desired accuracy
     * @returns {Mat} destination mat
     */
    static kmeans(src, dst, k, attempts, maxCount = 1e4, epsilon = 1e-4) {
        // Initialize
        dst = dst || new cv.Mat(src.size(), src.type());
        const [labels, centers] = [new cv.Mat(), new cv.Mat()];
        const criteria = new cv.TermCriteria(cv.TermCriteria_EPS + cv.TermCriteria_MAX_ITER, maxCount, epsilon);
        const flags = cv.KMEANS_PP_CENTERS;

        // Create samples
        const samples = new cv.Mat(src.rows * src.cols, 3, cv.CV_32F);
        for(let y = 0; y < src.rows; y += 1) {
            for(let x = 0; x < src.cols; x += 1) {
                const idx = y * src.cols + x;
                for(let z = 0; z < 3; z += 1) {                    
                    samples.floatPtr(idx)[z] = src.data[idx * 4 + z];
                }
            }
        }

        // K-Means method
        let startDate = new Date();
        cv.kmeans(samples, k, labels, criteria, attempts, flags, centers);
        console.log('kmeans:', new Date() - startDate, 'ms');
        
        // Convert Float to UInt8
        const floatToUint8 = x => Math.min(Math.max(Math.round(x), 0), 255);
        const ui8Centers = new Uint8Array(k * 3);
        for(let c = 0; c < k; c += 1) {
            for(let z = 0; z < 3; z += 1) {
                ui8Centers[c * 3 + z] = floatToUint8(centers.floatAt(c, z));
            }
        }        
        centers.delete();
        
        // Create dst from labels and centers
        startDate = new Date();
        for(let y = 0; y < dst.rows; y += 1) {
            for(let x = 0; x < dst.cols; x += 1) {
                const p = (y * dst.cols + x) * 4;
                const c = labels.data[p];
                for(let z = 0; z < 3; z += 1) {                    
                    dst.data[p + z] = ui8Centers[c * 3 + z];
                }
                dst.data[p + 3] = src.data[p + 3];
            }
        }
        labels.delete();
        console.log('after kmeans:', new Date() - startDate, 'ms');
        return dst;
    }

image.png

参考リンク

How can you use K-Means clustering to posterize an image using opencv javascript?

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?