【问题标题】:Image morphing with Delaunay triangulation使用 Delaunay 三角剖分进行图像变形
【发布时间】:2013-10-20 08:54:20
【问题描述】:

我正在开发一种简单的算法来使用关键点和 delaunay 三角剖分来变形两个图像。这个想法应该很简单:

  • 选择源代码控制点
  • 选择目的地控制点
  • 获取源帧和目标帧的 delaunay 三角剖分
  • 对于源图像中的每个像素
    • 获取与像素所在的源三角形相关的像素重心坐标
    • 获取与像素所在的目标三角形相关的像素重心坐标
    • 使用关系 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);  

有什么建议吗? 再见!

【问题讨论】:

    标签: image matlab triangulation delaunay morphing


    【解决方案1】:

    我无法重现您的代码中的错误,因为我没有您的输入数据集,但是,根据您的描述,您可能遇到与我昨天尝试通过三角测量变形图像时相同的问题:

    源三角剖分和目标三角剖分中的三角形数量不同

    这可能是由您在步骤中描述的原因引起的:

    1. 使用源控制点执行 Delaunay 三角剖分,得到三角形网格
    2. 对目标控制点执行 Delaunay 三角剖分,得到三角网格

    Delaunay 三角剖分非常聪明,它使用最少数量的三角形进行三角剖分。它不知道第 2 步中的控制点是从第 1 步中的控制点“转换而来”的。因此第 1 步和第 2 步中的三角形网格可能包含不同数量的三角形!这是一个示例以及如何解决该问题:

    假设您已经构建了 2 个控制点列表,“源 CP”和“目标 CP”。 “源 CP”是情况 A 中的红点。“目的地 CP”是情况 B 和 C 中的红点(它们是相同的)。

    案例 A 是通过对“源 CP”执行 Delaunay 三角剖分获得的。

    案例 B 是通过对“目标 CP”执行 Delaunay 三角剖分获得的。

    看到了吗?案例 B 包含的三角形比案例 A 少 1 个!!如果发生这种情况,您将无法使用案例 A 和 B 的 Delaunay 三角剖分中的三角形列表进行变形。

    一种解决方法是让案例 C 具有与案例 A 相同的邻接列表和相同数量的三角形,然后您可以使用成对的三角形到三角形仿射变换方法执行图像变形。

    Case C 是通过在Case A 中移动一个控制点得到的,但保持相同的邻接表

    当然,重叠的三角形现在已成为一个新问题。我认为您可以设置诸如失真幅度之类的约束,以防止三角形重叠。此外,您发布的三角形相交测试代码通过返回列表中与查询点相交的第一个三角形的三角形 ID 来考虑重叠三角形。

    所以重点是您只需对每个源-目标转换对执行一次 Delaunay 三角剖分

    希望这会有所帮助!

    【讨论】:

    • 是的,它帮助了我 =) 我注意到三角形的数量随着帧的变化而变化。实际上,对于我需要的东西,我将变形(但我有一天会做到!)用于基于光流的帧插值,它更容易且计算成本低!
    猜你喜欢
    • 2011-07-15
    • 2019-10-05
    • 2016-02-08
    • 2014-01-21
    • 2015-02-21
    • 2015-01-07
    • 2017-06-18
    • 1970-01-01
    • 2020-10-17
    相关资源
    最近更新 更多