通过滑动窗口切出部分图像与模板比较求相似度

简述

最近在做图像处理的时候,需要将图片中的地板部分切出来,所以想法是先用滑动窗口扫描图片,用矩形框框住图片的一小块,让这部分与提前准备好的地板模板图片比较,求出相似度,然后接下来才能根据相似度进行下一步处理。接下来我分享一些心得。

首先定义滑动窗口

#设置滑动窗口
def sliding_window(image, stepSize, windowSize):
    # slide a window across the image
    for y in range(0, image.shape[0], stepSize):
        for x in range(0, image.shape[1], stepSize):
            # yield the current window
            yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])

然后定义比较相似度的方法

#单通道直方图
def classify_gray_hist(img1,img2):
    im1 =  cv2.resize(img1,(80,80))
    gray1 = cv2.cvtColor(im1,cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
    hist1 = cv2.calcHist(gray1, [1], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist(gray2, [1], None, [256], [0.0, 255.0])
    #求两个图像的相似度,有三个参数可以调用。巴氏距离越大,相似度越低;相关性越小,相似度越低;卡方越大,相似度越低(我感觉这个不准)
    match1 = cv2.compareHist(hist1, hist2, cv2.HISTCMP_BHATTACHARYYA)
    match2 = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    match3 = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CHISQR)
    print("巴氏距离:%s, 相关性:%s, 卡方:%s" % (match1, match2, match3))

这里我用的是单通道直方图的方法来求相似度,后面我还会分享一下用余弦相似度求解相似度的方法,以及差值感知哈希法求汉明距离。

接下来直接上主函数,具体每一步我都写有注释,就不在分步骤了

if __name__ == '__main__':
    #固定用来对照的图片
    vi1 = cv2.imread("picture/10.jpg")

    #vi1 = cv2.resize(vi1,(800,800))
    #需要滑动的图片
    vi2 = cv2.imread("picture/9.jpg")

    #vi2 = cv2.resize(vi2,(800,800))

    #自定义滑动窗口的大小
    (winW,winH) = (80,80)
    #步长大小
    stepSize = 80
    cnt = 0
    #滑动窗口循环,不清楚的可以查一下sliding_window的用法
    for(x,y,window) in sliding_window(vi2,stepSize=stepSize,windowSize=(winW,winH)):
        if window.shape[0] != winH or window.shape[1] !=winW:
            continue
        clone = vi2.copy()
        #用矩形框选中图像部分区域
        cv2.rectangle(clone,(x,y),(x+winW,y+winH),(0,255,0),2)
        cv2.imshow("Window",clone)
        cv2.waitKey(1000)
        #选中区域的大小
        slice = vi2[y:y+winH,x:x+winW]
        #再建一个窗口展示选中的区域
        cv2.namedWindow('sliding_slice',0)
        cv2.imshow('sliding_slice',slice)
        cv2.waitKey(1000)
       #调用classify_gray_hist方法,输出相似度
        classify_gray_hist(vi1, slice)
        cnt = cnt + 1

运行结果

通过滑动窗口切出部分图像与模板比较求相似度_第1张图片

接下来分享一下其他求相似度的方法,可做参考

  • 余弦相似度
#用余弦相似度来处理
def image_similarity_vectors_via_numpy(image1, image2):

    im1 = get_thumbnail(image1)

    images = [im1, image2]
    vectors = []
    norms = []
    for image in images:
        vector = []
        for pixel_tuple in image.getdata():
            vector.append(average(pixel_tuple))
        vectors.append(vector)
        norms.append(linalg.norm(vector, 2))
    a, b = vectors
    a_norm, b_norm = norms
    res = dot(a / a_norm, b / b_norm)
    return res
  • 差值感知哈希法
#差值感知哈希法
 def dhash(img1,img2):
     gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
     gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
     hash1 = dhashcaulate(gray1)
     hash2 = dhashcaulate(gray2)
     return Hamming_distance(hash1,hash2)
     
 def dhashcaulate(gray):
     hash_str = ''
     for i in range(8):
         for j in range(8):
           if gray[i,j]>gray[i,j+1]:
               hash_str = hash_str + '1'
           else:
               hash_str = hash_str + '0'
     return hash_str
     
 def Hamming_distance(hash1,hash2):
     num = 0
     for index in range(len(hash1)):
         if hash1[index] != hash2[index]:
             num += 1
     return num

以上两种方法可以直接替换直方图的方法来用,有需要的可以尝试一下。第一次写,有不足之处,还望大家能够提出,共同进步。

你可能感兴趣的:(滑动窗口,相似度,图像切割)