图像识别初探:寻找眼睛

最近实验室的老师布置了第一个简单作业:给出一张图片和一张由图片中人物截取出来的眼睛图片,设计一个算法,在完整图片中找到眼睛的位置。

先上直观效果
输入图片
在这里插入图片描述
在这里插入图片描述

输出图片
在这里插入图片描述

输入图片
在这里插入图片描述
在这里插入图片描述

输出图片
在这里插入图片描述

完成这个任务需要的预备知识(只需了解即可不用深入)有向量相乘的性质以及卷积的概念

所谓卷积,简单来讲就是矩阵与矩阵对应的元素分别相乘(注意,不是矩阵乘法),一般会有一个较小的矩阵作为过滤器,从较大图片的左上角遍历到右下角,计算每个小矩阵的卷积和(小矩阵的大小和过滤矩阵相同),其中最大和对应的点就是匹配程度最高的矩阵的左上角。

为什么卷积和最大就是最匹配呢?想一想,卷积的过程是矩阵中对应的点相乘,这和矩阵展开成一维的向量再相乘结果是一样的。由向量相乘的性质可以知道:两个向量平行时可以取得相乘的最大值,因为夹角为0,cos0 = 1。两个完全相同的向量当然是平行的了,这也是其卷积和最大的原因。

但是,还是不对,你可能会发出这样的疑问,大矩阵中可以分成许多小矩阵,如果某两个矩阵的值的大小相差非常大,大到过滤器的作用也不大,这时候该怎么办呢?答案很简单,就是对于大矩阵中的每个小矩阵,在与过滤矩阵做卷积之前先减去自身的平均值,这样就可以避免值的差距过于悬殊了。

既然大矩阵里的小矩阵已经减去其平均值了,过滤矩阵也减去其平均值吧?
好,虽然没有必要这样做,但这样做却可以使计算的数值相对小一些。

公式

经过以上一波分析,再加上除去分母,其实最终版本是简单的求相关系数orz,相关系数越大则说明匹配程度越高。
在这里插入图片描述

至此,算法的结构就出来了,代码也很简洁,如下:

import matplotlib.pyplot as plt # plt 用于显示图片
import numpy as np
from PIL import Image

def find_piece_in_pic(whole_pic, part_pic) :
    #两个参数分别是两张图片的地址
    
    part = Image.open(part_pic)
    #转化为灰度图
    part = part.convert('L')
    part = np.array(part).astype('float64')

    whole = Image.open(whole_pic)
    whole = whole.convert('L')
    whole = np.array(whole).astype('float64')

    H, W = whole.shape
    h, w = part.shape

    part = part - int(np.average(part))

    res = np.zeros((whole.shape))

    for r in range(H - h + 1) :
        for c in range(W - w + 1) :
            cur_whole = whole[r : r + h, c : c + w]
            cur_whole = cur_whole - np.average(cur_whole)
            temp1 = (math.sqrt(np.sum(part * part)) * math.sqrt(np.sum(cur_whole * cur_whole)))
            if temp1 == 0 : continue
            temp = np.sum(cur_whole * part) / temp1
            res[r ,c] = temp

    topr, topc = np.where(res == np.max(res))
    print(topr, topc)
    print(np.max(res))

    plt.figure()
    plt.imshow(whole, cmap='gray')#灰度图要加上这个参数
    plt.gca().add_patch(plt.Rectangle((topc,topr), w, h, color='black'))
    plt.show()
    

find_piece_in_pic('einstain.png', 'eye.png')

Matlab函数

这么简单且应用性如此高的算法当然要收录进Matlab中啦,在Matlab下就变得无比简单了,因为函数都是封装好的。
仍然以爱因斯坦和他迷人的大眼睛为例:

eye = rgb2gray(imread('eye.png'));
einstain = rgb2gray(imread('einstain.png'));
imshowpair(peppers,onion,'montage')

c = normxcorr2(eye,einstain); #就是这个函数
figure, surf(c), shading flat
[ypeak, xpeak] = find(c==max(c(:)));

yoffSet = ypeak-size(eye,1);
xoffSet = xpeak-size(eye,2);

figure
imshow(einstain);
imrect(gca, [xoffSet+1, yoffSet+1, size(eye,2), size(eye,1)]);

猜你喜欢

转载自blog.csdn.net/weixin_43867940/article/details/106162416