最近在做图像处理的时候,需要将图片中的地板部分切出来,所以想法是先用滑动窗口扫描图片,用矩形框框住图片的一小块,让这部分与提前准备好的地板模板图片比较,求出相似度,然后接下来才能根据相似度进行下一步处理。接下来我分享一些心得。
#设置滑动窗口
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
#用余弦相似度来处理
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
以上两种方法可以直接替换直方图的方法来用,有需要的可以尝试一下。第一次写,有不足之处,还望大家能够提出,共同进步。