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

文章介绍了一种方法,通过计算MSE和SSIM来比较查询图像与数据库图像的相似度,实现在本地根据图片查找相似图片的功能。在32x32图像中,平均检索速度约为34.64秒,且支持设置权重阈值提前结束。代码使用了Python的OpenCV、PIL、skimage和PyTorch库。
摘要由CSDN通过智能技术生成

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

背景:由于需要查找别人代码保存的图像的命名,但由于数据集是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")

结果:

Java 中可以使用 OpenCV 库进行图片匹配,具体步骤如下: 1. 导入 OpenCV 库 需要在 Java 项目中导入 OpenCV 库,可以下载适合自己的版本,然后将其添加到项目的依赖中。 2. 加载图片 使用 `imread` 函数加载需要匹配图片和模板图片。 3. 转换图片格式 将图片转换为灰度图,使用 `cvtColor` 函数。 4. 进行模板匹配 使用 `matchTemplate` 函数进行模板匹配,可以选择不同的匹配算法,例如 `TM_SQDIFF`、`TM_SQDIFF_NORMED`、`TM_CCORR` 等。 5. 获取匹配结果 使用 `minMaxLoc` 函数获取匹配结果的坐标位置,可以选择不同的匹配方式(如最大值、最小值)。 6. 显示匹配结果 使用 `Imgproc.rectangle` 函数在原图上绘制匹配结果的矩形框。 下面是示例代码: ```java import org.opencv.core.Core; import org.opencv.core.Core.MinMaxLocResult; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.highgui.HighGui; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; public class ImageMatching { public static void main(String[] args) { // 加载 OpenCV 库 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 加载需要匹配图片和模板图片 Mat img = Imgcodecs.imread("path/to/image"); Mat tpl = Imgcodecs.imread("path/to/template"); // 转换为灰度图 Mat imgGray = new Mat(); Mat tplGray = new Mat(); Imgproc.cvtColor(img, imgGray, Imgproc.COLOR_BGR2GRAY); Imgproc.cvtColor(tpl, tplGray, Imgproc.COLOR_BGR2GRAY); // 模板匹配 Mat result = new Mat(); Imgproc.matchTemplate(imgGray, tplGray, result, Imgproc.TM_CCOEFF_NORMED); // 获取匹配结果的坐标位置 MinMaxLocResult mmr = Core.minMaxLoc(result); // 绘制矩形框 Point matchLoc = mmr.maxLoc; Imgproc.rectangle(img, matchLoc, new Point(matchLoc.x + tpl.cols(), matchLoc.y + tpl.rows()), new Scalar(0, 255, 0)); // 显示匹配结果 HighGui.imshow("Result", img); HighGui.waitKey(); } } ``` 注意:在使用 OpenCV 进行图片匹配时,需要注意图片的大小和质量,以及匹配算法的选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值