两张图片相似度匹配算法学习路线

news2024/11/24 17:24:10

大纲:​​​​​​目标跟踪基础:两张图片相似度算法-腾讯云开发者社区-腾讯云 (tencent.com)

目标跟踪基础:两张图片相似度算法 (qq.com)

一、传统方法

1.欧式距离(用于判断是否完全相同)

[三维重建] [机器学习] 图片相似度_评价两张图片相似度或差异度的指标是-CSDN博客

import numpy as np

def euclidean_distance(image1, image2):
    # 将图片展平为一维向量
    vector1 = image1.flatten()
    vector2 = image2.flatten()

    # 计算欧式距离
    distance = np.linalg.norm(vector1 - vector2)
    return distance

# 示例用法
image1 = np.array([[1, 2, 3], [4, 5, 6]])
image2 = np.array([[4, 5, 6], [7, 8, 9]])
distance = euclidean_distance(image1, image2)
print(distance)

缺点:只考虑了像素差异,没有考虑位置和形状。

2.余弦相似度

from PIL import Image
 
from numpy import average, linalg, dot
 
 
 
 
 
def get_thumbnail(image, size=(1200, 750), greyscale=False):
 
    image = image.resize(size, Image.ANTIALIAS)
 
    if greyscale:
 
        image = image.convert('L')
 
    return image
 
 
 
 
 
def image_similarity_vectors_via_numpy(image1, image2):
 
 
 
    image1 = get_thumbnail(image1)
 
    image2 = get_thumbnail(image2)
 
    images = [image1, image2]
 
    vectors = []
 
    norms = []
 
    for image in images:
 
        vector = []
 
        for pixel_tuple in image.getdata():
 
            vector.append(average(pixel_tuple))
 
        vectors.append(vector)
 
        norms.append(linalg.norm(vector, 2))
 
    a, b = vectors
 
    a_norm, b_norm = norms
 
    res = dot(a / a_norm, b / b_norm)
 
    return res
 
 
 
 
 
image1 = Image.open('1.jpg')
 
image2 = Image.open('2.jpg')
 
cosin = image_similarity_vectors_via_numpy(image1, image2)
 
 
 
print(cosin)

3.哈希算法/汉明距离

详细步骤 + 代码 :图像相似度中的Hash算法 - Yumeka - 博客园 (cnblogs.com)

(1)ahash(Average Hash,均值哈希算法)

此算法是基于比较灰度图每个像素与平均值来实现的

一般步骤:

1.缩放图片,一般大小为8*8,64个像素值。

2.转化为灰度图

3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。

4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.

5.得到信息指纹:组合64个bit位,顺序随意保持一致性。

6.最后比对两张图片的指纹,获得汉明距离即可。

#均值哈希算法
 
def aHash(img):
 
    #缩放为8*8
 
    img=cv2.resize(img,(8,8),interpolation=cv2.INTER_CUBIC)
 
    #转换为灰度图
 
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
    #s为像素和初值为0,hash_str为hash值初值为''
 
    s=0
 
    hash_str=''
 
    #遍历累加求像素和
 
    for i in range(8):
 
        for j in range(8):
 
            s=s+gray[i,j]
 
    #求平均灰度
 
    avg=s/64
 
    #灰度大于平均值为1相反为0生成图片的hash值
 
    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

(2)phash(Perceptual Hash,感知哈希算法)

平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

一般步骤:

1.缩小图片:32 * 32是一个较好的大小,这样方便DCT计算

2.转化为灰度图

3.计算DCT:利用Opencv中提供的dct()方法,注意输入的图像必须是32位浮点型,所以先利用numpy中的float32进行转换

4.缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率

5.计算平均值:计算缩小DCT后的所有像素点的平均值。

6.进一步减小DCT:大于平均值记录为1,反之记录为0.

7.得到信息指纹:组合64个信息位,顺序随意保持一致性。

8.最后比对两张图片的指纹,获得汉明距离即可。

import cv2
 
import numpy as np
 
from compiler.ast import flatten
 
import sys
 
 
 
def pHash(imgfile):
 
    """get image pHash value"""
 
    #加载并调整图片为32x32灰度图片
 
    img=cv2.imread(imgfile, 0)
 
    img=cv2.resize(img,(64,64),interpolation=cv2.INTER_CUBIC)
 
 
 
        #创建二维列表
 
    h, w = img.shape[:2]
 
    vis0 = np.zeros((h,w), np.float32)
 
    vis0[:h,:w] = img       #填充数据
 
 
 
    #二维Dct变换
 
    vis1 = cv2.dct(cv2.dct(vis0))
 
    #cv.SaveImage('a.jpg',cv.fromarray(vis0)) #保存图片
 
    vis1.resize(32,32)
 
 
 
    #把二维list变成一维list
 
    img_list=flatten(vis1.tolist())
 
 
 
    #计算均值
 
    avg = sum(img_list)*1./len(img_list)
 
    avg_list = ['0' if i<avg else '1' for i in img_list]
 
 
 
    #得到哈希值
 
    return ''.join(['%x' % int(''.join(avg_list[x:x+4]),2) for x in range(0,32*32,4)])
 
 
 
'''
cv2.imread
flags>0时表示以彩色方式读入图片
flags=0时表示以灰度图方式读入图片
flags<0时表示以图片的本来的格式读入图片
interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值

(3)dhash(Difference Hash,差异哈希算法)

def dHash(img):
 
    #缩放8*8
 
    img=cv2.resize(img,(9,8),interpolation=cv2.INTER_CUBIC)
 
    #转换灰度图
 
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
    hash_str=''
 
    #每行前一个像素大于后一个像素为1,相反为0,生成哈希
 
    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

总结: 

图像均值(ahash)哈希本质上是对像素(颜色)的比较
图像感知(phash)哈希由于做了离散余弦变换操作,本质上是对频率的比较
图像差异(dhash)哈希本质上是基于变化的感知,更关注图片的像素值的变化 

4.直方图 + 巴氏系数

(1)直方图

直方图是描述一个图片中,颜色出现的次数(或频率)的一种统计图象,因为只关心某个像素值出现的次数,不关注像素值的位置,所以具有旋转、平移、缩放等不变性。且计算代价较小,只需要遍历整个图像就能得到。

直方图的横坐标为某个像素值,纵坐标为像素值在图片内出现的次数,如下图所示的图片矩阵中,像素值“1”出现了两次,所以该图片的直方图中,像素值“1”对应的纵坐标就该是2。

有时候为了避免图片分辨率造成的影响,(分辨率高的图像,像素个数肯定多,出现次数肯定多),会将出现次数除以图片的总像素个数,转化成出现概率。如上图中的图片矩阵的总像素个数是9,像素值“1”的出现次数是2,它的出现概率为 2 / 9。

直方图分为灰度直方图与RGB直方图

灰度直方图:对于灰度直方图,只需要维护一个长度为256的数组Gray[256],遍历图片矩阵,假设矩阵内某个位置的像素值为124,则Gray[124]++。

RGB直方图:如果每种原色都可以取256个值,那么整个颜色空间共有1600万种颜色(256的三次方)。针对这1600万种颜色比较直方图,计算量实在太大了,因此可以通过划分bin的方式进行简化。可以将0~255分成四个区:0~63为第0区,64~127为第1区,128~191为第2区,192~255为第3区。这意味着红绿蓝分别有4个区,总共可以构成64种组合(4的3次方)。再根据图片矩阵中某个位置的RGB值,决定直方图内哪个bin值加一。

直方图最终也可以表示成一个向量的形式,向量维数为直方图横坐标的个数,向量中的值为直方图纵坐标的值。A=(2,3,2,1,0,1)

(2)巴氏系数

5.特征结构

6.互信息 

7. 均方误差(MSE)

 8.SSIM结构相似性

9.特征匹配 

10.传统方法总结代码

opencv 简单的图片相似度匹配_opencv 图片相似度-CSDN博客

图像相似算法最全总结_图片相似度-CSDN博客

二、深度学习方法

1.孪生神经网络

pytorch孪生网络识别面部相似度代码解读_f.pairwise_distance-CSDN博客

 孪生网络:图片相似度对比神器-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1559446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RAG进阶笔记:RAG进阶

1 查询/索引部分 1.1 层次索引 创建两个索引——一个由摘要组成&#xff0c;另一个由文档块组成分两步进行搜索&#xff1a;首先通过摘要过滤出相关文档&#xff0c;接着只在这个相关群体内进行搜索 1.2 假设性问题 让LLM为每个块生成一个假设性问题&#xff0c;并将这些问…

一文看懂DDR1到DDR5的演变

DDR内存技术自问世以来&#xff0c;已经经历了多代的迭代和优化。每一代DDR内存都在性能、容量、功耗和功能上有所提升。以下是从DDR1到DDR5的主要区别和特点&#xff1a; DDR1 DDR1是第一代双倍数据速率同步动态随机存取存储器&#xff0c;标志着内存技术的一个重要里程碑。…

网安基础2-Sniffer的使用与防范

1. 嗅探器sniffer的工作原理 能捕获经过该网络设备的报文&#xff0c;通过分析网络流量&#xff0c;找出关键信息&#xff0c;解决网络问题。 不同于键盘捕获程序&#xff0c;如keylogger利用中断或钩子技术&#xff0c;Sniffer将网络接口置成适当的模式&#xff0c;如杂收。…

瑞吉外卖实战学习--9、mybatisPlus公共字段自动填充

mybatisPlus公共字段自动填充 前言实现步骤实体类添加注解按照框架要求编写元数据对象处理器&#xff0c;在此类中统一为公共字段赋值&#xff0c;此类需要实现MetaObjectHandler接口1、在创建和更新的时候修改创建和更新的时候自动填充时间2、如何获取到当前的id 测试结果 前言…

Vision Mamba 双向状态空间模型下的高效视觉表示学习

论文题目&#xff1a;Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 双向状态空间模型下的高效视觉表示学习 论文链接&#xff1a;http://arxiv.org/abs/2401.09417 代码链接&#xff1a;https://github.com/hustvl/Vim 1、…

Java中的多线程和线程安全问题

线程 线程是操作系统进行调度的最小单位。一个进程至少包含一个主线程&#xff0c;而一个线程可以启动多个子线程。线程之间共享进程的资源&#xff0c;但也有自己的局部变量。多线程程序和普通程序的区别&#xff1a;每个线程都是一个独立的执行流&#xff1b;多个线程之间是…

大模型面试准备(九):简单透彻理解MoE

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

C++list的模拟实现

为了实现list&#xff0c;我们需要实现三个类 一、List的节点类 template<class T> struct ListNode {ListNode(const T& val T()):_pPre(nullptr),_pNext(nullptr),_val(val){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val; }; 二、List的迭代器…

双网卡环境概率出现DNS解析错误

测试环境 VMware Rocky Linux 9 虚拟机, 双网卡(eth0和eth1)配置如下&#xff1a; eth0 10.206.216.27/24 DNS 10.204.16.18 eth1 192.168.1.27/24 DNS 192.168.1.1问题描述 手动配置eth1的DNS后&#xff0c;网络不通&#xff0c;通过抓包发现是eth1的DNS server配置有误…

【JavaWeb】Day29.SpringBootWeb请求响应——请求(二)

请求响应 4.数组集合参数 数组集合参数的使用场景&#xff1a;在HTML的表单中&#xff0c;有一个表单项是支持多选的(复选框)&#xff0c;可以提交选择的多个值。 4.1 数组 数组参数&#xff1a;请求参数名与形参数组名称相同且请求参数为多个&#xff0c;定义数组类型形参即…

springboot简历系统

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;简历系统当然也不能排除在外。简历系统是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;采用…

速通汇编(三)寄存器及汇编mul、div指令

一&#xff0c;寄存器及标志 AH&ALAX(accumulator)&#xff1a;累加寄存器BH&BLBX(base)&#xff1a;基址寄存器CH&CLCX(count)&#xff1a;计数寄存器DH&DLDX(data)&#xff1a;数据寄存器SP(Stack Pointer)&#xff1a;堆栈指针寄存器BP(Base Pointer)&#…

Vue3+Vite Nginx部署 跨域

打包项目 webstorm打开项目之后&#xff0c;在Terminal执行打包命令 pnpm run build:prod 复制到Nginx 打包完成之后,生成的包在根目录dist&#xff0c;把dist目录拷贝到Nginx放网站目录下&#xff1a;\nginx-1.25.2\html\divided &#xff0c;dist改名了divided 修改配置…

力扣---网络延迟时间---迪杰斯特拉,弗洛伊德floyd

首先推荐博客&#xff1a;图论最短路径专题&#xff08;力扣743、5888&#xff09;_力扣 最短路径-CSDN博客 迪杰斯特拉算法&#xff1a; 太久没有做图论的题了&#xff0c;&#xff0c;临时抱佛脚。。 这道题可以转化为max{点x到点k的距离}。因为带权图&#xff08;权值为正…

[超详细]3种方法判断一个数是否为质数(Python)

(发现好多博客对第三种进阶方法说的不明白&#xff0c;至少我是没完全看明白。后面结合自己的理解应该算是弄懂了&#xff0c;供大家参考&#xff0c;欢迎纠正。) 方法一&#xff1a;最暴力&#xff0c;最简单&#xff0c;也最耗时O(n) 思想&#xff1a;由素数的定义&#xf…

arcgis 无法编辑元素的解决办法(无法删除元素或者缺失值替换)

打开“编辑器”中&#xff0c;“开始编辑”即可进行元素编辑&#xff0c;也可进行缺失值替换 &#xff08;其他方式&#xff1a;选中图层&#xff0c;右击点击开始编辑&#xff09; 在元素编辑状态下无法删除变量&#xff0c;可以删除元素 元素编辑结束后 点击“编辑器”&…

深入剖析Spring WebFlux:从MethodHandler到反射获取请求信息的源码之旅

文章目录 前言一、获取请求执行的类、方法信息二、获取请求url变量三、获取请求处理数据总结 前言 最近想写一个代办事项后台服务&#xff0c;底层&#xff0c;选型WebFlux。在操作层面上&#xff0c;针对部分操作&#xff0c;想在不侵入业务代码的前提下&#xff0c;记录操作…

使用 Seq2Seq 模型进行文本摘要

目录 引言 1 导入数据集 2 清洗数据集 3 确定允许的最大序列长度 4 选择合理的文本和摘要 5 对文本进行标记 6 删除空文本和摘要 7 构建模型 7.1 编码器 7.2 解码器 8 训练模型 9 测试模型 10 注意 11 整体代码 引言 文本摘要是指在捕捉其本质的同时缩短长文本的…

主从复制与读写分离

前言&#xff1a; 在企业应用中&#xff0c;成熟的业务通常数据量都比较大&#xff0c;单台MySQL在安全性、高可用性和高并发方面 都无法满足实际的需求&#xff1f; 配置多台主从数据库服务器以实现读写分离 目录 一 主从复制的工作原理 ①MySQL的复制类型 ②主从复制过…

Netty组件优化之FastThreadLocal

ThreadLocal:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132995427 Netty中的FastThreadLocal是对Java中的FastThreadLocal的优化主要是为了解决ThreadLocal中线性查找 带来的性能下降同时实现快速查找和赋值 FastThreadLocal构建这里的index代表一个编号&#xff0c;从…