Janilabo

Clustering vs. Splitting

Sep 24th, 2013
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 34.99 KB | None | 0 0
  1. const
  2.   DIST = 12;
  3.  
  4. {==============================================================================]
  5.  Splits TPA with dist. Alternative to SplitTPA.
  6. [==============================================================================}
  7. function ClusterTPA(TPA: TPointArray; dist: Extended): T2DPointArray;
  8. type
  9.   TPointScan = record
  10.     skipRow: Boolean;
  11.     count: Integer;
  12.   end;
  13. var
  14.   h, i, l, c, s, x, y, o, r, d, m: Integer;
  15.   p: array of array of TPointScan;
  16.   q: TPointArray;
  17.   a, b, t: TBox;
  18.   e: Extended;
  19.   z: TPoint;
  20.   v: Boolean;
  21. begin
  22.   SetLength(Result, 0);
  23.   h := High(TPA);
  24.   if (h > -1) then
  25.     if (h > 0) then
  26.     begin
  27.       b.X1 := TPA[0].X;
  28.       b.Y1 := TPA[0].Y;
  29.       b.X2 := TPA[0].X;
  30.       b.Y2 := TPA[0].Y;
  31.       r := 0;
  32.       for i := 1 to h do
  33.       begin
  34.         if (TPA[i].X < b.X1) then
  35.           b.X1 := TPA[i].X
  36.         else
  37.           if (TPA[i].X > b.X2) then
  38.             b.X2 := TPA[i].X;
  39.         if (TPA[i].Y < b.Y1) then
  40.           b.Y1 := TPA[i].Y
  41.         else
  42.           if (TPA[i].Y > b.Y2) then
  43.             b.Y2 := TPA[i].Y;
  44.       end;
  45.       SetLength(p, ((b.X2 - b.X1) + 1));
  46.       for i := 0 to (b.X2 - b.X1) do
  47.       begin
  48.         SetLength(p[i], ((b.Y2 - b.Y1) + 1));
  49.         for c := 0 to (b.Y2 - b.Y1) do
  50.         begin
  51.           p[i][c].count := 0;
  52.           p[i][c].skipRow := False;
  53.         end;
  54.       end;
  55.       if (dist < 0.0) then
  56.         dist := 0.0;
  57.       d := Ceil(dist);
  58.       m := Max(((b.X2 - b.X1) + 1), ((b.Y2 - b.Y1) + 1));
  59.       if (d > m) then
  60.         d := m;
  61.       for i := 0 to h do
  62.         Inc(p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  63.       for i := 0 to h do
  64.         if (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count > 0) then
  65.         begin
  66.           c := Length(Result);
  67.           SetLength(Result, (c + 1));
  68.           SetLength(Result[c], p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  69.           for o := 0 to (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count - 1) do
  70.             Result[c][o] := TPA[i];
  71.           r := (r + p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  72.           if (r > h) then
  73.             Exit;
  74.           SetLength(q, 1);
  75.           q[0] := TPA[i];
  76.           p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count := 0;
  77.           s := 1;
  78.           while (s > 0) do
  79.           begin
  80.             s := High(q);
  81.             z := q[s];
  82.             a.X1 := (z.X - d);
  83.             a.Y1 := (z.Y - d);
  84.             a.X2 := (z.X + d);
  85.             a.Y2 := (z.Y + d);
  86.             t := a;
  87.             SetLength(q, s);
  88.             if (a.X1 < b.X1) then
  89.               a.X1 := b.X1
  90.             else
  91.               if (a.X1 > b.X2) then
  92.                 a.X1 := b.X2;
  93.             if (a.Y1 < b.Y1) then
  94.               a.Y1 := b.Y1
  95.             else
  96.               if (a.Y1 > b.Y2) then
  97.                 a.Y1 := b.Y2;
  98.             if (a.X2 < b.X1) then
  99.               a.X2 := b.X1
  100.             else
  101.               if (a.X2 > b.X2) then
  102.                 a.X2 := b.X2;
  103.             if (a.Y2 < b.Y1) then
  104.               a.Y2 := b.Y1
  105.             else
  106.               if (a.Y2 > b.Y2) then
  107.                 a.Y2 := b.Y2;
  108.             case ((t.X1 <> a.X1) or (t.X2 <> a.X2)) of
  109.               True:
  110.               for y := a.Y1 to a.Y2 do
  111.                 if not p[(a.X2 - b.X1)][(y - b.Y1)].skipRow then
  112.                 for x := a.X1 to a.X2 do
  113.                   if (p[(x - b.X1)][(y - b.Y1)].count > 0) then
  114.                   begin
  115.                     e := Sqrt(Sqr(z.X - x) + Sqr(z.Y - y));
  116.                     if (e <= dist) then
  117.                     begin
  118.                       l := Length(Result[c]);
  119.                       SetLength(Result[c], (l + p[(x - b.X1)][(y - b.Y1)].count));
  120.                       for o := 0 to (p[(x - b.X1)][(y - b.Y1)].count - 1) do
  121.                       begin
  122.                         Result[c][(l + o)].X := x;
  123.                         Result[c][(l + o)].Y := y;
  124.                       end;
  125.                       r := (r + p[(x - b.X1)][(y - b.Y1)].count);
  126.                       if (r > h) then
  127.                         Exit;
  128.                       p[(x - b.X1)][(y - b.Y1)].count := 0;
  129.                       SetLength(q, (s + 1));
  130.                       q[s] := Result[c][l];
  131.                       Inc(s);
  132.                     end;
  133.                   end;
  134.               False:
  135.               for y := a.Y1 to a.Y2 do
  136.                 if not p[(a.X2 - b.X1)][(y - b.Y1)].skipRow then
  137.                 begin
  138.                   v := True;
  139.                   for x := a.X1 to a.X2 do
  140.                     if (p[(x - b.X1)][(y - b.Y1)].count > 0) then
  141.                     begin
  142.                       e := Sqrt(Sqr(z.X - x) + Sqr(z.Y - y));
  143.                       if (e <= dist) then
  144.                       begin
  145.                         l := Length(Result[c]);
  146.                         SetLength(Result[c], (l + p[(x - b.X1)][(y - b.Y1)].count));
  147.                         for o := 0 to (p[(x - b.X1)][(y - b.Y1)].count - 1) do
  148.                         begin
  149.                           Result[c][(l + o)].X := x;
  150.                           Result[c][(l + o)].Y := y;
  151.                         end;
  152.                         r := (r + p[(x - b.X1)][(y - b.Y1)].count);
  153.                         if (r > h) then
  154.                           Exit;
  155.                         p[(x - b.X1)][(y - b.Y1)].count := 0;
  156.                         SetLength(q, (s + 1));
  157.                         q[s] := Result[c][l];
  158.                         Inc(s);
  159.                       end else
  160.                         v := False;
  161.                     end;
  162.                   if v then
  163.                     p[(a.X2 - b.X1)][(y - b.Y1)].skipRow := True;
  164.                 end;
  165.             end;
  166.           end;
  167.         end;
  168.     end else
  169.     begin
  170.       SetLength(Result, 1);
  171.       SetLength(Result[0], 1);
  172.       Result[0][0] := TPA[0];
  173.     end;
  174. end;
  175.  
  176. {==============================================================================]
  177.  Splits TPA with width, height (alternative for SplitTPAEx).
  178. [==============================================================================}
  179. function ClusterTPAEx(TPA: TPointArray; width, height: Integer): T2DPointArray;
  180. type
  181.   TPointScan = record
  182.     skipRow: Boolean;
  183.     count: Integer;
  184.   end;
  185. var
  186.   h, i, l, c, s, x, y, o, r, m, dw, dh: Integer;
  187.   p: array of array of TPointScan;
  188.   q: TPointArray;
  189.   a, b, t: TBox;
  190.   z: TPoint;
  191. begin
  192.   SetLength(Result, 0);
  193.   h := High(TPA);
  194.   if (((width > 0) and (height > 0)) and (h > -1)) then
  195.     if (h > 0) then
  196.     begin
  197.       dw := width;
  198.       dh := height;
  199.       b.X1 := TPA[0].X;
  200.       b.Y1 := TPA[0].Y;
  201.       b.X2 := TPA[0].X;
  202.       b.Y2 := TPA[0].Y;
  203.       r := 0;
  204.       for i := 1 to h do
  205.       begin
  206.         if (TPA[i].X < b.X1) then
  207.           b.X1 := TPA[i].X
  208.         else
  209.           if (TPA[i].X > b.X2) then
  210.             b.X2 := TPA[i].X;
  211.         if (TPA[i].Y < b.Y1) then
  212.           b.Y1 := TPA[i].Y
  213.         else
  214.           if (TPA[i].Y > b.Y2) then
  215.             b.Y2 := TPA[i].Y;
  216.       end;
  217.       SetLength(p, ((b.X2 - b.X1) + 1));
  218.       for i := 0 to (b.X2 - b.X1) do
  219.       begin
  220.         SetLength(p[i], ((b.Y2 - b.Y1) + 1));
  221.         for c := 0 to (b.Y2 - b.Y1) do
  222.         begin
  223.           p[i][c].count := 0;
  224.           p[i][c].skipRow := False;
  225.         end;
  226.       end;
  227.       if (dw > ((b.X2 - b.X1) + 1)) then
  228.         dw := ((b.X2 - b.X1) + 1);
  229.       if (dh > ((b.Y2 - b.Y1) + 1)) then
  230.         dh := ((b.Y2 - b.Y1) + 1);
  231.       for i := 0 to h do
  232.         Inc(p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  233.       for i := 0 to h do
  234.         if (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count > 0) then
  235.         begin
  236.           c := Length(Result);
  237.           SetLength(Result, (c + 1));
  238.           SetLength(Result[c], p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  239.           for o := 0 to (p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count - 1) do
  240.             Result[c][o] := TPA[i];
  241.           r := (r + p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count);
  242.           if (r > h) then
  243.             Exit;
  244.           SetLength(q, 1);
  245.           q[0] := TPA[i];
  246.           p[(TPA[i].X - b.X1)][(TPA[i].Y - b.Y1)].count := 0;
  247.           s := 1;
  248.           while (s > 0) do
  249.           begin
  250.             s := High(q);
  251.             z := q[s];
  252.             a.X1 := (z.X - dw);
  253.             a.Y1 := (z.Y - dh);
  254.             a.X2 := (z.X + dw);
  255.             a.Y2 := (z.Y + dh);
  256.             t := a;
  257.             SetLength(q, s);
  258.             if (a.X1 < b.X1) then
  259.               a.X1 := b.X1
  260.             else
  261.               if (a.X1 > b.X2) then
  262.                 a.X1 := b.X2;
  263.             if (a.Y1 < b.Y1) then
  264.               a.Y1 := b.Y1
  265.             else
  266.               if (a.Y1 > b.Y2) then
  267.                 a.Y1 := b.Y2;
  268.             if (a.X2 < b.X1) then
  269.               a.X2 := b.X1
  270.             else
  271.               if (a.X2 > b.X2) then
  272.                 a.X2 := b.X2;
  273.             if (a.Y2 < b.Y1) then
  274.               a.Y2 := b.Y1
  275.             else
  276.               if (a.Y2 > b.Y2) then
  277.                 a.Y2 := b.Y2;
  278.             case ((t.X1 <> a.X1) or (t.X2 <> a.X2)) of
  279.               True:
  280.               for y := a.Y1 to a.Y2 do
  281.                 if not p[(a.X2 - b.X1)][(y - b.Y1)].skipRow then
  282.                 for x := a.X1 to a.X2 do
  283.                   if (p[(x - b.X1)][(y - b.Y1)].count > 0) then
  284.                   begin
  285.                     l := Length(Result[c]);
  286.                     SetLength(Result[c], (l + p[(x - b.X1)][(y - b.Y1)].count));
  287.                     for o := 0 to (p[(x - b.X1)][(y - b.Y1)].count - 1) do
  288.                     begin
  289.                       Result[c][(l + o)].X := x;
  290.                       Result[c][(l + o)].Y := y;
  291.                     end;
  292.                     r := (r + p[(x - b.X1)][(y - b.Y1)].count);
  293.                     if (r > h) then
  294.                       Exit;
  295.                     p[(x - b.X1)][(y - b.Y1)].count := 0;
  296.                     SetLength(q, (s + 1));
  297.                     q[s] := Result[c][l];
  298.                     Inc(s);
  299.                   end;
  300.               False:
  301.               for y := a.Y1 to a.Y2 do
  302.                 if not p[(a.X2 - b.X1)][(y - b.Y1)].skipRow then
  303.                 begin
  304.                   for x := a.X1 to a.X2 do
  305.                     if (p[(x - b.X1)][(y - b.Y1)].count > 0) then
  306.                     begin
  307.                       l := Length(Result[c]);
  308.                       SetLength(Result[c], (l + p[(x - b.X1)][(y - b.Y1)].count));
  309.                       for o := 0 to (p[(x - b.X1)][(y - b.Y1)].count - 1) do
  310.                       begin
  311.                         Result[c][(l + o)].X := x;
  312.                         Result[c][(l + o)].Y := y;
  313.                       end;
  314.                       r := (r + p[(x - b.X1)][(y - b.Y1)].count);
  315.                       if (r > h) then
  316.                         Exit;
  317.                       p[(x - b.X1)][(y - b.Y1)].count := 0;
  318.                       SetLength(q, (s + 1));
  319.                       q[s] := Result[c][l];
  320.                       Inc(s);
  321.                     end;
  322.                   p[(a.X2 - b.X1)][(y - b.Y1)].skipRow := True;
  323.                 end;
  324.             end;
  325.           end;
  326.         end;
  327.     end else
  328.     begin
  329.       SetLength(Result, 1);
  330.       SetLength(Result[0], 1);
  331.       Result[0][0] := TPA[0];
  332.     end;
  333. end;
  334.  
  335. {==============================================================================]
  336.   Explanation: Returns all the color points from bitmap as TPointArray.
  337.                Result is based on Row-by-Row.
  338. [==============================================================================}
  339. function GetBitmapColorTPA(bmp: Integer; color: Integer): TPointArray;
  340. var
  341.   w, h, x, y, r: Integer;
  342. begin
  343.   try
  344.     GetBitmapSize(bmp, w, h);
  345.   except
  346.   end;
  347.   if ((w > 0) and (h > 0)) then
  348.   begin
  349.     SetLength(Result, (w * h));
  350.     for y := 0 to (h - 1) do
  351.       for x := 0 to (w - 1) do
  352.         if (FastGetPixel(bmp, x, y) = color) then
  353.         begin
  354.           Result[r] := Point(x, y);
  355.           Inc(r);
  356.         end;
  357.   end;
  358.   SetLength(Result, r);
  359. end;
  360.  
  361. procedure DrawBounds(var bmp: Integer; ATPA: T2DPointArray; color: Integer);
  362. var
  363.   w, h, l, i, x, y: Integer;
  364.   b: TBox;
  365. begin
  366.   GetBitmapSize(bmp, w, h);
  367.   l := Length(ATPA);
  368.   for i := 0 to (l - 1) do
  369.   begin
  370.     b := GetTPABounds(ATPA[i]);
  371.     b.X1 := (b.X1 - 1);
  372.     b.Y1 := (b.Y1 - 1);
  373.     b.X2 := (b.X2 + 1);
  374.     b.Y2 := (b.Y2 + 1);
  375.     for x := b.X1 to b.X2 do
  376.       if ((x > -1) and (b.Y1 > -1) and (x < w) and (b.Y1 < h)) then
  377.         FastSetPixel(bmp, x, b.Y1, color);
  378.     for y := b.Y1 to b.Y2 do
  379.       if ((b.X2 > -1) and (y > -1) and (b.X2 < w) and (y < h)) then
  380.         FastSetPixel(bmp, b.X2, y, color);
  381.     for x := b.X2 downto b.X1 do
  382.       if ((x > -1) and (b.Y2 > -1) and (x < w) and (b.Y2 < h)) then
  383.         FastSetPixel(bmp, x, b.Y2, color);
  384.     for y := b.Y2 downto b.Y1 do
  385.       if ((b.X1 > -1) and (y > -1) and (b.X1 < w) and (y < h)) then
  386.       FastSetPixel(bmp, b.X1, y, color);
  387.   end;
  388. end;
  389.  
  390. procedure DebugBitmap(bmp: Integer);
  391. var
  392.   w, h: Integer;
  393. begin
  394.   GetBitmapSize(bmp, w, h);
  395.   DisplayDebugImgWindow(w, h);
  396.   DrawBitmapDebugImg(bmp);
  397. end;
  398.  
  399. procedure Test;
  400. var
  401.   bmp, t: Integer;
  402.   TPA: TPointArray;
  403.   ATPA: T2DPointArray;
  404. begin
  405.   ClearDebug;
  406.   bmp := BitmapFromString(1000, 600, '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');
  407.   TPA := GetBitmapColorTPA(bmp, 0);
  408.   t := GetSystemTime;
  409.   ATPA := ClusterTPA(TPA, DIST);
  410.   WriteLn('ClusterTPA took ' + IntToStr(GetSystemTime - t) + ' ms.');
  411.   WriteLn('Groups: ' + IntToStr(Length(ATPA)));
  412.   DrawBounds(bmp, ATPA, 13387839);
  413.   DebugBitmap(bmp);
  414.   SetLength(ATPA, 0);
  415.   t := GetSystemTime;
  416.   ATPA := ClusterTPAEx(TPA, DIST, DIST);
  417.   WriteLn('ClusterTPAEx took ' + IntToStr(GetSystemTime - t) + ' ms.');
  418.   WriteLn('Groups: ' + IntToStr(Length(ATPA)));
  419.   DrawBounds(bmp, ATPA, 8355711);
  420.   DebugBitmap(bmp);
  421.   SetLength(ATPA, 0);
  422.   t := GetSystemTime;
  423.   ATPA := SplitTPAEx(TPA, DIST, DIST);
  424.   WriteLn('SplitTPAEx took ' + IntToStr(GetSystemTime - t) + ' ms.');
  425.   WriteLn('Groups: ' + IntToStr(Length(ATPA)));
  426.   DrawBounds(bmp, ATPA, 255);
  427.   DebugBitmap(bmp);
  428.   SetLength(ATPA, 0);
  429.   t := GetSystemTime;
  430.   ATPA := SplitTPA(TPA, DIST);
  431.   WriteLn('SplitTPA took ' + IntToStr(GetSystemTime - t) + ' ms.');
  432.   WriteLn('Groups: ' + IntToStr(Length(ATPA)));
  433.   DrawBounds(bmp, ATPA, 5026082);
  434.   DebugBitmap(bmp);
  435. end;
  436.  
  437. begin
  438.   Test;
  439. end.
Advertisement
Add Comment
Please, Sign In to add comment