【Python实例学习笔记】图像相似度计算--哈希算法
【Python实例学习笔记】图像相似度计算--哈希算法
- 一、哈希算法的实现步骤:
- 二、对每一步都进行注解的代码
一、哈希算法的实现步骤:
1、缩小尺寸:
将图像缩小到8*8的尺寸,总共64个像素。这一步的作用是去除图像的细节,只保留结构/明暗等基本信息,摒弃不同尺寸/比例带来的图像差异;
2、简化色彩:
将缩小后的图像,转为64级灰度,即所有像素点总共只有64种颜色;
3、计算平均值:
计算所有64个像素的灰度平均值;
4、比较像素的灰度:
将每个像素的灰度,与平均值进行比较,大于或等于平均值记为1,小于平均值记为0;
5、计算哈希值:
将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图像的指纹。组合的次序并不重要,只要保证所有图像都采用同样次序就行了;
7、计算汉明距离
得到指纹以后,就可以对比不同的图像,看看64位中有多少位是不一样的。在理论上,这等同于”汉明距离”(Hamming distance,在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数)。如果不相同的数据位数不超过5,就说明两张图像很相似;如果大于10,就说明这是两张不同的图像。
二、对每一步都进行注解的代码
由于本人刚刚开始学习Python,所以,代码注解比较多。
这个Python代码也是在别人的参考代码,我为了学习找来写了注解并且做了一些修改,在Python 3.12.8中运行成功。修改的都是一些真的Python3的修改,参考文章是2013年的。
#!/usr/bin/python
# 指定脚本的解释器路径,表示使用 /usr/bin/python 来运行这个脚本
'''
导入所需的模块:
glob 用于文件模式匹配,
os 用于操作系统相关功能,
sys 用于访问命令行参数,
PIL(Python Imaging Library)中的 Image 用于图像处理。
'''
import glob
import os
import sys
from functools import reducefrom PIL import Image# 定义支持的图像文件扩展名
EXTS = 'jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG''''
该函数用于计算图像的平均哈希值(aHash)。
功能:
1. 将输入的图像调整为 8x8 像素大小,并转换为灰度图。
2. 计算图像的平均像素值。
3. 根据平均值,将每个像素值转换为二进制值(0 或 1)。
4. 将这些二进制值组合成一个 64 位的整数,作为图像的哈希值。
用途:
- 生成图像的指纹(哈希值),用于快速比较图像的相似性。
参数:
- im: 可以是一个 PIL.Image.Image 对象或图像文件路径。
返回值:
- 一个整数,表示图像的平均哈希值。
'''
def avhash(im):# 如果输入不是 Image 对象,则打开图像文件if not isinstance(im, Image.Image):im = Image.open(im)# 第一步,缩小尺寸。# 第二步,简化色彩。# 将图像调整为 8x8 像素,转换为灰度图# im = im.resize((8, 8), Image.ANTIALIAS).convert('L')im = im.resize((8, 8), Image.Resampling.LANCZOS).convert('L')# 第三步,计算平均值。# 计算图像的平均像素值avg = reduce(lambda x, y: x + y, im.getdata()) / 64.# return reduce(lambda x, (y, z): x | (z << y),# enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())),# 0)# 第四步,比较像素的灰度。# 根据平均值,将每个像素值转换为 0 或 1,生成哈希值# 获取图像的像素数据pixels = im.getdata()# 将每个像素值与平均值比较,生成二进制序列#这就是这张图片的指纹,这个指纹是一个64位的二进制数,我们可以通过这个指纹来判断两张图片是否相似。 binary_sequence = map(lambda i: 0 if i < avg else 1, pixels)# 第五步,计算哈希值。# 枚举二进制序列,生成索引和值的元组序列。# 生成的 (index, value) 序列,表示像素索引和二值化结果。enumerated_sequence = enumerate(binary_sequence)# 使用 reduce 函数将枚举后的序列累积为一个整数hash_value = reduce(lambda x, yz: x | (yz[1] << yz[0]), enumerated_sequence, 0)# 将哈希值转换为二进制字符串并打印binary_hash = bin(hash_value)[2:].zfill(64)print(f"Hash binary representation: {binary_hash}") # 返回哈希值return hash_valuedef hamming(h1, h2):# 计算两个哈希值之间的汉明距离(不同位的数量)h, d = 0, h1 ^ h2while d:h += 1#这是一种高效的位操作技巧,用于清除 d 中最低位的 1。#例如:d = 0110,d - 1 = 0101,d & (d - 1) = 0100。d &= d - 1return h'''
第一个参数是基准图片,
第二个参数是用来比较的其他图片所在的目录,
返回结果是两张图片之间不相同的数据位数量(汉明距离)。
'''
if __name__ == '__main__':# 检查命令行参数的数量,如果不符合要求,打印用法说明# if len(sys.argv) <= 1 or len(sys.argv) > 3:# print("{} Usage: {} image.jpg [dir]".format(sys.argv[0], sys.argv[0])) # print(f"{sys.argv[0]} Usage: {sys.argv[0]} image.jpg [dir]")# else:# # else则执行后面的语句,而执行内容可以多行,以缩进来区分表示同一范围。# # 从命令行参数中读取两个值:im 和 wd# # im 被设置为 sys.argv[1],即命令行中的第一个参数(脚本名称之后的第一个值)# # wd 的值则取决于命令行参数的数量# # 如果 len(sys.argv) < 3,即命令行参数的数量少于 3 个(只包括脚本名称和一个参数),那么 wd 被设置为字符串 '.'# # 否则,如果命令行参数的数量大于或等于 3 个,那么 wd 被设置为 sys.argv[2],即命令行中的第二个参数# im, wd = sys.argv[1], '.' if len(sys.argv) < 3 else sys.argv[2]im = '/Users/jp/Desktop/comparePic/pic1/frame_0005.png'wd = '/Users/jp/Desktop/comparePic/pic1'# 计算基准图像的哈希值h = avhash(im)# 切换到工作目录os.chdir(wd)images = []# 查找所有支持的图像文件for ext in EXTS:images.extend(glob.glob('*.%s' % ext))seq = []# 如果图像数量超过 50 且输出到终端,显示进度prog = int(len(images) > 20 and sys.stdout.isatty())for f in images:# 计算每个图像与基准图像之间的汉明距离seq.append((f, hamming(avhash(f), h)))if prog:perc = 100. * prog / len(images)x = int(2 * perc / 5)print ('\rCalculating... [' + '#' * x + ' ' * (40 - x) + ']'),print ('%.2f%%' % perc, '(%d/%d)' % (prog, len(images))),sys.stdout.flush()prog += 1if prog: print()# 按汉明距离排序并打印结果for f, ham in sorted(seq, key=lambda i: i[1]):print("{}\t{}".format(ham, f))
参考文章链接:
https://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html
https://www.ruanyifeng.com/blog/2011/07/imgHash.txt
相关文章:
【Python实例学习笔记】图像相似度计算--哈希算法
【Python实例学习笔记】图像相似度计算--哈希算法 一、哈希算法的实现步骤:二、对每一步都进行注解的代码 一、哈希算法的实现步骤: 1、缩小尺寸: 将图像缩小到8*8的尺寸,总共64个像素。这一步的作用是去除图像的细节,…...
2025DevSecOps标杆案例|智能制造国际领导厂商敏捷安全工具链实践
某智能制造国际领导厂商是涵盖智能家居、楼宇科技,工业技术、机器人与自动化和数字化创新业务五大业务板块为一体的全球化科技集团,连续入选《财富》世界500强,每年为全球超过4亿用户、各领域的重要客户与战略合作伙伴提供产品和服务。 数智化…...
【YOLOv11】目标检测任务-实操过程
目录 一、torch环境安装1.1 创建虚拟环境1.2 启动虚拟环境1.3 安装pytorch1.4 验证cuda是否可用 二、yolo模型推理2.1 下载yolo模型2.2 创建模型推理文件2.3 推理结果保存路径 三、labelimg数据标注3.1 安装labelimg3.2 解决浮点数报错3.3 labelimg UI界面介绍3.4 数据标注案例…...
第十七章:Python数据可视化工工具-Pyecharts库
一、Pyecharts简介 资源绑定附上完整资源供读者参考学习! Pyecharts是一个基于百度开源可视化库ECharts的Python数据可视化工具,支持生成交互式的HTML格式图表。相较于Matplotlib等静态图表库,Pyecharts具有以下优势: 丰富的图表…...
解决【vite-plugin-top-level-await】 插件导致的 Bindings Not Found 错误
解决【vite-plugin-top-level-await】 插件导致的 Bindings Not Found 错误 环境设置 操作系统: macOS硬件平台: M1 Pro前端框架: Vue 3Node.js 版本: 20 在使用 Vue 项目时,我们尝试集成 vite-plugin-top-level-await 插件以支持顶层 await 语法。然而ÿ…...
《八大排序算法》
相关概念 排序:使一串记录,按照其中某个或某些关键字的大小,递增或递减的排列起来。稳定性:它描述了在排序过程中,相等元素的相对顺序是否保持不变。假设在待排序的序列中,有两个元素a和b,它们…...
六十天前端强化训练之第三十七天之Docker 容器化部署实战指南(大师级详解)
欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、Docker 核心知识体系 1.1 容器革命:改变开发方式的技术 1.2 Docker 三剑客 1.3 Docker 生命周期管理 1.4 关键命令详解 二、前端容器化实战案例ÿ…...
RabbitMQ--延迟队列事务消息分发
目录 1.延迟队列 1.1应用场景 1.2利用TTL死信队列模拟延迟队列存在的问题 1.3延迟队列插件 1.4常见面试题 2.事务 2.1配置事务管理器 3.消息分发 3.1概念 3.2应用场景 3.2.1限流 3.2.2负载均衡 1.延迟队列 延迟队列(Delayed Queue),即消息被发送以后, 并…...
列表,元组,字典,集合,之间的嵌套关系
在 Python 中,列表、元组、字典和集合的嵌套关系需要遵循各自的特性(如可变性、可哈希性)。以下是它们之间的嵌套规则、示例和典型应用场景的详细梳理: 1. 列表(List)的嵌套 特性: 可变、有序…...
【行驶证识别】批量咕嘎OCR识别行驶证照片复印件图片里的文字信息保存表格或改名字,基于QT和腾讯云api_ocr的实现方式
项目背景 在许多业务场景中,如物流管理、车辆租赁、保险理赔等,常常需要处理大量的行驶证照片复印件。手动录入行驶证上的文字信息,像车主姓名、车辆型号、车牌号码等,不仅效率低下,还容易出现人为错误。借助 OCR(光学字符识别)技术,能够自动识别行驶证图片中的文字信…...
鸿蒙HarmonyOS NEXT设备升级应用数据迁移流程
数据迁移是什么 什么是数据迁移,对用户来讲就是本地数据的迁移,终端设备从HarmonyOS 3.1 Release API 9及之前版本(单框架)迁移到HarmonyOS NEXT(双框架)后保证本地数据不丢失。例如,我在某APP…...
MCP从零开始
MCP简介 MCP,全称是Model Context Protocol,模型上下文协议,由Claude母公司Anthropic于去年11月正式提出。MCP解决的最大痛点就是Agent开发中调用外部工具的技术门槛过高的问题。 能调用外部工具,是大模型进化为智能体Agent的关…...
Three.js 快速入门教程【十九】CSS2DRenderer(CSS2D渲染器)介绍,实现场景中物体或设备标注标签信息
系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…...
横扫SQL面试——连续性登录问题
横扫SQL面试 📌 连续性登录问题 在互联网公司的SQL面试中,连续性问题堪称“必考之王”。💻🔍 用户连续登录7天送优惠券🌟,服务器连续报警3次触发熔断⚠️,图书馆连续3天人流破百开启限流⚡” …...
爱因斯坦求和 torch
目录 向量点积 矩阵乘法 矩阵转置 向量转换相机坐标系 在 Python 的科学计算库(如 NumPy)中,einsum 是一个强大的函数,它可以简洁地表示各种张量运算。下面是几个不同类型的使用示例: 向量点积 向量点积是两个向量…...
Spring Initializr搭建spring boot项目
介绍 Spring Initializr 是一个用于快速生成 Spring Boot 项目结构的工具。它为开发者提供了一种便捷的方式,可以从预先定义的模板中创建一个新的 Spring Boot 应用程序,从而节省了从头开始设置项目的大量时间。 使用 Spring Initializr,你…...
【实战】渗透测试下的文件操作
目录 Linux查找文件 Windows查找文件 查找可写目录 windows Linux 创建 Windows Linux 压缩 解压 远程解压文件 Linux查找文件 >find / -name index.php 查找木马文件 >find . -name *.php | xargs grep -n eval( >find . -name *.php | xargs grep -n ass…...
MATLAB 控制系统设计与仿真 - 30
用极点配置设计伺服系统 方法2-反馈修正 如果我们想只用前馈校正输入,从而达到伺服控制的效果,我们需要很精确的知道系统的参数模型,否则系统输出仍然具有较大的静态误差。 但是如果我们在误差比较器和系统的前馈通道之间插入一个积分器&a…...
P1091 [NOIP 2004 提高组] 合唱队形
题目链接: 思路: 题目意思,找出最少的同学出列,保证学生 1-t 上升, t-n 下降。我们只要求出每个点的最长上升子序列和最长不上升子序列,然后总人数-最长上升子序列和最长不上升子序列1,就是最少…...
小林coding-12道Spring面试题
1.说一下你对 Spring 的理解?spring的核心思想说说你的理解? 2.Spring IoC和AOP 介绍一下?Spring的aop介绍一下?IOC和AOP是通过什么机制来实现的?怎么理解SpringIoc?依赖倒置,依赖注入,控制反转分别是什么?依赖注…...
通过Spring Boot集成WebSocket进行消息通信
文章目录 通过Spring Boot集成WebSocket进行消息通信1. 创建 Spring Boot 项目2. 添加 WebSocket 依赖3. 配置 WebSocket4. 创建 WebSocket 处理器5. 创建控制器(可选)6. 前端页面测试7. 运行项目注意事项 通过Spring Boot集成WebSocket进行消息通信 1.…...
ComfyUI发展全景:从AI绘画新星到多功能创意平台的崛起
在人工智能技术迅猛发展的浪潮中,ComfyUI作为基于Stable Diffusion的开源工具,已经从最初的AI绘画辅助软件成长为支持多模态创作的强大平台。本文将全面梳理ComfyUI的发展历程、技术特点、应用场景及其在AIGC生态中的独特地位,同时展望这一工…...
11-项目涉及设备的问题
我们部门在开发一些项目时,确实需要借用设备,但每次开发新需求时都要从硬件部门借设备,开发完成后又要归还。这种频繁的借还流程不仅增加了沟通成本,还导致项目负责人和开发人员对设备的功能和应用场景缺乏直观的了解。有时甚至连…...
将 Markdown 表格结构转换为Excel 文件
在数据管理和文档编写过程中,我们经常使用 Markdown 来记录表格数据。然而,Markdown 格式的表格在实际应用中不如 Excel 方便,特别是需要进一步处理数据时。因此,我们开发了一个使用 wxPython 的 GUI 工具,将 Markdown…...
C++学习之Linux文件编译、调试及库制作
目录 1.rwx对于文件和目录的区别 2.gcc编译过程 3.数据段合并和地址回填说明 4.gcc编译其他参数 5.函数库简介 6.静态库的使用 7.动态库的简介 8.动态库制作基本流程 9.启动APP错误解决方案12 10.启动APP错误解决方案34 11.makefile一组规则 12.makefile的两个函数 …...
neo4j中导入csv格式的三元组数据
csv数据格式: head_entity,relation,tail_entity 02.02类以外的脂肪乳化制品,包括混合的和(或)调味的脂肪乳化制品,允许添加,β-胡萝卜素 02.02类以外的脂肪乳化制品,包括混合的和(或)调味的脂…...
高项第十六章——项目采购管理
什么是采购管理?项目采购管理包括从项目团队外部采购或获取所需产品、服务或成果的各个过程。 项目采购管理包括编制和管理协议所需的管理和控制过程。 16_1 管理基础 什么是协议?协议是用于明确项目初步意向的任何文件或沟通结果,协议的范…...
架构师面试(二十二):TCP 协议
问题 今天我们聊一个非常常见的面试题目,不管前端还是后端,也不管做的是上层业务还是底层框架,更不管技术方向是运维还是架构,都可以思考和参与一下哈! TCP协议无处不在,我们知道 TCP 是基于连接的端到端…...
五.ubuntu20.04 - ffmpeg推拉流以及Nginx、SRS本地部署
一.本地部署nginx 1.编译ffmpeg,参考这位博主的,编译选项有的enable找不到的不需要的可以直接删除,但是像sdl(包含ffplay)、h264、h265这些需要提前下载好,里面都有下载指令。 Ubuntu20.04 编译安装 FFmp…...
JS 手撕题高频考点
前端面试中,JS 手撕题是高频考点,主要考察 编程能力、算法思维、JS 核心知识。以下是最常见的手撕题分类 代码示例: 目录 📌 1. 手写函数柯里化📌 2. 手写 debounce(防抖)📌 3. 手写…...
Hyperlane框架临时上下文数据管理:提升Web开发效率的利器
Hyperlane框架临时上下文数据管理:提升Web开发效率的利器 在现代Web开发中,临时上下文数据管理是实现高效请求处理的关键。Hyperlane框架通过创新的临时上下文存储机制,为开发者提供了一套简洁、安全的解决方案,让数据在请求生命…...
QT操作PDF文件
Qt 早期本身不提供原生的 PDF 操作功能。从 Qt 5.15 开始,Qt 提供了 PDF 模块,可以显示和提取 PDF 内容。Qt中有如下几种方式实现 PDF 文件的生成、读取和操作。 1、使用 QPrinter 生成 PDF 2、使用 Qt PDF 模块 (Qt 5.15+) 3、使用第三方库(比如:Poppler) 一、使用 Q…...
【算法手记8】NC95 数组中的最长连续子序列 字母收集
🦄个人主页:修修修也 🎏所属专栏:刷题 ⚙️操作环境:牛客网 目录 一.NC95 数组中的最长连续子序列 题目详情: 题目思路: 解题代码: 二.字母收集 题目详情: 题目思路: 解题代码: 结语 一.NC95 数组中的最长连续子序列 牛客网题目链接(点击即可跳转):NC95 …...
AI渗透测试:网络安全的“黑魔法”还是“白魔法”?
引言:AI渗透测试,安全圈的“新魔法师” 想象一下,你是个网络安全新手,手里攥着一堆工具,正准备硬着头皮上阵。这时,AI蹦出来,拍着胸脯说:“别慌,我3秒扫完漏洞࿰…...
使用perf工具分析Linux系统的性能瓶颈
想获取更多高质量的Java技术文章?欢迎访问Java技术小馆官网,持续更新优质内容,助力技术成长 Java技术小馆官网https://www.yuque.com/jtostring 使用perf工具分析Linux系统的性能瓶颈 在现代计算系统中,性能瓶颈是一个经常遇到…...
知识就是力量——HELLO GAME WORD!
你好!游戏世界! 简介环境配置前期准备好文章介绍创建头像小功能组件安装本地中文字库HSV颜色空间音频生成空白的音频 游戏UI开发加载动画注册登录界面UI界面第一版第二版 第一个游戏(贪吃蛇)第二个游戏(俄罗斯方块&…...
LeetCode算法题(Go语言实现)_20
题目 给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,请你返回一个长度为 2 的列表 answer ,其中: answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。 answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组成…...
ES拼音分词自动补全实现
#测试拼音分词 POST /_analyze { "text":"如家酒店真不错", "analyzer": "pinyin" } #这里把拼音的首字母放到这里,也说明了这句话没有被分词,而是作为一个整体出现的 #还把每一个字都形成了一个拼音&#…...
Spring Boot 日志 配置 SLF4J 和 Logback
文章目录 一、前言二、案例一:初识日志三、案例二:使用Lombok输出日志四、案例三:配置Logback 一、前言 在开发 Java 应用时,日志记录是不可或缺的一部分。日志可以记录应用的运行状态、错误信息和调试信息,帮助开发者…...
构建大语言模型应用:数据准备(第二部分)
本专栏通过检索增强生成(RAG)应用的视角来学习大语言模型(LLM)。 本系列文章 简介数据准备(本文)句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模型服务高级检索增强生成 RAG 如上…...
mac m 芯片 动态切换 jdk 版本jdk8.jdk11.jdk17
下载 jdk 版本. 默认安装路径在. /Library/Java/JavaVirtualMachines配置环境变量 # 动态获取所有 JDK 路径 export JAVA_8_HOME$(/usr/libexec/java_home -v 1.8) export JAVA_11_HOME$(/usr/libexec/java_home -v 11) export JAVA_17_HOME$(/usr/libexec/java_home -v 17)#…...
如何通过python将视频转换为字符视频
请欣赏另类的老鼠舞 字符老鼠舞 与原版对比 对比 实现过程 1. 安装库 pip install numpy pip install Pillow pip install opencv-python pip install moviepy 2. 读取视频帧并转换为灰度图 import cv2def make_video(input_video_path, output_video_path):video_cap cv2…...
如何高效备考蓝桥杯(c/c++)组
以下是针对蓝桥杯C/C组的高效备考策略,结合你的当前基础(C语法简单算法题),分阶段提升竞赛能力,重点突破高频考点: 一、蓝桥杯C/C组核心考点梳理 根据历年真题,重点考察以下内容(按…...
两数之和-力扣
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…...
react撤销和恢复
创建一个历史记录栈past,和一个撤销过的栈future,,在每次操作store的时候,将当前的store的数据,存入历史记录栈past中,, 如果是撤销操作,,就从这个历史栈中取最后面那个数…...
华为机试—密码验证合格程序
题目 你需要书写一个程序验证给定的密码是否合格。 合格的密码要求: 长度超过 8 位必须包含大写字母、小写字母、数字、特殊字符中的至少三种不能分割出两个独立的、长度大于 2 的连续子串,使得这两个子串完全相同;更具体地,如果…...
分布式ID生成器:雪花算法原理与应用解析
在互联网分布式系统中,生成全局唯一的ID是一个核心问题。传统的数据库自增ID、UUID虽然各有优缺点,但在高并发、分库分表场景下往往无法满足需求。美团Leaf分布式ID生成器便是为了解决这些问题而诞生的,其核心实现便是基于Snowflakeÿ…...
搭建Flutter开发环境 - MacOs
一、配置Flutter SDK 1.1 到官网下载Flutter SDK 打开Flutter中文社区网址,往下滚动,找到下载并安装Flutter,选择适合自己电脑的安装包进行下载。下载完毕后,解压放到你想要放置的目录下,我放到了 User/账户/develop…...
【Flutter学习(1)】Dart访问控制
疑问代码片段: class _MyHomePageState extends State<MyHomePage> {int _counter 0;void _incrementCounter() {setState(() {_counter;});} }对Flutter初始文件里下划线的疑问 为什么这里的类和申明的计数器都要在前面加一个下划线? 在 Dart 中…...
Day50 单词规律
给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 class Solution {public boolean wordPattern(String p…...