数据处理四 基于图像hash进行数据整理(删除重复图片、基于模版查找图片)

一、背景知识

1.1 什么是hash

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出。这个映射的规则就是对应的Hash算法,而原始数据映射后的二进制串就是哈希值。与指纹一样,就是以较短的信息来保证文件的唯一性的标志,这种标志与文件的每一个字节都相关,而且难以找到逆向规律。 活动开发中经常使用的MD5和SHA都是历史悠久的Hash算法。

hash算法的特点:

  • 从hash值不可以反向推导出原始的数据 不可逆
  • 输入数据的微小变化会得到完全不同的hash值,相同的数据会得到相同的值 唯一对应
  • hash算法的冲突概率要小 冲突概率小
  • 哈希算法的执行效率要高效,长的文本也能快速地计算出哈希值 高效计算

由于hash的原理是将输入空间的值映射成hash空间内,而hash值的空间远小于输入空间(输入空间是无限长度,而hash空间是有限的)。根据抽屉原理,一定会存在不同的输入被映射成相同输出的情况。那么作为一个好的hash算法,就需要这种冲突的概率尽可能小。
以上内容参考自:https://zhuanlan.zhihu.com/p/309675754

一般使用hash算法是为了校验文件是否被篡改或有传输损失。例如:某网站提供了文件下载地址和文件hash,我们下载文件后可以通过校验hash,确认文件没有发生传输损失(我下载的文件hash值,与网站公布的hash值一致)。又例如:某计算机考试,让学生提交作业文档和文档hash值给老师,确保作业未被篡改。

1.2 图片hash

哈希相似度算法(Hash algorithm),它的作用是对每张图片生成一个固定位数的Hash 值(指纹 fingerprint)字符串,然后比较不同图片的指纹,结果越接近,就说明图片越相似。图像Hash算法准确的说有三种,分别为平均哈希算法(aHash)、感知哈希算法你(pHash)和差异哈哈希算法(dHash)。

图像hash与上文中描述的hash算法目的不同,图像hash主要可用于判断或查找相似的图片,我们要尽可能的是图像hash值具有意义,与内容相关。他应当具备以下特点:

  • 1、高效计算,能适应于不同尺寸的图像(图像hash都要进行resize(8x8)

  • 2、存在相似性,使相似的图像hash值相似(根据图像的内容生成hash值

    三种Hash算法都是通过获取图片的hash值,再比较两张图片hash值的汉明距离来度量两张图片是否相似。两张图片越相似,那么两张图片的hash数的汉明距离越小。

平均哈希算法(aHash)

平均哈希算法是三种Hash算法中最简单的一种,它通过下面几个步骤来获得图片的Hash值,这几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 算像素均值;(4)根据相似均值计算指纹。具体算法如下所示:
在这里插入图片描述
得到图片的ahash值后,比较两张图片ahash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。汉明距离:字符串差异计算,相同位置下字符不同,则距离值加1

感知哈希算法(pHash)

感知哈希算法是三种Hash算法中较为复杂的一种,它是基于DCT(离散余弦变换)来得到图片的hash值,其算法几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 计算DCT;(4)缩小DCT; (5)算平均值;(6) 计算指纹。具体算法如下所示:
在这里插入图片描述

得到图片的phash值后,比较两张图片phash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。

差异哈希算法(dHash)

相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。其算法几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 算差异值;(4) 计算指纹。具体算法如下所示:
在这里插入图片描述
得到图片的phash值后,比较两张图片phash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。
以上内容参考自:https://www.cnblogs.com/Yumeka/p/11260808.html

二、图片hash的运用

2.1 删除重复图片

要删除文件夹内重复的图片,可以使用 imagededup库。 imagededup是一个基于Python的图片查重工具库,它简化了在图像集合中查找精确重复和近似重复的任务。可以使用CNN(卷积神经网络)、PHash、DHash、WHash(小波散列)、以及AHash这几种方法之一对图像生成编码,然后根据编码进行比对图像是否重复,并提供一些工具生成图片重复项快照​。

在这里插入图片描述
通过 pip 安装
安装命令

 pip install imagededup
具体使用案例

对一个文件夹内相同图片进行去重操作。本博文运用的是PHash(感知hash算法)。原始文件夹内的数据如下图所示:
在这里插入图片描述
注意如果是windows系统的话要加上if name==‘main’: ,因为它会默认使用多线程进行处理,不加的话会报错。
完整代码:

import os
from imagededup.methods import PHashdef process_file(img_path):"""处理图片去重:return:"""try:phasher = PHash()#WHash、AHash# 生成图像目录中所有图像的二值hash编码encodings = phasher.encode_images(image_dir=img_path)#print(encodings)# 对已编码图像寻找重复图像duplicates = phasher.find_duplicates(encoding_map=encodings)print(duplicates)only_img = []  # 唯一图片like_img = []  # 相似图片for img, img_list in duplicates.items():if img not in only_img and img not in like_img:only_img.append(img)like_img.extend(img_list)# 删除文件for like in like_img:print("like:  ",like)like_src = os.path.join(img_path, like)if os.path.exists(like_src):os.remove(like_src)except Exception as e:print(e)if __name__ == "__main__":img_path = "D:/实战项目/图像清理/1123"process_file(img_path)

代码运行输出如下所示:like即为找出的相似图片
在这里插入图片描述

代码运行后,文件夹内的图片如下所示,将大部分重复的图像进行删除。
在这里插入图片描述
这个方法的核心步骤是通过计算图片的哈希值进行比较,因为哈希值在一定程度上能够反映出图片的内容特征,所以相同或相似的图片的哈希值也会相对接近。通过利用哈希值进行比较,能够快速找出重复的图片并删除。
需要注意的是,由于哈希值是通过将图片文件转化为数值进行计算得出的,所以不能保证100%的准确性。在实际操作中,可能会存在一些不同的图片被误判为重复图片,或者相同的图片被误判为不同图片的情况。因此,在删除重复图片之前,建议先备份图片并进行人工审核,确保没有误删重要的图片。

2.2 基于模板查找图片

基于模板查找图片是在给定模版图片的情况下,到图像数据库下查找出类似的图片。在本次任务重,模版图片为没有钢卷的图像(图像数据库的图像基本分为有钢卷和无钢卷)。

根据实际数据情况,将数据分为有钢卷和没钢卷,因为钢卷在图像的中心,所以不需要计算周围的相似区域(相似区域会混淆hash值)。故此,我们定义chash函数,其步骤如下,具体如下图所示。
1、将图像resize到固定尺寸
2、截取出图像的中心区域
3、计算图像中心区域的ahash值(可以根据效果调整,选择其他的hash算法
在这里插入图片描述
根据模版图片删除相似图片的步骤如下:

  • 1、获取文件夹内所有图片 => all_list
  • 2、读取模版图片 => temp_mat
  • 3、计算模版图片chash值 => temp_hash 根据个人数据情况使用hash算法,如ahash、dhash、phash等
  • 4、计算每一个图片hash值 =>img_hash
  • 5、将all_list里面的图片hash值(img_hash)和模版图片hash值(temp_hash)进行对比,相同则移动到temp文件夹内

完整代码如下


import cv2,os
import numpy as np
# 均值哈希算法
def ahash(image):# 将图片缩放为8*8的image =  cv2.resize(image, (8,8), interpolation=cv2.INTER_CUBIC)# 将图片转化为灰度图gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)# s为像素和初始灰度值,hash_str为哈希值初始值s = 0ahash_str = ''# 遍历像素累加和for i in range(8):for j in range(8):s = s+gray[i, j]# 计算像素平均值avg = s/64# 灰度大于平均值为1相反为0,得到图片的平均哈希值,此时得到的hash值为64位的01字符串ahash_str  = ''for i in range(8):for j in range(8):if gray[i,j]>avg:ahash_str = ahash_str + '1'else:ahash_str = ahash_str + '0'result = ''for i in range(0, 64, 4):result += ''.join('%x' % int(ahash_str[i: i + 4], 2))# print("ahash值:",result)return result# 差异值哈希算法
def dhash(image):# 将图片转化为8*8image = cv2.resize(image,(9,8),interpolation=cv2.INTER_CUBIC )# 将图片转化为灰度图gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)dhash_str = ''for i in range(8):for j in range(8):if gray[i,j]>gray[i, j+1]:dhash_str = dhash_str + '1'else:dhash_str = dhash_str + '0'result = ''for i in range(0, 64, 4):result += ''.join('%x'%int(dhash_str[i: i+4],2))# print("dhash值",result)return result# 计算hash值
def phash(img):img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)img=img.astype(np.float32)#step2:离散余弦变换img=cv2.dct(img)img=img[0:8,0:8]sum=0.hash_str=''#step3:计算均值# avg = np.sum(img) / 64.0for i in range(8):for j in range(8):sum+=img[i,j]avg=sum/64#step4:获得哈希for i in range(8):for j in range(8):if img[i,j]>avg:hash_str=hash_str+'1'else:hash_str=hash_str+'0'return hash_str# 中心hash算法 
def crop_center(image):image =  cv2.resize(image, (900,900))image=image[300:600,300:600]#image=image[350:550,350:550]return image
def chash(image):cimage=crop_center(image)hash_value=ahash(cimage)return hash_value# 计算两个哈希值之间的差异
def campHash(hash1, hash2):n = 0# hash长度不同返回-1,此时不能比较if len(hash1) != len(hash2):return -1# 如果hash长度相同遍历长度for i in range(len(hash1)):if hash1[i] != hash2[i]:n = n+1return nif __name__ == "__main__":#读取并计算模版图片中心的ahash值temp_mat='temp.jpg' #模版路径temp=cv2.imread(temp_mat)temp_hash = chash(temp)print('temp的ahash值',temp_hash)#创建temp文件夹,用于保存和模版相似的图片del_path="temp/"os.makedirs(del_path,exist_ok=True)#读取并计算文件夹内图片中心的ahash值img_path = "图片路径/"all_list=os.listdir(img_path)for p in all_list:img=cv2.imread(img_path+p)img_hash = chash(img)#计算图片和模版图片hash值的差异,并将差异小于10的图片移动到temp文件夹内dif= campHash(temp_hash,img_hash)#print('img的ahash值',dif,p)#continueif dif<10:print('img的ahash值',dif,p)os.rename(img_path+p,del_path+p)

图片路径中图片如下
在这里插入图片描述
temp.jpg 模版图片如下所示
在这里插入图片描述
代码执行完后找到的重复图像如下
在这里插入图片描述

代码执行时输出如下所示

img的ahash值 3 T2023-11-15_11-20-44.jpg
img的ahash值 2 T2023-11-15_12-23-59.jpg
img的ahash值 6 T2023-11-16_13-28-01.jpg
img的ahash值 7 T2023-11-16_21-48-58.jpg
img的ahash值 8 T2023-11-17_06-24-17.jpg
img的ahash值 7 T2023-11-18_11-00-37.jpg
img的ahash值 9 T2023-11-18_11-00-43.jpg
img的ahash值 6 T2023-11-18_11-55-30.jpg
img的ahash值 5 T2023-11-18_11-56-24.jpg
img的ahash值 9 T2023-11-18_11-57-40.jpg
img的ahash值 5 T2023-11-18_12-51-23.jpg
img的ahash值 5 T2023-11-18_12-52-17.jpg
img的ahash值 6 T2023-11-18_22-57-15.jpg
img的ahash值 8 T2023-11-18_23-11-26.jpg
img的ahash值 6 T2023-11-21_00-24-43.jpg
img的ahash值 5 T2023-11-21_13-37-37.jpg
img的ahash值 6 T2023-11-22_02-51-48.jpg

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

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

相关文章

程序员必知!命令模式的实战应用与案例分析

命令模式是一种行为设计模式&#xff0c;它将请求封装为对象以实现客户端参数化、请求排队、日志记录及撤销操作&#xff0c;旨在解耦调用者与操作实现者&#xff0c;以智能家居为例&#xff0c;用户通过界面发送命令对象&#xff0c;设备作为接收者执行相应操作&#xff0c;无…

Ubuntu 安装Nginx服务

文章目录 前言一、Nginx安装1. Nginx默认安装2. Nginx指定版本安装3. Nginx验证4. Nginx服务控制4.1 查看服务状态4.2 停止服务4.3 启动服务4.4 重启服务 5. Nginx文件存放目录 二、自己编译Nginx1. 下载源码2. 依赖配置3. 编译 三、Nginx卸载总结 前言 Nginx&#xff08;发音为…

机器学习(四) -- 模型评估(3)

系列文章目录 机器学习&#xff08;一&#xff09; -- 概述 机器学习&#xff08;二&#xff09; -- 数据预处理&#xff08;1-3&#xff09; 机器学习&#xff08;三&#xff09; -- 特征工程&#xff08;1-2&#xff09; 机器学习&#xff08;四&#xff09; -- 模型评估…

探索 OceanBase 中图数据的实现

在数据管理和处理的现代环境中&#xff0c;对能够处理复杂数据结构的复杂数据模型和方法的需求从未如此迫切。图数据的出现以其自然直观地表示复杂关系的独特能力&#xff0c;开辟了数据分析的新领域。 虽然 Neo4j 等成熟的图形数据库为处理图形数据提供了强大的解决方案&…

如何理解Transformer论文中的positional encoding,和三角函数有什么关系?

大家好&#xff0c;我分享交流下这个问题。 Positional Encoding 掏出一张被无数人讲述的架构图。 Transformer 模型中的位置编码&#xff08;Positional Encoding&#xff09;是为了让模型能够考虑单词在句子中的位置。 由于 Transformer 的自注意力&#xff08;Self-Atte…

bat批处理文件_bat注释汇总

文章目录 1、示例&#xff08;直接结合脚本和结果进行理解&#xff09; 1、示例&#xff08;直接结合脚本和结果进行理解&#xff09; %这是一个注释% %这是另一个注释%rem 这是一个注释 rem 这是另一个注释:这是一个注释 ::这是一个注释 :?这是另一个注释if 1 1 ( %这里会执…

伐木工 - 华为OD统一考试

OD统一考试 题解&#xff1a; Java / Python / C 题目描述 一根X米长的树木&#xff0c;伐木工切割成不同长度的木材后进行交易&#xff0c;交易价格为每根木头长度的乘积。规定切割后的每根木头长度都为正整数,也可以不切割&#xff0c;直接拿整根树木进行交易。请问伐木工如…

libexif库介绍

libexif是一个用于解析、编辑和保存EXIF数据的库。它支持EXIF 2.1标准(以及2.2中的大多数)中描述的所有EXIF标签。它是用纯C语言编写的&#xff0c;不需要任何额外的库。源码地址&#xff1a;https://github.com/libexif/libexif &#xff0c;最新发布版本为0.6.24&#xff0c;…

深度学习中的自动化标签转换:对数据集所有标签做映射转换

在机器学习中&#xff0c;特别是在涉及图像识别或分类的项目中&#xff0c;标签数据的组织和准确性至关重要。本文探讨了一个旨在高效转换标签数据的 Python 脚本。该脚本在需要更新或更改类标签的场景中特别有用&#xff0c;这是正在进行的机器学习项目中的常见任务。我们将逐…

基于JavaWeb+SSM+Vue家政项目微信小程序系统的设计和实现

基于JavaWebSSMVue家政项目微信小程序系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 目录 1系统概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系统设计思想 1 2相关技术 2…

MyBatis 进阶

MyBatis 进阶 复杂CURD返回设置返回类型&#xff1a;resultType返回字典映射&#xff1a;resultMap 多表查询动态SQL使⽤<<if>if>标签<trim\>标签<where\>标签<set\>标签<foreach\>标签 其他打开日志单元测试不污染数据库 复杂CURD 返回设…

Model::unguard()的作用

这是在生成假数据时碰见的&#xff0c;浅查了一下 Model::unguard() 是 Laravel 框架中的一个方法&#xff0c;它的作用是取消对 Eloquent 模型的属性赋值的安全性保护。 在默认情况下&#xff0c;Laravel 的 Eloquent 模型会对属性赋值做一些安全性检查&#xff0c;例如防止…

Java:IO流详解

文章目录 基础流1、IO概述1.1 什么是IO1.2 IO的分类1.3 顶级父类们 2、字节流2.1 一切皆为字节2.2 字节输出流 OutputStream2.3 FileOutputStream类2.3.1 构造方法2.3.2 写出字节数据2.3.3 数据追加续写2.3.4 写出换行 2.4 字节输入流 InputStream2.5 FileInputStream类2.5.1 构…

LeetCode 225.用队列实现栈(详解) ૮꒰ ˶• ༝ •˶꒱ა

题目详情&#xff1a; 思路&#xff1a;1.定义两个队列用于存储栈的数据&#xff0c;其中一个为空。 2.对我们定义的栈进行入数据&#xff0c;就相当于对不为空的队列进行入数据。 3.对我们定义的栈进行删除&#xff0c;相当于取出不为空的队列中的数据放到为空的队列中&#x…

Python基础入门第八课笔记(自定义函数 lambda)

什么时候用lambda表达式&#xff1f; 当函数有一个返回值&#xff0c;且只有一句代码&#xff0c;可以用lambda简写。 2、lanbda语法 lambda 形参 : 表达式 注意&#xff1a; 1、形参可以省略&#xff0c;函数的参数在lambda中也适用 2、lambda函数能接收任何数量的参数但只能…

MySQL之视图内连接、外连接、子查询案例

目录 一.视图 1.1 含义 1.2 操作 二.案例 三.思维导图 一.视图 1.1 含义 虚拟表&#xff0c;查询方面和普通表一样使用。 1.2 操作 1.创建视图&#xff1a; create or replace view 视图名 as 查询语句&#xff1b; 2.视图的修改&#xff1a; 方式1 create or replace view …

了解长短期记忆 (LSTM) 网络:穿越时间和记忆的旅程

一、说明 在人工智能和机器学习的迷人世界中&#xff0c;长短期记忆 (LSTM) 网络作为一项突破性创新脱颖而出。LSTM 旨在解决传统循环神经网络 (RNN) 的局限性&#xff0c;尤其是在学习长期依赖性方面的局限性&#xff0c;彻底改变了我们在各个领域建模和预测序列的能力。本文深…

Nacos与Eureka

一、前言 在构建和管理微服务架构时&#xff0c;选择适当的服务注册中心至关重要。Nacos和Eureka都是微服务体系结构中常用的服务注册和发现工具。本文将探讨它们之间的区别&#xff0c;帮助开发者在选择适合其项目需求的注册中心时做出明智的决策。 二、架构和适用场景 Nacos …

Java/JDK下载安装与环境配置

Java由Sun Microsystems&#xff08;现在是Oracle的子公司&#xff09;于1995年首次发布。它是一种面向对象的编程语言&#xff0c;广泛应用于Web开发、移动应用程序开发、桌面应用程序开发和企业级应用程序开发等领域。 Java语言的主要特点是跨平台、可移植性强、安全性高和具…

【开源】基于JAVA语言的智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…