一种基于颜色统计和特征指纹的图片相似度计算方法

一种基于颜色统计和特征指纹的图片相似度计算方法

1.摘要

图片相似度有很多实际应用,比如谷歌搜图、淘宝识物购买,现在很多类似应用已经使用神经网络训练实现,但是本文仅仅从图像处理角度出发,根据图像内容特征信息实现图片相似度计算。如题描述,我们将从颜色和内容信息两方面进行。

2.实现

本节内容将从原理、代码实现并结合应用效果介绍感知哈希算法和颜色分量统计算法

from math import sqrt
import numpy as np
import pandas as pd
import itertools

2.1.感知哈希算法

  1. 原理描述:结合离散余弦变换,将灰度图片所包含的特征生成一组指纹(哈希值),计算图片相似度即计算图片指纹的相似度。
  2. 关于离散余弦变换:灰度图是二维矩阵,由不同频率的成分组成。一般来说亮度变化小的区域是低频成分,它描述大范围的信息。而亮度变化剧烈的区域(比如物体的边缘)就是高频的成分,它描述具体的细节。由于大多数自然信号的能量都集中在余弦变换后的低频部分,可以舍弃信息含量更少的高频部分而提高计算效率,具体使用方法是离散余弦变换(DCT)。
  3. 具体步骤:
  • 简化色彩:BGR2GRAY;

  • 计算DCT:计算图片的DCT变换,得到32*32的DCT系数矩阵;

  • 缩小DCT:保留左上角的8*8的矩阵(最低频率);

  • 计算平均值:计算DCT的均值;

  • 计算hash值:根据8*8的DCT矩阵,设置0或1的64位的hash值,大于等于DCT均值的设为”1”,小于DCT均值的设为“0”。将得到的二维数组拉伸成一维,构成了一个长度为64位的向量,这就是这张图片的指纹;

  • 计算两张图片指纹,使用汉明距离计算相似度。

    结果并不能告诉我们真实性的低频率,只能粗略地告诉我们较于平均值频率的相对比例。只要图片的整体结构保持不变,hash结果值就不变。能够避免伽马校正或颜色直方图被调整带来的影响。

#均值哈希算法
def aHash(img):
    img=cv2.resize(img,(8,8),interpolation=cv2.INTER_CUBIC)
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    s=0
    hash_str=''
    for i in range(8):
        for j in range(8):
            s=s+gray[i,j]
    avg=s/64
    for i in range(8):
        for j in range(8):
            if  gray[i,j]>avg:
                hash_str=hash_str+'1'
            else:
                hash_str=hash_str+'0'            
    return hash_str

#差值感知算法
def dHash(img):
    img=cv2.resize(img,(9,8),interpolation=cv2.INTER_CUBIC)
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    hash_str=''
    for i in range(8):
        for j in range(8):
            if   gray[i,j]>gray[i,j+1]:
                hash_str=hash_str+'1'
            else:
                hash_str=hash_str+'0'
    return hash_str

# 感知哈希算法
def pHash(img):
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    img=cv2.resize(img,(32,32),interpolation=cv2.INTER_CUBIC)

    _ = np.array(img,np.float32)
    __ = cv2.dct(_)
    #取低频区域
    img_dct = __[:8,:8]

    #把二维list变成一维list
    img_list = []
    for i in img_dct.tolist():
        for j in i:
            img_list.append(j)
    
    #计算均值并哈希转换
    avg = sum(img_list)*1./len(img_list)
    hash_str = ''
    for i in img_list:
        if i > avg:
            hash_str=hash_str+'1'
        else:
            hash_str=hash_str+'0' 
    return hash_str
    
#Hash值对比
def compCode(code1,code2,length):
    num = 0
    for index in range(0,len(code1)):
        if code1[index] != code2[index]:
            num+=1
    return (1-(num / length))
# 感知哈希算法使用:
compCode(pHash(img_a),pHash(img_b),64)

2.2.颜色分量统计算法

  1. 原理描述:每张图片都有自己特定的颜色分布。将1600多万种颜色分为N个颜色区间,对每张图片,统计其每个颜色区间的像素个数,获得一组长度为N的向量。计算图片相似度即计算向量之间的相似度。
  2. 具体步骤:
  • 规整尺寸:resize(102410243);
  • 颜色分区:将RGB每个颜色通道均分为m个数值区间,共得到m的三次方(记为N)个颜色区间;
  • 统计每个颜色区间内的像素个数,获得向量;
  • 计算向量之间的相似度;
# 代码不贴了 有兴趣私聊

3.验证效果

感知哈希算法中,经过了余弦离散变化,图像内部信息的大都集中在低频区域,将计算重点缩小至该区域,但是仅仅对灰度图研究,丢失了颜色信息,而颜色分量统计算法从颜色角度出发,统计了整张图片的颜色分布情况,两种方法结合保证了相似度的准确性。

扫描二维码关注公众号,回复: 8511545 查看本文章

以下风景图(450×800×3)为例,记为img
Original

  • 将原图上下平均拆分
    img_up:225×800
    img_dn:225×800
  • 将原图左右比例拆分
    img_left:450×600
    img_right:450×600

感知哈希算法效果如下:
这里写图片描述

综合两种算法一起的效果如下:
这里写图片描述

参考:https://blog.csdn.net/haofan_/article/details/77097473?locationNum=7&fps=1

发布了20 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/github_35965351/article/details/82704313