【以图搜图】Python实现根据图片批量匹配(查找)相似图片

news2024/12/23 16:05:19

目的:可以解决在本地实现根据图片查找相似图片的功能

背景:由于需要查找别人代码保存的图像的命名,但由于数据集是cifa10图像又小又多,所以直接找很费眼睛,所以实现用该代码根据图像查找图像,从而得到保存图像的命名。

方法:

1、将需要查找的图像(查询图像, queryImg)放入queryImgs文件夹,以及一个存放数据库图像的文件夹datasetImgs

2、批量读取查询图像

3、根据MSE(均方误差)和SSIM(结构相似性指数)计算权重,来比较两张图像的相似程度。

其中:

MSE(均方误差):计算两张图片的每个像素值之间的平均差值,结果越小表示两张图片越相似。

SSIM(结构相似性指数):比较两张图片的结构、亮度和对比度等方面的相似程度,结果介于-1到1之间,越接近1表示两张图片越相似。

weight=MSE\times (1-SSIM)

4、以224×224的大小显示当前queryImg和bestImg(数据库图像中相似度最高的图像),title为queryImg和bestImg的文件名。

5、将bestImg移动到命名为“dstImgs”的文件夹,并保留源文件名称。

运行速度:

在1万张32×32图像中,平均检索速度:34.64s左右(不包括对数据库图像使用transform统一大小),可以为权重设置阈值提前结束检索(建议阈值为小于10)。

限制:

1、需要明确查询图像和数据库图像的大小,并手动更改对应注释的代码。

2、检索结果唯一,不能检索到多个结果(由于我知道我的datasets里只有唯一对应的图像,所以代码逻辑是只保存最相似的图像,或第一个相似度权重小于10的图像),不过可以自行修改代码实现检索多个结果。

代码:

import os
import shutil
import time
from skimage.metrics import structural_similarity as compare_ssim
from torchvision.transforms import transforms
from PIL import Image
import cv2
import numpy as np

data_transform = transforms.Resize((32, 32))  # 数据库图像和查询图像统一大小,大小为32×32
show_transform = transforms.Resize((224, 224))  # 显示图像大小为224×224


def transformImg(img, transform):
    img = transform(Image.fromarray(img))
    img = np.array(img)
    return img


root_path = "./queryImgs"  # 查询图像所在的文件夹
dataset_path = "./datasetImgs"  # 数据库图像所在的文件夹

for query_img in os.listdir(root_path):
    query_img_path = os.path.join(root_path, query_img)
    query_img_obj = cv2.imread(query_img_path)
    query_img_obj = transformImg(query_img_obj, data_transform)

    best_mse = np.Inf
    best_ssim = np.Inf
    best_weight = np.Inf
    best_img_name = ""
    best_img_path = ""
    best_img_obj = None
    print("Start search Img: ", query_img)
    start_time = time.time()
    for dataset_img in os.listdir(dataset_path):
        dataset_img_path = os.path.join(dataset_path, dataset_img)
        dataset_img_obj = cv2.imread(dataset_img_path)
        # # 统一数据库图像大小, 若数据库图像大小一致则可以只调整查询图像大小。
        # dataset_img_obj = transformImg(dataset_img_obj, data_transform)
        mse = ((query_img_obj - dataset_img_obj) ** 2).mean()
        ssim = compare_ssim(query_img_obj, dataset_img_obj, channel_axis=query_img_obj.shape[2] - 1)
        weight = mse * (1 - ssim)
        if weight < best_weight:
            best_mse = mse
            best_ssim = ssim
            best_weight = weight
            best_img_path = dataset_img_path
            best_img_obj = dataset_img_obj
            best_img_name = dataset_img
            print(query_img, "->", dataset_img, ": ")
            print("\tmse: ", best_mse, " ssim: ", ssim, " weight: ", weight)

        # 权重小于10提前结束检索
        if best_weight < 10:
            break

    elapsed_time = time.time() - start_time

    best_img = np.hstack([transformImg(query_img_obj, show_transform), transformImg(best_img_obj, show_transform)])
    cv2.imshow("left: {}   right: {}".format(query_img, best_img_name), best_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    if not os.path.exists("./dstImgs"): os.mkdir("./dstImgs")
    shutil.copy(best_img_path, './dstImgs/' + best_img_name)
    print("save as: ", './dstImgs/' + best_img_name, " time elapsed: ", elapsed_time, "\n")

结果:

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

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

相关文章

azure刷新令牌失效 The grant was issued for a different client id

博主在以msal-node这个认证库实现electron客户端混合h5授权登录后&#xff0c;在某一次访问令牌过期后并且通过已存储的刷新令牌获取新的访问令牌和刷新令牌时&#xff0c;在控制台日志看到了The grant was issued for a different client id报错。 Error refreshing token: Se…

产品经理都在收藏的10个原型设计工具!

在产品经理的设计工作中&#xff0c;原型工具是必不可少的&#xff0c;今天本文将会为大家分享8个好用的原型工具&#xff0c;助力产品经理实现高效设计&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一款优秀的原型工具&#xff0c;它可以在网页中直接运行并…

CS162 13-17 虚拟内存

起源 为啥我们需要虚拟内存-----------需求是啥&#xff1f; 可以给程序提供一个统一的视图&#xff0c;比如多个程序运行同一个代码段的话&#xff0c;同一个kernel&#xff0c;就可以直接共享 cpu眼里的虚拟内存 无限内存的假象 设计迭代过程 为啥这样设计&#xff1f; 一…

P2404 自然数的拆分问题

题目 思路 最简单的dfs题之一 只需要一点点小优化 代码 #include<bits/stdc.h> using namespace std; const int maxn55; int n; int ans[maxn],s; void print(int tot) { for(int i1;i<tot-1;i) cout<<ans[i]<<""; cout<<ans[tot-1]&…

Spark-任务怎么切分

&#xff08;1&#xff09;Application&#xff1a;初始化一个SparkContext即生成一个Application&#xff1b; &#xff08;2&#xff09;Job&#xff1a;一个Action算子就会生成一个Job&#xff1b; &#xff08;3&#xff09;Stage&#xff1a;Stage等于宽依赖的个数加1&…

速成版-带您2天学完vue3框架+Element-plus框架

Vue是渐进式的JavaScript框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的web前端框架&#xff0c;vue算是目前最火的web前端框架之一&#xff0c;使用vue可以提升开发体验。Vue组件可以按照两种不同的风格写&#xff0c;即选项式api和组合式api两种。…

数据中心电子电气设备常见的五种地线种类和做法

数据中心机房计算机系统的集成化程度很高&#xff0c;其正常工作对环境的要求很严格。接地&#xff0c;是指电力系统和电气装置的中性点、电气设备的外露导电部分和装置外导电部分经由导体与大地相连。其作用主要是防止人身遭受电击、设备和线路遭受损坏、预防火灾和防止雷击、…

7.复合类型注解

目录 1 联合类型 2 交叉类型 2.1 基本使用 2.2 与继承的区别 1 联合类型 联合类型是 或 的关系 联合类型表示这个变量可以是多个类型&#xff0c;比如 a 可以是 数字或字符串 使用联合类型后改变到指定的类型就不会报错了 2 交叉类型 2.1 基本使用 交叉类型是 …

MB21 手工创建关于生产订单的预留

1、前面博文中有说到新增了工单超领的移动类型Z61,我们在创建新的移动类型的时候参考的是261的移动类型。本质上Z61的配置和261也是一样的。 2、我们在MB21创建预留的时候就会遇到问题 这里系统给出了提示:不能手工创建该类型的预留。 3、SE38对程序进行修改,根据报错的信…

Qt应用开发(基础篇)——布局管理 Layout Management

目录 一、前言 二&#xff1a;相关类 三、水平、垂直、网格和表单布局 四、尺寸策略 一、前言 在实际项目开发中&#xff0c;经常需要使用到布局&#xff0c;让控件自动排列&#xff0c;不仅节省控件还易于管控。Qt布局系统提供了一种简单而强大的方式来自动布局小部件中的…

docker 容器引擎基础(2)

目录 创建私有仓库 将修改过的nginx镜像做标记封装&#xff0c;准备上传到私有仓库 将镜像上传到私有仓库 从私有仓库中下载镜像到本地 CPU使用率 CPU共享比例 CPU周期限制 CPU 配额控制参数的混合案例 内存限制 Block IO 的限制 限制bps 和iops 创建私有仓库 仓库&a…

一起学SF框架系列5.12-spring-beans-数据绑定dataBinding

数据绑定有助于将用户输入动态绑定到应用程序的域模型&#xff08;或用于处理用户输入的任何对象&#xff09;&#xff0c;主要用于web层&#xff0c;但实际可用于任何层。Spring提供了DataBinder来做到这一点&#xff0c;并提供了Validator进行数据验证&#xff0c;两者组成了…

高通滤波器,低通滤波器

1.高通滤波器是根据像素与邻近像素的亮度差值来提升该像素的亮度。 import cv2 import numpy as np from scipy import ndimagekernel_3_3 np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]]) print(kernel_3_3) kernel_5_5 np.array([[-1,-1,-1,-1,-1],[-1,1,2,1,-1],[-1,2,4,2,-…

网络安全进阶学习第八课——信息收集

文章目录 一、什么是信息收集&#xff1f;二、信息收集的原则三、信息收集的分类1.主动信息收集2.被动信息收集 四、资产探测1、Whois查询#常用网站&#xff1a; 2、备案信息查询#常用网站&#xff1a; 3、DNS查询#常用网站&#xff1a; 4、子域名收集#常用网站&#xff1a;#常…

在访问一个网页时弹出的浏览器窗口,如何用selenium 网页自动化解决?

相信大家在使用selenium做网页自动化时&#xff0c;会遇到如下这样的一个场景&#xff1a; 在你使用get访问某一个网址时&#xff0c;会在页面中弹出如上图所示的弹出框。 首先想到是利用Alert类来处理它。 然而&#xff0c;很不幸&#xff0c;Alert类处理的结果就是没有结果…

SNAT和DNAT原理与应用

iptables的备份和还原 1.写在命令行当中的都是临时配置。 2.把我们的规则配置在 备份&#xff08;导出&#xff09;&#xff1a;iptables-save > /opt/iptables.bak 默认配置文件&#xff1a;/etc/sysconfig/iptables 永久配置&#xff1a;cat /opt/iptables.bak > /etc…

最近安全事件频发,分享一些如何在Sui上构建安全应用的建议

在Sui上构建任何应用程序的一个关键部分是防止恶意攻击和威胁行为。对安全性的重视对于减少用户的资产损失&#xff0c;以及降低对开发者和企业的声誉损害至关重要。 Sui安全和密码学社区的成员总结了一些开发者在开发过程中应该注意避免的最佳实践。虽然其中一些经验是单独针…

AD21 PCB设计的高级应用(十)Gerber文件转PCB

&#xff08;十&#xff09;Gerber文件转PCB Altium Designer 导入 Gerber 并转换成 PCB 的操作步骤如下: (1)打开 Altium Designer 软件,执行菜单栏中“文件”→“新的”→“项目”命令,新建一个 PCB Project,并且新建一个 CAM 文档添加到工程中,如图所示。 (2)Gerber 文件有两…

Web性能测试模型全面解读

前言 性能测试用例主要分为预期目标用户测试、用户并发测试、疲劳强度与大数据量测试、网络性能测试、服务器性能测试五大部分。 具体编写用例时要根据实际情况去进行&#xff0c;遵守低成本、策略为中心&#xff0c;裁减、完善模型&#xff0c;具体化等原则。 Web性能测试模…

视频监控汇聚平台EasyCVR告警消息生成后,合成录像显示不了是什么原因?

智能视频监控平台TSINGSEE青犀视频EasyCVR具备视频融合汇聚能力&#xff0c;作为安防视频监控综合管理平台&#xff0c;它支持多协议接入、多格式视频流分发&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&…