話說我今天上午寫的博客忘了保存,直接關了電腦,然后我就XX了,沒辦法,晚上補回來吧,還是老算法,還是熟悉的味道
SAD算法的基本流程:
1.構造一個小窗口,類似與卷積核。
2.用窗口覆蓋左邊的圖像,選擇出窗口覆蓋區域內的所有像素點。
3.同樣用窗口覆蓋右邊的圖像並選擇出覆蓋區域的像素點。
4.左邊覆蓋區域減去右邊覆蓋區域,並求出所有像素點差的絕對值的和。
5.移動右邊圖像的窗口,重復3,4的動作。(這里有個搜索范圍,超過這個范圍跳出)
6.找到這個范圍內SAD值最小的窗口,即找到了左邊圖像的最佳匹配的像素塊。
下面我寫一下對於這個算法的理解:
我們要構造一個窗口D分別用於覆蓋左邊圖像和右邊圖像,窗口的size大小可以自己去定義,然后用D窗口圈出了AB兩幅圖像后,我們需要要左右窗口內的
選定的像素做差,然后求取其絕對值,並且對絕對值求和。在視差范圍內移動窗口 ,並重復作差,求取絕對值,並求和。找到最小的匹配塊,並且標記記錄下來
廢話不多說我們看代碼,這份代碼不是我寫的,我寫完后發現運行效率超級低,我以為我寫錯了,
賦值粘貼了別人的代碼發現還是很慢,不知道什么原因。求大神指教。
for(i=1+win:1:wL-win)
for(j=1+win:1:hL-win-dispMax)
preSAD = 10000000; temp=0.0; OptimalDisp = dispMin;
for(dispRange=dispMin:1:dispMax)
curSAD=0.0;
for(x=-win:1:win)
for(y=-win:1:win)
if (j+y+dispRange <= hL)
temp=imR(i+x,j+y)-imL(i+x,j+y+dispRange);
if(temp<0.0)
temp=temp*-1.0;
end
curSAD=curSAD+temp;
end
end
end
%Finding a best disaparty
if (preSAD > curSAD)
preSAD = curSAD;
OptimalDisp = dispRange;
end
end
%Final disparity
dispMap_SAD(i,j) = OptimalDisp;
end
end
(其實不難發現,算法中存在大量的冗余計算,主要體現在,你需要反復地計算出,已經計算過的差值,絕對值,求和,所以,能不能只計算一次插值呢,能不能先求取插值,比如生成一個插值圖像(imgL-imgR),然后利用窗口D在插值圖像上面滑動,計算和,然后在針對每個點進行匹配)= =這份代碼也是在網上找到的,發現寫代碼還是一件費勁的事,自己還是很垃圾,慢慢努力吧
im1=imread('left2.png');
im2=imread('right2.png');
if isrgb(im1)
im1=rgb2gray(im1);
end
%imshow(im1);
im1=double(im1);
if isrgb(im2)
im2=rgb2gray(im2);
end
%figure
%imshow(im2);
im2=double(im2);
D=20; %最大視差
N=9; %窗口大小的一半
[H,W]=size(im1);
%計算右圖減去左圖,相減產生D個矩陣放到imgDiff中
imgDiff=zeros(H,W,D);
e=zeros(H,W);
tic
for i=1:D
fprintf('%g\n',i)
e(:,1:(W-i))=abs(im2(:,1:(W-i))- im1(:,(i+1):W));
%e=conv2(e,e,'same');
e2=zeros(H,W);%計算窗口內的和
for y=(N+1):(H-N)
for x=(N+1):(W-N)
e2(y,x)=sum(sum(e((y-N):(y+N),(x-N):(x+N))));
end
end
imgDiff(:,:,i)=e2;
end
%20
%找到最小的視差,到dispMap
dispMap=zeros(H,W);
for x=1:W
for y=1:H
%[val,id]=min(imgDiff(y,x,:));
[val,id]=sort(imgDiff(y,x,:));
if abs(val(1)-val(2))>10
dispMap(y,x)=id(1);
end
end
end
toc
%顯示
dispMap=dispMap*200/D;
dispMap=uint8(dispMap);
%toc
imshow(dispMap)
%imwrite(dispMap,'dispMap.jpg')
