2013-10-12 96 views
1

我正在開發一個簡單的算法來使用關鍵點和delaunay三角測量來變形兩個圖像。這個想法應該很簡單:Delaunay三角測量圖像變形

  • 信源選擇控制點
  • 選擇目標控制點
  • 獲取源和目標德洛內三角框架
  • 每個像素的源圖像中
    • 得到與像素所在的源三角形相關的像素重心座標
    • 獲得與目的地t有關的像素重心座標使用關係Px = w1 * v0x + w2 * v1x + w3 * v2x(對於y和目標像素相同)指定OUT [PdestX,PdestY] = IN [Px,Py]的像素位於的棱紋
    • 。 。

但它不工作X_X這是我的matlab源:

function out = myMorph(im1, p_source, p_dest, tri_source, tri_dest) 

[h w] = size(im1); 

%get single column vectors for source and destination image control points 
Psource_x = p_source(:,1); 
Psource_y = p_source(:,2); 
Pdest_x  = p_dest(:,1); 
Pdest_y  = p_dest(:,2); 

%for each intermediate frame... 

out = zeros(size(im1)); 

%get triangles. Each array is 3n x 2, where n is the number of triangles 
triangles_source = []; 
triangles_dest = []; 
for i= 1 : size(tri_source,1) 
triangle_s = getTriangle(Psource_x,Psource_y,tri_source,i); 
triangle_d = getTriangle(Pdest_x,Pdest_y,tri_dest,i); 

triangles_source = cat(1,triangles_source,triangle_s); 
triangles_dest = cat(1,triangles_dest,triangle_d); 
end 



%iterate each pixel 
for x=1:h 
for y=1:w 

    %get the source and destination triangle for pixel [x y] 

    %source triangle 
    for t = 1 : 3 : size(triangles_source, 1)-2 

     [w1,w2,w3,inTriangle] = inTri(x,y, ... 
            triangles_source(t,1),triangles_source(t,2), ... 
            triangles_source(t+1,1),triangles_source(t+1,2), ... 
            triangles_source(t+2,1),triangles_source(t+2,2)); 
     if(inTriangle == 1) 
      break; %point [x,y] must belong to one (and only) triangle 
     end 
    end 

    %source triangle 
    for k = 1 : 3 : size(triangles_dest, 1)-2 
     [w1d,w2d,w3d,inTriangleD] = inTri(x,y, ... 
            triangles_dest(k,1),triangles_dest(k,2), ... 
            triangles_dest(k+1,1),triangles_dest(k+1,2), ... 
            triangles_dest(k+2,1),triangles_dest(k+2,2)); 
     if(inTriangleD == 1) 
      break; 
     end 
    end 

    v_source = [w1*triangles_source(t,1) + ... 
       w2*triangles_source(t+1,1) + ... 
       w3*triangles_source(t+2,1), ... 
       w1*triangles_source(t,2) + ... 
       w2*triangles_source(t+1,2) + ... 
       w3*triangles_source(t+2,2)]; 

    v_dest = [w1d*triangles_dest(k,1) + ... 
       w2d*triangles_dest(k+1,1) + ... 
       w3d*triangles_dest(k+2,1),... 
       w1d*triangles_dest(k,2) + ... 
       w2d*triangles_dest(k+1,2) + ... 
       w3d*triangles_dest(k+2,2)]; 


    if(inTriangle ~= 1 && inTriangleD ~= 1) 
     continue; 
    end 

    v_source = round(v_source); 
    v_dest  = round(v_dest); 

    if(v_source(1)>0 && v_source(1) <= h && ... 
     v_source(2)>0 && v_source(2) <= w && ... 
     v_dest(1)>0 && v_dest(1) <= h && ... 
     v_dest(2)>0 && v_dest(2) <= w) 

    disp('pixel warped') 
    out(v_dest(1),v_dest(2)) = im1(v_source(1),v_source(2)); 
    end 
    % else 
    % out(x,y) = im1(x,y); 

end 
end 

這些是得到控制點

%Get control points used to morph im into another image 
%im      -> source image 
%im2     -> destination image 
%linesNum    -> number of lines 
function [P] = getControlPoints(im, controlPtsNum) 

close all 

P = zeros(controlPtsNum, 2); 

%select lines from source image 
figure; 
imshow(im,[]);title('select control points') 

for i=1 : controlPtsNum 
    %get source control point 
[x,y] = ginput(1); 
    P(i,:) = [x,y]; 

    hold on 
    plot(x,y,'o','Color','r'); 
    hold off 
end 



%Get control points used to morph im into another image and do delaunay 
%triangulation using the control points 
%im      -> source image 
%im2     -> destination image 
%controlPtsNum   -> number of control points 
function [P,tri] = getControlPointsAndTriangulate(im, controlPtsNum) 

P = getControlPoints(im, controlPtsNum); 

[h w] = size(im); 

%Add corners to control points 
P = cat(1, P, [1 1]); 
P = cat(1, P, [w 1]); 
P = cat(1, P, [1 h]); 
P = cat(1, P, [w h]); 

tri = delaunay(P(:,1),P(:,2)); 

hold on 
triplot(tri,P(:,1),P(:,2)) 
hold on 

這個功能效用函數(我在網上找到),測試一個點是否位於給定的三角形上,並返回u,v,w值:

function [w1,w2,w3,r] = inTri(vx, vy, v0x, v0y, v1x, v1y, v2x, v2y) 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
% inTri checks whether input points (vx, vy) are in a triangle whose 
% vertices are (v0x, v0y), (v1x, v1y) and (v2x, v2y) and returns the linear 
% combination weight, i.e., vx = w1*v0x + w2*v1x + w3*v2x and 
% vy = w1*v0y + w2*v1y + w3*v2y. If a point is in the triangle, the 
% corresponding r will be 1 and otherwise 0. 
% 
% This function accepts multiple point inputs, e.g., for two points (1,2), 
% (20,30), vx = (1, 20) and vy = (2, 30). In this case, w1, w2, w3 and r will 
% be vectors. The function only accepts the vertices of one triangle. 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
v0x = repmat(v0x, size(vx,1), size(vx,2)); 
v0y = repmat(v0y, size(vx,1), size(vx,2)); 
v1x = repmat(v1x, size(vx,1), size(vx,2)); 
v1y = repmat(v1y, size(vx,1), size(vx,2)); 
v2x = repmat(v2x, size(vx,1), size(vx,2)); 
v2y = repmat(v2y, size(vx,1), size(vx,2)); 
w1 = ((vx-v2x).*(v1y-v2y) - (vy-v2y).*(v1x-v2x))./... 
((v0x-v2x).*(v1y-v2y) - (v0y-v2y).*(v1x-v2x)+eps); 
w2 = ((vx-v2x).*(v0y-v2y) - (vy-v2y).*(v0x-v2x))./... 
((v1x-v2x).*(v0y-v2y) - (v1y-v2y).*(v0x-v2x)+eps); 
w3 = 1 - w1 - w2; 
r = (w1>=0) & (w2>=0) & (w3>=0) & (w1<=1) & (w2<=1) & (w3<=1); 

有什麼建議嗎? 再見!

回答

2

我無法在代碼中重現錯誤,因爲我沒有輸入數據集,但是,根據您的描述,您可能會遇到與我嘗試通過三角測量變形圖像時相同的問題昨天:

源三角測量和目標三角測量中三角形的數量是不同

這可能是你在你的步驟描述什麼原因造成的:

  1. 與源控制點進行Delaunay三角,得到了三角形網格
  2. 與目標控制點進行Delaunay三角,得到了三角形網格

Delaunay三角是太聰明瞭,它使用最少的NU用於三角測量的三角形的mbers。它不知道步驟2中的控制點是從步驟1中的控制點「轉換而來」的。因此步驟1和步驟2中的三角形網格可能包含不同數量的三角形!下面是一個例子,如何來解決這個問題:

Example.

比方說,你已經構建的控制點,「源CP」和「目的地CP」 2名列表。 「源CP」是情況A中的紅點。「目標CP」是情況B和C(它們相同)中的紅點。

通過在「源CP」上執行Delaunay Triangulation來獲得案例A.

通過在「目標CP」上執行Delaunay Triangulation來獲得案例B.

請參閱?案例B比案例A少了1個三角形!如果發生這種情況,你可以在例的三角網和B.

一種解決方法是讓案件C具有相同鄰接表和相同數量的三角形的情況A的使用三角名單不變形,那麼你可以用成對的三角形到三角形的仿射變換方法進行圖像變形。

案例C是由剛剛在移動情形A一個控制點,但保持相同的鄰接表獲得。

當然,重疊的三角形現在已經成爲一個新問題。我認爲你可以放置扭曲的大小等約束來防止三角形重疊。此外,您發佈的三角形相交測試代碼通過返回列表中與查詢點相交的第一個三角形的三角形ID來考慮重疊三角形。

所以問題是你只需要對每個源 - 目的地轉換對執行一次Delaunay Triangulation

希望這會有所幫助!

+0

是的,它幫助了我=)我注意到三角形的數量從一幀到另一幀。實際上,對於我需要的東西,我留下了變形(但我會做到這一點!)基於光流的幀插值,並且它非常容易和計算便宜! –