benson0308 发表于 2023-12-7 13:49

IOU求重叠面积函数,部分代码不太理解 求助

本帖最后由 benson0308 于 2023-12-7 13:54 编辑

源代码:

%%%%%%%%%%%%%%%%%%%%%
%{

      *函 数 名:is_overlap

      *功能描述: 判断两个库位是否匹配,即是否为同一库位

      *输入参数:Slot1       - 全局坐标系下的库位1

      *          Slot2      - 全局坐标系下的库位1

      *          threshold    - 判断是否重叠的阈值,0-1,值越大代表重叠度越高,1代表完全重叠

      *输出参数: ret
               0 - Slot1和Slot2不匹配
               1 - Slot1和Slot2匹配
%}
function ret=is_overlap(Slot1, Slot2, threshold)
point.x=single(0);
point.y=single(0);
pt_Slot1=repmat(point,4,1);
pt_Slot2=repmat(point,4,1);

Slot1.p0_x = (round(Slot1.p0_x*10000))./10000;
Slot1.p0_y = (round(Slot1.p0_y*10000))./10000;
Slot1.p1_x = (round(Slot1.p1_x*10000))./10000;
Slot1.p1_y = (round(Slot1.p1_y*10000))./10000;
Slot1.p2_x = (round(Slot1.p2_x*10000))./10000;
Slot1.p2_y = (round(Slot1.p2_y*10000))./10000;
Slot1.p3_x = (round(Slot1.p3_x*10000))./10000;
Slot1.p3_y = (round(Slot1.p3_y*10000))./10000;

pt_Slot1(1).x=Slot1.p0_x;pt_Slot1(1).y=Slot1.p0_y;
pt_Slot1(2).x=Slot1.p1_x;pt_Slot1(2).y=Slot1.p1_y;
pt_Slot1(3).x=Slot1.p2_x;pt_Slot1(3).y=Slot1.p2_y;
pt_Slot1(4).x=Slot1.p3_x;pt_Slot1(4).y=Slot1.p3_y;
pt_Slot1_PN = length(pt_Slot1);

Slot2.p0_x = (round(Slot2.p0_x*10000))./10000;
Slot2.p0_y = (round(Slot2.p0_y*10000))./10000;
Slot2.p1_x = (round(Slot2.p1_x*10000))./10000;
Slot2.p1_y = (round(Slot2.p1_y*10000))./10000;
Slot2.p2_x = (round(Slot2.p2_x*10000))./10000;
Slot2.p2_y = (round(Slot2.p2_y*10000))./10000;
Slot2.p3_x = (round(Slot2.p3_x*10000))./10000;
Slot2.p3_y = (round(Slot2.p3_y*10000))./10000;


pt_Slot2(1).x=Slot2.p0_x;pt_Slot2(1).y=Slot2.p0_y;
pt_Slot2(2).x=Slot2.p1_x;pt_Slot2(2).y=Slot2.p1_y;
pt_Slot2(3).x=Slot2.p2_x;pt_Slot2(3).y=Slot2.p2_y;
pt_Slot2(4).x=Slot2.p3_x;pt_Slot2(4).y=Slot2.p3_y;
pt_Slot2_PN = length(pt_Slot2);

p0_sqrt = sqrt((Slot1.p0_x - Slot2.p0_x)^2 + (Slot1.p0_y - Slot2.p0_y)^2);
p1_sqrt = sqrt((Slot1.p1_x - Slot2.p1_x)^2 + (Slot1.p1_y - Slot2.p1_y)^2);
p2_sqrt = sqrt((Slot1.p2_x - Slot2.p2_x)^2 + (Slot1.p2_y - Slot2.p2_y)^2);
p3_sqrt = sqrt((Slot1.p3_x - Slot2.p3_x)^2 + (Slot1.p3_y - Slot2.p3_y)^2);

if ((p0_sqrt < 0.3) && (p1_sqrt < 0.3) && (p2_sqrt < 0.3) && (p3_sqrt < 0.3))
    ret = 1;
    return;
else
   
end

%排序
pc1=pointsOrdered(pt_Slot1, pt_Slot1_PN);
pc2=pointsOrdered(pt_Slot2, pt_Slot2_PN);

inter=intersectPolygonSHPC(pc1,pc2);
pc_inter=pointsOrdered2(inter);

if pc_inter.size<=0 || pc1.size<=0
    proportion = single(0);
else
    proportion = computeArea(pc_inter)/computeArea(pc1);
end
% proportion = polyarea(,)/polyarea(,);

if proportion>threshold
    ret=1;
else
    ret=0;
end
% plot(,,'b',,,'g',,,'r')
end
function res=intersectPolygonSHPC(Slot1,Slot2)
    n=Slot1.size;
    point.x=single(0);
    point.y=single(0);
    res.point=repmat(point,16,1);
%   res.size = uint8(0);
    res.size = 0;
    p1=res;
    dir = left_of(Slot2.point(1), Slot2.point(2), Slot2.point(3));
    Slot1_temp=res;
    Slot2_temp=res;
    for k=1:Slot1.size
      Slot1_temp.point(k).x=Slot1.point(k).x;
      Slot1_temp.point(k).y=Slot1.point(k).y;
      Slot1_temp.size=Slot1.size;
    end
    for k=1:Slot2.size
      Slot2_temp.point(k).x=Slot2.point(k).x;
      Slot2_temp.point(k).y=Slot2.point(k).y;
      Slot2_temp.size=Slot2.size;
    end
    p2=poly_edge_clip(Slot1_temp,Slot2_temp.point(n), Slot2_temp.point(1), dir);
   
    for i =1:n-1
      tmp = p2;
      p2 = p1;
      p1 = tmp;
      p2=poly_edge_clip(p1, Slot2_temp.point(i), Slot2_temp.point(i+1), dir);
    end

    index=0;
    for i =1:p2.size
      index=index+1;
      res.point(index)=p2.point(i);
      res.size = res.size + 1;
    end
end

function res=poly_edge_clip(sub,x0,x1,left)
    n=sub.size;
    point.x=single(0);
    point.y=single(0);
    res.point=repmat(point,16,1);
    res.size = 0;
    if n==0
      return;
    end
    v0=sub.point(n);
    side0 = left_of(x0, x1, v0);
    if side0 ~=-left
      res.size=res.size+1;
      res.point(res.size).x=v0.x;
      res.point(res.size).y=v0.y;
    end
   
    for i=1:n
      v1 = sub.point(i);
      side1 = left_of(x0, x1, v1);
      if ((side0 + side1 == 0 )&& side0)
            %       /* last point and current straddle the edge */
            =line_sect(x0, x1, v0, v1);
            if (ret)
                res.size=res.size+1;
                res.point(res.size)=temp;
            end
      end
      if (i == n)
            break;
      end
      
      if (side1 ~= -left)
            res.size=res.size+1;
            res.point(res.size).x=v1.x;
            res.point(res.size).y=v1.y;
      end
      v0 = v1;
      side0 = side1;
    end
end


function =line_sect(x0,x1,y0,y1)
    ret = 1;
    temp.x = single(0);
    temp.y = single(0);

    dx=vsub(x1, x0);
    dy=vsub(y1, y0);
    d=vsub(x0, y0);
    dyx = cross(dy, dx);
    if (~dyx)
      ret= 0;
      return;
    end
    dyx = cross(d, dx) / dyx;
    if (dyx <= 0 || dyx >= 1)
      ret= 0;
      return;
    end
    temp.x = (y0.x + dyx * dy.x);
    temp.y = (y0.y + dyx * dy.y);
    ret= 1;
end

function ret=left_of(a,b,c)

    ret = 0;

    tmp1=vsub(b, a);%向量a->b
    tmp2=vsub(c, b);
    x = cross(tmp1, tmp2);%叉积
    if x < 0
      ret=-1;
    elseif x == 0
      ret=0;
    else
      ret=1;
    end
end

function res=vsub(a,b)
    point.x=single(0);
    point.y=single(0);
    res=point;
    res.x = a.x - b.x;
    res.y = a.y - b.y;
end

function ret=cross(a,b)
    ret= a.x * b.y - a.y * b.x;
end

function pc=pointsOrdered(pt, pt_num)

%   n=pt_num;
    if( pt_num <= 0)
      return;
    end

    center.x = mean();
    center.y = mean();

    temp.x=single(0);
    temp.y=single(0);
    temp.angle=single(0);
    pc.point=repmat(temp,16,1);
    pc.size = pt_num;
    for i = 1:pt_num
      pc.point(i).x = pt(i).x;
      pc.point(i).y = pt(i).y;
      pc.point(i).angle = atan2((pt(i).y - center.y), (pt(i).x - center.x));
    end
    pc.point=qsort(pc.point, pt_num, 1);%按角度升序排列,直角坐标系X轴为0度   从-pi到pi排列
    for i = 1:pt_num
      pt(i).x = pc.point(i).x;
      pt(i).y = pc.point(i).y;
    end
end

function pc=pointsOrdered2(pt)
    n=pt.size;
    temp.x=single(0);
    temp.y=single(0);
    temp.angle=single(0);
    pc.point=repmat(temp,16,1);
    pc.size = n;
    if( n <= 0)
      return;
    end
    center.x = single(0);
    center.y = single(0);
    for ii = 1:n
      center.x = center.x + pt.point(ii).x;
      center.y = center.y + pt.point(ii).y;
    end
    center.x = center.x/single(n);
    center.y = center.y/single(n);

    for i = 1:n
      pc.point(i).x = pt.point(i).x;
      pc.point(i).y = pt.point(i).y;
      pc.point(i).angle = atan2((pt.point(i).y - center.y), (pt.point(i).x - center.x));
    end
    pc.point=qsort(pc.point, n, 1);
    for i = 1:n
      pt.point(i).x = pc.point(i).x;
      pt.point(i).y = pc.point(i).y;
    end
end
%comp_point_with_angle=1 升序,-1 降序
function ret=qsort(pc,n,comp_point_with_angle)
    if comp_point_with_angle==1
      for i=1:n
            for j=i:n
                if pc(i).angle>pc(j).angle
                  temp=pc(i);
                  pc(i)=pc(j);
                  pc(j)=temp;
                end
               
            end
      end
    else
      for i=1:n
            for j=i+n
                if pc(i).angle<pc(j).angle
                  temp=pc(i);
                  pc(i)=pc(j);
                  pc(j)=temp;
                end
               
            end
      end
    end
    ret=pc;
end

function area0=computeArea(pt)
    area0 = single(0);
    n=pt.size;
    if n <= 0
      return;
    end

    for i=1:n-1
      area0 = area0+pt.point(i).x * pt.point(i+1).y;
      area0 = area0-pt.point(i).y * pt.point(i+1).x;
    end
    area0 = area0+pt.point(n).x * pt.point(1).y;
    area0 = area0-pt.point(n).y * pt.point(1).x;

    area0 = 0.5*abs(area0);

end
%%%%%%%%%%%%%%%%%%%%%

其中line_sect模块什么作用,(dyx <= 0 || dyx > 1)作何筛选?

qfxldhw 发表于 2023-12-7 15:32

代码中的 line_sect 函数是用来计算两条直线的交点的。它的作用是通过输入的两条线段(由四个点表示),判断这两条线段是否相交,并计算它们的交点坐标。

在给定的函数中,line_sect 接收四个点作为输入,分别代表两条线段的起点和终点。它首先计算两条线段的斜率,然后判断两条线段是否相交。

代码中的 (dyx <= 0 || dyx >= 1) 是用来排除交点位置不在两条线段的端点之间的情况。dyx 是通过计算交点在两条线段上的比例,判断其位置是否在两条线段的范围内。如果交点的比例小于等于 0 或者大于等于 1,意味着交点在延长线上而不在两条线段之间,因此不是线段的交点。

这个判断条件的作用是排除一些特殊情况,避免将不在线段上的点作为交点进行处理,确保得到的交点是有效的且位于两条线段之间的。

Mtnuli 发表于 2023-12-7 15:55

学习了,顶楼主

ciker_li 发表于 2023-12-7 19:11

这是啥语言写的?

benson0308 发表于 2023-12-8 09:11

ciker_li 发表于 2023-12-7 19:11
这是啥语言写的?

matlab.m

benson0308 发表于 2023-12-8 09:14

本帖最后由 benson0308 于 2023-12-8 09:17 编辑

qfxldhw 发表于 2023-12-7 15:32
代码中的 line_sect 函数是用来计算两条直线的交点的。它的作用是通过输入的两条线段(由四个点表示),判 ...
感谢楼主,我也找到一部分参考。

https://www.cnblogs.com/zhb2000/p/vector-cross-product-solve-intersection.html#:~:text=%E5%A6%82%E5%9B%BE%E6%89%80%E7%A4%BA%EF%BC%8C%E6%9C%89%E4%B8%A4%E6%9D%A1%E7%9B%B4%E7%BA%BF%E4%BA%A4%E4%BA%8E%E7%82%B9%20I%20%E3%80%82%20%E6%88%91%E4%BB%AC%E7%94%A8%E7%82%B9%20p%201%20%E5%92%8C%E5%90%91%E9%87%8F%20v

benson0308 发表于 2023-12-8 09:15

qfxldhw 发表于 2023-12-7 15:32
代码中的 line_sect 函数是用来计算两条直线的交点的。它的作用是通过输入的两条线段(由四个点表示),判 ...

感谢楼主,我最近也在补相关知识。
代码是先用给矩形角点排序,然后利用叉乘判断矩形角点是否在另一矩形任一条线的同侧,如果异侧使用 line_sect函数求两线段交点。
页: [1]
查看完整版本: IOU求重叠面积函数,部分代码不太理解 求助