使用KMP算法进行图像匹配

本文探讨了如何利用KMP算法解决图像匹配问题,将图像转化为一维字符串,并在大图中寻找小图位置。参考了孙远等人的论文,详细介绍了算法的具体实现。
摘要由CSDN通过智能技术生成

这里想探索图像匹配问题的处理,即在一个大图中找一个小图的位置。相关的文献有很多。这里参照论文(孙远,周刚慧,赵立初,施鹏飞 灰度图像匹配的快速算法 上海交通大学学报)将图像投影成一维字符串,并使用KMP算法查找匹配。
一些具体实现写在了注释中。

import numpy as np
from PIL import Image
def mtx_similar1(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    计算矩阵相似度的一种方法。将矩阵展平成向量,计算向量的乘积除以模长。
    注意有展平操作。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:实际是夹角的余弦值,ret = (cos+1)/2
    '''
    farr1 = arr1.ravel()
    farr2 = arr2.ravel()
    len1 = len(farr1)
    len2 = len(farr2)
    if len1 > len2:
        farr1 = farr1[:len2]
    else:
        farr2 = farr2[:len1]
    #~如果矩阵的维度、向量的模长不一样。
    numer = np.sum(farr1 * farr2)
    denom = np.sqrt(np.sum(farr1**2) * np.sum(farr2**2))
    similar = numer / denom # 这实际是夹角的余弦值
    return  (similar+1) / 2     # 姑且把余弦函数当线性

def mtx_similar2(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    计算对矩阵1的相似度。相减之后对元素取平方再求和。因为如果越相似那么为0的会越多。
    如果矩阵大小不一样会在左上角对齐,截取二者最小的相交范围。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:相似度(0~1之间)
    '''
    if arr1.shape != arr2.shape:
        minx = min(arr1.shape[0],arr2.shape[0])
        miny = min(arr1.shape[1],arr2.shape[1])
        differ = arr1[:minx,:miny] - arr2[:minx,:miny]
    else:
        differ = arr1 - arr2
    numera = np.sum(differ**2)
    denom = np.sum(arr1**2)
    similar = 1 - (numera / denom)
    return similar


def mtx_similar3(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    From CS231n: There are many ways to decide whether
    two matrices are similar; one of the simplest is the Frobenius norm. In case
    you haven't seen it before, the Frobenius norm of two matrices is the square
    root of the squared sum of differences of all elements; in other words, reshape
    the matrices into vectors and compute the Euclidean distance between them.
    difference = np.linalg.norm(dists - dists_one, ord='fro')
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:相似度(0~1之间)
    '''
    if arr1.shape != arr2.shape:
        minx = min(arr1.shape[0],arr2.shape[0])
        miny = min(arr1.shape[1],arr2.shape[1])
        differ = arr1[:minx,:miny] - arr2[:minx,:miny]
        #~如果矩阵的大小不一样
    else:
        differ = arr1 - arr2
    dist = np.linalg.norm(differ, ord='fro')
    len1 = np.linalg.norm(arr1)
    len2 = np.linalg.norm(arr2)     # 普通模长
    denom = (len1 + len2) / 2
    similar = 1 - (dist / denom)
    return similar


import random
def find_position_process(page:str,pic:str):
    '''
    问题:在一个大图中查找一个小图/模板图
    这是基础但低效的算法,效率之低而几乎不会用——在我的电脑上一张一千多像素宽度的图查一个400*400图用了超过20min。
    :param page:大图
    :param pic:小图
    :return:打印匹配度较高的位置
    '''
    pageArr = np.array(Image.open(page).convert('L'))
    picArr = np.array(Image.open(pic).convert('L'))     # 首先转换成灰度图像
    hei,wid = picArr.shape
    # if hei > 600:
    #     #太大了,裁一个400*400以内的小块,用之预比较
    #     hStart = int(random.uniform(0,hei-400))
    #     if wid > 400:
    #         wStart = int(random.uniform(0,wid-400))
    #         smallArr = picArr[hStart:hStart + 400, wStart:wStart + 400]
    #     else:
    #         smallArr = picArr[hStart:hStart + 400,:]
    # elif wid > 600:
    #     wStart = int(random.uniform(0,wid-400))
    #     smallArr = picArr[:, wStart:wStart+400]     # 好吧,实际上保证是比较块一定在600*600以内
    # else:
    #……发现可能大的子图比较的反而快
    smallArr = picArr
    sHei, sWid = smallArr.shape
    for i in range(0,hei - sHei):
        if i%100 == 0:
            print('do i:', i)
        for k in range(0, wid - sWid):
            sim = mtx_similar2(smallArr, pageArr[i: i+sHei, k: k+sWid])
            if sim > 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值