SAD(Sum of absolute differences)是一种图像匹配算法。
SAD算法的基本流程:
1.构造一个小窗口,类似与卷积核。
2.用窗口覆盖左边的图像,选择出窗口覆盖区域内的所有像素点。
3.同样用窗口覆盖右边的图像并选择出覆盖区域的像素点。
4.左边覆盖区域减去右边覆盖区域,并求出所有像素点差的绝对值的和。
5.移动右边图像的窗口,重复3,4的动作。(这里有个搜索范围,超过这个范围跳出)
6.找到这个范围内SAD值最小的窗口,即找到了左边图像的最佳匹配的像素块。
SAD算法具体实现
import os
import time
import cv2 as cv
from PIL import Image
import numpy as np
from matplotlib import pyplot as plt
max_D = 25 #最大视差
win_size = 5 #滑动窗口大小
os.chdir(r'../ohta') #图片所在文件夹路径
limg = np.asanyarray(Image.open(r"scene1.row3.col1.ppm")) #左相机图片
rimg = np.asanyarray(Image.open(r"scene1.row3.col3.ppm")) #右相机图片
limg = cv.cvtColor(limg, cv.COLOR_BGR2GRAY) #将左图像转化为灰度图
rimg = cv.cvtColor(rimg, cv.COLOR_BGR2GRAY)
limg = np.asanyarray(limg, dtype=np.double) #将左图像转化为double类型
rimg = np.asanyarray(rimg, dtype=np.double)
img_size = np.shape(limg)[0:2] #定义一个和图片大小相等尺寸的数组
plt.figure("左图灰度图")
plt.imshow(limg)
plt.show()
plt.figure("右图灰度图")
plt.imshow(rimg)
plt.show()
t1 = time.time() #记录开始时间
imgDiff = np.zeros((img_size[0], img_size[1], max_D)) #记录视差为max_D的e2
e = np.zeros(img_size) #记录视差为i时,左右图片的整体差距
for i in range(0, max_D):
e = np.abs(rimg[:, 0:(img_size[1]-i)]-limg[:, i:img_size[1]])
e2 = np.zeros(img_size) #记录win_size之和
for x in range(0, img_size[0]):
for y in range(0, img_size[1]):
e2[x, y] = np.sum(e[(x-win_size):(x+win_size), (y-win_size):(y+win_size)])
imgDiff[:, :, i] = e2
dispMap = np.zeros(img_size) #最小视差图
for x in range(0, img_size[0]):
for y in range(0, img_size[1]):
val = np.sort(imgDiff[x, y, :]) #排序
if np.abs(val[0]-val[1]) > 10:
val_id = np.argsort(imgDiff[x, y, :]) #返回从小到大的索引
dispMap[x, y] = val_id[0]/max_D*255 #恢复彩色图像
print("所用时间:", time.time()-t1)
plt.figure("视差图")
plt.imshow(dispMap)
plt.show()
具体的运行效果
所用时间为: 11.613516569137573