Javascript native realization of image similarity recognition algorithm

There is a function called 查找相似图片
js that can easily realize image similarity recognition

Final example

Experience address http://cdn.magiczhu.cn/index.html
code stamp here
Insert picture description here

Implementation principle & steps

  1. Read local files-network pictures can omit this step
  2. Compress pictures-no need to deal with too many picture pixels
  3. Image grayscale-easy to compare features
  4. Extract feature fingerprints-take the average of the gray scale, the larger is 1 and the smaller is 0
  5. Calculate Hamming distance-a simple calculation method (and cosine similarity, etc.)
  6. Get similarity-(characteristic string length-Hamming distance)/characteristic string length

Implementation

Read local file

About FileReader can go to here

    //读取本地文件返回 src可用值
    function readFile(file) {
    
    
        return new Promise((resolve) => {
    
    
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.addEventListener("load", function () {
    
    
                resolve(reader.result);
            }, false)
        })
    }

Compress image

Utilizes the feature that canvas will automatically merge similar pixels when setting a smaller width and height

    function compressImage(imgSrc, imgWidth = 50) {
    
    
        return new Promise((resolve, reject) => {
    
    
            if (!imgSrc) {
    
    
                reject('imgSrc can not be empty!')
            }
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')
            const img = new Image()
            img.crossOrigin = 'Anonymous'
            img.src = imgSrc
            img.onload = function () {
    
    
                canvas.width = imgWidth
                canvas.height = imgWidth
                ctx.drawImage(img, 0, 0, imgWidth, imgWidth)
                const imageData = ctx.getImageData(0, 0, imgWidth, imgWidth)
                let info = {
    
    
                    dataUrl: canvas.toDataURL(),
                    imageData,
                }
                resolve(info)
            }
        })
    }

Picture grayscale

Grayscale. In the RGB model, if R=G=B, the color represents a grayscale color. The value of R=G=B is called the grayscale value. Therefore, each pixel of the grayscale image only needs one The byte stores the gray value (also called intensity value, brightness value), and the gray range is 0-255.

Graying formula
Insert picture description here

    //根据rgb值算出灰度值
    function getGrayFromRGB(R, G, B) {
    
    
        let a = Math.pow(R, 2.2) + Math.pow(1.5 * G, 2.2) + Math.pow(0.6 * B, 2.2);
        let b = 1 + Math.pow(1.5, 2.2) + Math.pow(0.6, 2.2);
        return parseInt(Math.pow(a / b, 1 / 2.2))
    }
        //根据rgba数组生成 imageData 和dataUrl
    function createImageData(data) {
    
    
        const canvas = document.createElement('canvas')
        canvas.width = 50
        canvas.height = 50
        const ctx = canvas.getContext('2d')
        const imgWidth = Math.sqrt(data.length / 4)
        const newImageData = ctx.createImageData(imgWidth, imgWidth)
        for (let i = 0; i < data.length; i += 4) {
    
    
            newImageData.data[i] = data[i]
            newImageData.data[i + 1] = data[i + 1]
            newImageData.data[i + 2] = data[i + 2]
            newImageData.data[i + 3] = data[i + 3]
        }
        ctx.putImageData(newImageData, 0, 0);
        return {
    
    
            dataUrl: canvas.toDataURL(),
            imageData: newImageData
        }
    }
    //灰度化
    function grayImage(imageData) {
    
    
        let data = imageData.data;
        let len = imageData.data.length;
        let newData = new Array(len);
        for (let i = 0; i < len; i += 4) {
    
    
            const R = data[i];
            const G = data[i + 1];
            const B = data[i + 2];
            const grey = getGrayFromRGB(R, G, B);
            newData[i] = grey;
            newData[i + 1] = grey;
            newData[i + 2] = grey;
            newData[i + 3] = 255;
        }
        return createImageData(newData);
    }

The average value of rgb is used directly in the reference article
{.is-warning}

Extract characteristic fingerprints

It is a string of the gray value and the average value of all gray values. The larger is 1 and the smaller is 0.

    function HashFingerprint(imageData) {
    
    
        const grayList = imageData.data.reduce((pre, cur, index) => {
    
    
            if ((index + 1) % 4 === 0) {
    
    
                pre.push(imageData.data[index - 1])
            }
            return pre
        }, [])
        const length = grayList.length
        const grayAverage = grayList.reduce((pre, next) => (pre + next), 0) / length
        return grayList.map(gray => (gray >= grayAverage ? 1 : 0)).join('')
    }

Calculate Hamming distance

The Hamming distance is named after Richard Wesley Hamming. In information theory, the Hamming distance between two strings of equal length is the number of different characters in the corresponding positions of the two strings. In other words, it is the number of characters that need to be replaced to transform one string into another. For example:
The Hamming distance between 1011101 and 1001001 is 2.
The Hamming distance between 2143896 and 2233796 is 3.
The Hamming distance between "toned" and "roses" is 3.

   function getHm(str1,str2){
    
    
        let distance=0;
        let len = str1.length;
        for(let i=0;i<len;i++){
    
    
            if(str1[i]!=str2[i]){
    
    
                distance++;
            }
        }
        return distance
    }

Get similarity

Similarity formula: (characteristic string length-Hamming distance)/characteristic string length

    //相似度
    function getSimilarity(strLen,hm){
    
    
        return parseInt((strLen - hm)/strLen*100)
    }

Reference article https://mp.weixin.qq.com/s/oOlv9cbIhSwJtb-mGU8gwg

Guess you like

Origin blog.csdn.net/weixin_38616850/article/details/107851189