2

目标
找到一种检查 2 个图像是否相似的好方法,比较它们的哈希配置文件。哈希是一个包含0 和 1 值的简单数组

简介
我有 2 张图片。它们是相同的图像,但有一些细微差别:一个具有不同的亮度、旋转和拍摄。
我想要做的是创建一个 Javascript 方法来比较 2 个图像并计算一个百分比值来说明它们的相似程度

我所做的
在将 2 张图片上传到 html5 画布以获取它们的图像数据后,我使用了pHash算法 (www.phash.org) 来获取它们的哈希表示。
哈希是一个包含 0 和 1 值的数组,它以“简化”形式重新创建图像。
我还创建了一个 JS 脚本,它生成一个带有黑色单元格的 html 表格,其中数组包含 1。
结果是以下屏幕截图(图像是梵高图片):

截屏

现在,我应该做的是比较两个数组以获得百分比值,以了解它们相似的“多少”。
我发现谷歌搜索的大部分哈希 Javascript 算法已经有一个比较算法:汉明距离算法。它非常简单和快速,但不是很精确。事实上,汉明距离算法说我截图中的 2 张图片有67% 的相似度

问题
从 2 个长度相同的简单数组开始,填充 0 和 1 值:什么是更精确地确定相似度的好算法?

NOTES
- 纯 Javascript 开发,没有第三方插件或框架。
- 当两幅图像相同但它们非常不同(强烈旋转、完全不同的颜色等)时,无需复杂的算法来找到正确的相似性。

谢谢

相码

  // Size is the image size (for example 128px)
  var pixels = [];

  for (var i=0;i<imgData.data.length;i+=4){
			
      var j = (i==0) ? 0 : i/4;
			var y = Math.floor(j/size);
			var x = j-(y*size);			
			
			var pixelPos = x + (y*size);
			var r = imgData.data[i];
			var g = imgData.data[i+1];
			var b = imgData.data[i+2];

			var gs = Math.floor((r*0.299)+(g*0.587)+(b*0.114));
			pixels[pixelPos] = gs;
      
  }

  var avg = Math.floor( array_sum(pixels) / pixels.length );
  var hash = [];
  array.forEach(pixels, function(px,i){
    if(px > avg){
      hash[i] = 1;
    } else{
      hash[i] = 0;
    }
  });

  return hash;

汉明距离码

  // hash1 and hash2 are the arrays of the "coded" images.
  
  var similarity = hash1.length;
  
  array.forEach(hash1, function(val,key){
    if(hash1[key] != hash2[key]){
      similarity--;
    }
  });

  var percentage = (similarity/hash1.length*100).toFixed(2);

注意:array.forEach 不是纯 JavaScript。将其视为替换:for (var i = 0; i < array.length; i++)。

4

2 回答 2

1

我正在使用blockhash,到目前为止看起来还不错,我得到的唯一误报是当一半的图片具有相同的背景颜色时,这是可以预料的=/

http://blockhash.io/

BlockHash 可能比你的慢,但它应该更准确。

您所做的只是计算每个像素的灰度,然后将其与平均值进行比较以创建您的哈希值。

BlockHash 所做的是将图片分割成大小相等的小矩形,并对其中像素的 RGB 值的总和进行平均,并将它们与 4 个水平中位数进行比较。

所以它需要更长的时间是正常的,但它仍然非常有效和准确。

我正在使用分辨率良好的图片,至少 1000x800,并使用 16 位。这给出了一个 64 字符长的十六进制散列。当使用同一个库提供的汉明距离时,我在使用 10 相似度阈值时看到了很好的结果。

您使用灰度的想法一点也不坏。但是您应该平均图像的各个部分,而不是比较每个像素。这样,您可以将缩略图版本与其原始版本进行比较,并获得几乎相同的 phash!

于 2017-07-25T08:24:46.827 回答
0

我不知道这是否可以解决问题,但您可以比较数组之间的 0 和 1 相似性:

const arr1 = [1,1,1,1,1,1,1,1,1,1],
      arr2 = [0,0,0,0,0,0,0,0,0,0],
      arr3 = [0,1,0,1,0,1,0,1,0,1],
      arr4 = [1,1,1,0,1,1,1,0,1,1]

const howSimilar = (a1,a2) => {
    let similarity = 0
    a1.forEach( (elem,index) => {
        if(a2[index]==elem) similarity++
    })
    let percentage = parseInt(similarity/arr1.length*100) + "%"
    console.log(percentage)
}

howSimilar(arr1,arr2) // 0%
howSimilar(arr1,arr3) // 50%
howSimilar(arr1,arr4) // 80%
于 2017-07-25T08:30:52.557 回答