寻找相似图片算法

寻找相似图片算法

根据阮一峰的博文实现一个js版本, 步骤如下:

  1. 将图片缩小到8x8的尺寸
  2. 转化为64灰度级
  3. 计算所有64个像素的灰度平均值
  4. 比较像素的灰度, 大于或等于平均值,记为1;小于平均值,记为0。
  5. 计算哈希值

更加详细的步骤参考作者原文

实现这个功能的过程中,会涉及到图片的缩放,将图片转化为灰度图, 以及生成图片hash,计算汉明距离等细节点。在实现的时候通过对canvas的操作来处理图片

 

图片缩放

function resize2Canvas(img, width, height) {
    if (!img || !width) {
        return img;
    }
    height = height || width;
    // 按原图缩放
    var detImg = img.width / img.height;
    if (width / height > detImg) {
        height = width / detImg;
    } else {
        width = height * detImg;
    }
    // 画到 canvas 中
    var canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, width, height);
    return canvas;
}

 

 

转化图片为灰度图

转换的算法为: Y =0.299 * R + 0.587 * G + 0.114 * B

更多细节参考color-contrast

 

function grayscaleCanvas(canvas) {
    var canvasContext = canvas.getContext('2d');
    var cWidth = canvas.width;
    var cHeight = canvas.height;
    var canvasData = canvasContext.getImageData(0, 0, cWidth, cHeight);
    var canvasDataWidth = canvasData.width;

    for (var x = 0; x < cWidth; x++) {
        for (var y = 0; y < cHeight; y++) {

            // Index of the pixel in the array
            var idx = (x + y * canvasDataWidth) * 4;
            var r = canvasData.data[idx + 0];
            var g = canvasData.data[idx + 1];
            var b = canvasData.data[idx + 2];

            // calculate gray scale value
            var gray = Math.ceil((0.299 * r + 0.587 * g + 0.114 * b) / 4);


            // assign gray scale value
            canvasData.data[idx + 0] = gray; // Red channel
            canvasData.data[idx + 1] = gray; // Green channel
            canvasData.data[idx + 2] = gray; // Blue channel
            canvasData.data[idx + 3] = 255; // Alpha channel
        }
    }
    canvasContext.putImageData(canvasData, 0, 0);
    return canvasData;
}

计算图片的hash值,并计算其汉明距离

/**
 + 计算图片的hash值
 */
function hash(img) {
    var size = 8;
    var resizedCanvas = resize2Canvas(img, size, size, false);
    var canvasData = grayscaleCanvas(resizedCanvas);
    var cW = canvasData.width,
        cH = canvasData.height;
    var totalGray = 0,
        x, y, idx, grayValue;
    for (x = 0; x < cW; x++) {
        for (y = 0; y < cH; y++) {
            // Index of the pixel in the array
            idx = (x + y * cW) * 4;
            grayValue = canvasData.data[idx];
            totalGray += grayValue;
        }
    }
    var meanGray = totalGray / (size * size);
    var val;
    var array = [];
    for (x = 0; x < cW; x++) {
        for (y = 0; y < cH; y++) {
            // Index of the pixel in the array
            idx = (x + y * cW) * 4;
            grayValue = canvasData.data[idx];
            if (grayValue >= meanGray) {
                val = 1;
            } else {
                val = 0;
            }
            array.push(val);
        }
    }
    return parseInt(array.join(''), 2).toString(16);
}
/**
 * 计算汉明距离
 */
function hamming(h1, h2) {
    var h1a = hashToBinaryArray(h1);
    var h2a = hashToBinaryArray(h2);
    var diff = 0;
    for (var i = 0; i < h1a.length; i++) {
        diff += h1a[i] ^ h2a[i];
    }
    return diff;
}

/**
 + 将16进制的图片hash转化为二进制
 */
function hashToBinaryArray(h) {
    return parseInt(h, 16).toString(2);
}

    完整的代码请查看  https://github.com/976032412/front-end-playground/tree/master/frontend/find-similar-picture

    非常感谢  Andrew Zhang 的分享   

 

 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值