(图像匹配)用脚本找出图案中重复出现的匹配的两个最小单元

(图像匹配)用脚本找出图案中重复出现的匹配的两个最小单元

概述:运用图像匹配技术,找出一张图片中重复出现的最小单元,并用opencv库将它分别裁剪下来

参考的github——基于图像匹配模型patch2pix:[https://github.com/GrumpyZhou/patch2pix](https://github.com/GrumpyZhou/patch2pix)

1.环境:

安装环境的过程这边就不讲了,我用的是pytorch1.7.0+cuda10.2,如果pytorch版本过高模型会有warning。

老版本pytorch安装也很简单,进入pytorch官网,点install
在这里插入图片描述
再点previous verisons就可以了,需要注意的是要和自己的cuda版本匹配。

2.应用以及思路

在文件目录的example里有作者给出的示例脚本:
在这里插入图片描述
我们只要对visualize_matches.ipynb脚本进行修改即可,在修改之前也可以先运行一下,对应作者给的图片示例。
作者给出的图片都是两个对比的图片
在这里插入图片描述
举例:

在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述
那么我们怎么用图像匹配的思想,只输入一张图片,并且从一张图片中找出两个重复的部分呢?

举个例子,给出下面一张图,我要做的工作就是找出的就是它能匹配的两个最小的单元:
在这里插入图片描述

这里我用到的是滑动窗口的思想,默认第一个串口是我的左上角,串口大小我尝试了一下对于1440 * 900的图,窗口大小200* 200效果就很不错。

从纵向上每隔200像素滑动一个窗口,与地一个窗口进行比较,我们会得到一个matches的值,它里面保存的就是两个窗口匹配的像素点的坐标。通过坐标之间的像素差值,计算所有匹配的像素点的平均值,我们就可以粗略计算出图像块的周期,并且用cv将他裁剪出来。

下面给出我的脚本代码:

import sys
sys.path.append('..')
from argparse import Namespace
import os
import numpy as np
import pydegensac
from utils.common.plotting import plot_matches
from utils.eval.model_helper import *
import cv2
import time
np.set_printoptions(precision=2)

os.environ['CUDA_VISIBLE_DEVICES'] = '0'

METHOD = 'patch2pix'

if METHOD == 'nc':
    # Initialize ncnet matcher
    args = Namespace(ncn_thres=0.9, imsize=1024, ksize=2,
                     ckpt='../pretrained/ncn_ivd_5ep.pth')
    matcher = init_ncn_matcher(args)
else:
    # Initialize patch2pix matcher
    args = Namespace(io_thres=0.25, imsize=1024, ksize=2,
                     ckpt='../pretrained/patch2pix_pretrained.pth')
    matcher = init_patch2pix_matcher(args)

    ticks = time.time()
    img = cv2.imread('./images/1.jpg')
    w = img.shape[1]  # 图像的宽度
    h = img.shape[0]  # 图像的高度
    # (1000, 4096, 3)
    if max(w, h) > 2000:
        win = int(min(w, h) / 10)  # 设置滑动窗口的大小
    else:
        # win = int(min(w, h) / 5)
        win = 200 #设置窗口大小为200

    cv2.imwrite("./images/1_1.jpg", img[0:win, 0:win])
    im1_path = "./images/1_1.jpg"
    i = win
    count1 = count2 = cal = count = sum1 = sum2 = maxnum  = 0
    while i < h-win:
        # 裁剪坐标为[y0:y1, x0:x1]
        cv2.imwrite("./images/1_2.jpg", img[i:i + win, 0:win])
        im2_path = "./images/1_2.jpg"

        # Predict matches (with ransac geometric verification)
        matches, _, _ = matcher(im1_path, im2_path)
        _, inls = pydegensac.findFundamentalMatrix(matches[:, 0:2], matches[:, 2:4], 1.0)
        if len(matches) > maxnum:
            maxnum = max(maxnum, len(matches))
            temp = matches
            c = count
        i += win
        count += 1

    for j in range(0, len(temp)):
        if temp[j][3] > temp[j][1]:
            sum1 += temp[j][3] - temp[j][1] + win * c + win
            count1 += 1
        else:
            sum2 += temp[j][3] - temp[j][1] + win * c + win
            count2 += 1
        if count1 > count2:
            res = sum1 / count1
        else:
            res = sum2 / count2
    print("纵周期像素大小为{}".format(res))

    # step 2:
    count = count1 = count2 = maxnum = sum1 = sum2  = 0
    k = win
    while k < w-win:
        # 裁剪坐标为[y0:y1, x0:x1]
        cv2.imwrite("./images/1_3.jpg", img[0:win, k:k + win])
        im2_path = "./images/1_3.jpg"

        # Predict matches (with ransac geometric verification)
        matches, _, _ = matcher(im1_path, im2_path)
        _, inls = pydegensac.findFundamentalMatrix(matches[:, 0:2], matches[:, 2:4], 1.0)
        if len(matches) > maxnum:
            maxnum = max(maxnum, len(matches))
            temp = matches
            c = count
        k += win
        count += 1

    for j in range(0, len(temp)):
        if temp[j][2] > temp[j][0]:
            sum1 += temp[j][2] - temp[j][0] + win * c + win
            count1 += 1;
        else:
            sum2 += temp[j][2] - temp[j][0] + win * c + win
            count2 += 1;
        if count1 > count2:
            res2 = sum1 / count1
        else:
            res2 = sum2 / count2
    print("横周期像素大小为{}".format(res2))

    ticks2 = time.time()
    print("图像匹配时间为{}秒".format(ticks2-ticks))
    # print(res) #纵周期像素大小
    # print(res2) #横周期像素大小

    # 横向匹配
    cv2.imwrite("./images/match_h1.jpg", img[0:h, 0:int(res2)])
    cv2.imwrite("./images/match_h2.jpg", img[0:h, int(res2):int(res2) * 2])

    # 纵向匹配
    cv2.imwrite("./images/match_z1.jpg", img[0:int(res), 0:w])
    cv2.imwrite("./images/match_z2.jpg", img[int(res):int(res) * 2, 0:w])

最后裁剪出来的匹配的两个最小单元,结果如下图:
在这里插入图片描述
在这里插入图片描述
其实我感觉使用滑动窗口的方法存在着很多的限制:
1.默认从左上角截取第一个窗口,左上角假如存在黑边就会产生很大影响
2.设置窗口的大小和每次滑动的距离都是通过实践尝试出来的,对于不同图片的泛化性能可能会有影响(如果觉得不合理也可以自己设置)

接下来的方向是打算做图片的变化检测,对两张图的不同之处进行检测,类似于找不同。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值