JS实现图片相似度判断实例页面

回到相关文章 »

效果:

相近图片

相似度是?


差异明显图片

相似度是?


自己本地选图

相似度是:?

代码:

HTML代码:
<section>
    <h4>相近图片</h4>
    <div class="flex">
        <figure>
            <img src="./book1.jpg" />
        </figure>
        <figure>
            <img src="./book2.jpg" />
        </figure>
    </div>
    <p>相似度是?<button>计算</button></p>
</section>

<section>
    <h4>差异明显图片</h4>
    <div class="flex">
        <figure>
            <img src="./book1.png" />
        </figure>
        <figure>
            <img src="./me.jpg" />
        </figure>
    </div>
    <p>相似度是?<button>计算</button></p>
</section>

<section>
    <h4>自己本地选图</h4>
    <div class="flex">
        <figure>
            <input type="file" accept="image/*">
        </figure>
        <figure>
            <input type="file" accept="image/*">
        </figure>
    </div>
    <p>相似度是:<output>?</output></p>
</section>
JS代码:
// 图片转imageData需要的canvas
// 为了节省开销,就在外面定义,只用这一个玩耍了
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { 
    willReadFrequently: true 
});
// image 转 imagedata的方法
const image2data = (img, flag) => {
    const { width, height } = canvas;
    ctx.clearRect(0, 0, width, height);
    ctx.drawImage(img, 0, 0, width, height);
    return ctx.getImageData(0, 0, width, height);
};
// 点击按钮计算相似度
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
    const images = button.closest('section').querySelectorAll('img');
    button.onclick = function () {
        // canvas的尺寸,越小性能越好
        canvas.width = 128;
        canvas.height = 157;
        
        const { mssim, performance } = ssim.ssim(image2data(images[0]), image2data(images[1]));
        
        // 显示对比结果
        const span = document.createElement('span');
        span.innerHTML = `&emsp; 相似度: ${mssim} (${performance}ms)`;
        
        this.after(span);
        this.disabled = true;
    };    
});
// 选择文件对比相似度
const inputs = document.querySelectorAll('[type="file"]');
const inputImgs = [];
const compareImg = () => {
    // 开始转imageData并对比相似度
    if (inputImgs.length === 2) {
        // 首先是尺寸,按照面积小的那个算
        let { width, height } = inputImgs[0];
        // 如果面积大了,算第2个图
        if (width * height > inputImgs[1].width * inputImgs[0].height) {
            width = inputImgs[1].width;
            height = inputImgs[1].height;
        }
        canvas.width = width;
        canvas.height = height;
        
        const { mssim, performance } = ssim.ssim(image2data(inputImgs[0]), image2data(inputImgs[1]));

        // 显示对比结果
        const output = inputImgs[0].closest('section').querySelector('output');
        output.textContent = `${mssim} (${performance}ms)`;
    }
}
inputs.forEach((input, index) => {
    input.onchange = function (event) {
        const file = event.target.files[0];
        // 图片元素
        const img = input.nextElementSibling || new Image();
        img.onload = function () {
            inputImgs[index] = img;
            compareImg();
        };
        // 文件转base64地址给图片用
        const reader = new FileReader();
        reader.addEventListener('load', () => {
            img.src = reader.result;
            // 图片插入到页面中
            if (!img.isConnected) {
                input.after(img);
            }
        }, false);
        reader.readAsDataURL(file);
    }
});