Advertisement
WarPie90

[Simba1300] Canny & Hough

Jul 2nd, 2018
501
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 7.00 KB | None | 0 0
  1. program Canny;
  2. {$I SRL1300/osr.simba}
  3. {$R-}
  4.  
  5. procedure SplitRGB(a: TMufasaBitmap; out R,G,B: TSingleMatrix);
  6. var
  7.   W,H,x,y: Int32;
  8. begin
  9.   W := a.GetWidth();
  10.   H := a.GetHeight();
  11.   R.SetSize(W,H);
  12.   G.SetSize(W,H);
  13.   B.SetSize(W,H);
  14.   for y:=0 to H-1 do
  15.     for x:=0 to W-1 do begin
  16.       R[y,x] := (a.GetPixel(x,y){shr 00}and $FF);
  17.       G[y,x] := (a.GetPixel(x,y) shr 08 and $FF);
  18.       B[y,x] := (a.GetPixel(x,y) shr 16 and $FF);
  19.     end;
  20. end;
  21.  
  22. procedure Gradients(a: TMufasaBitmap; out Mag, Dir: TSingleMatrix);
  23. var
  24.   W,H,x,y: Int32;
  25.   dx,dy,theta: Single;
  26.   r,g,b: TSingleMatrix;
  27. const
  28.   Deg22_5:  Single = 0.3926990816987;
  29.   Deg45_0:  Single = 0.7853981633975;
  30.   Deg67_5:  Single = Deg45_0 + Deg22_5;
  31.   Deg90_0:  Single = 1.5707963267949;
  32.   Deg112_5: Single = Deg90_0 + Deg22_5;
  33.   Deg135_0: Single = 2.35619449019234;
  34.   Deg157_5: Single = Deg135_0 + Deg22_5;
  35. begin
  36.   W := a.GetWidth();
  37.   H := a.GetHeight();
  38.  
  39.   Mag.SetSize(W, H);
  40.   Dir.SetSize(W, H);
  41.  
  42.   SplitRGB(a, r,g,b);
  43.  
  44.   for y:=1 to H-2 do
  45.     for x:=1 to W-2 do
  46.     begin
  47.       dx := (-1 * r[y-1,x-1]) + (-2 * r[y-1,x+0]) + (-1 * r[y-1,x+1]) + (+1 * r[y+1,x-1]) + (+2 * r[y+1,x+0]) + (+1 * r[y+1,x+1]);
  48.       dy := (-1 * r[y-1,x-1]) + (+1 * r[y-1,x+1]) + (-2 * r[y+0,x-1]) + (+2 * r[y+0,x+1]) + (-1 * r[y+1,x-1]) + (+1 * r[y+1,x+1]);
  49.  
  50.       dx += (-1 * g[y-1,x-1]) + (-2 * g[y-1,x+0]) + (-1 * g[y-1,x+1]) + (+1 * g[y+1,x-1]) + (+2 * g[y+1,x+0]) + (+1 * g[y+1,x+1]);
  51.       dy += (-1 * g[y-1,x-1]) + (+1 * g[y-1,x+1]) + (-2 * g[y+0,x-1]) + (+2 * g[y+0,x+1]) + (-1 * g[y+1,x-1]) + (+1 * g[y+1,x+1]);
  52.  
  53.       dx += (-1 * b[y-1,x-1]) + (-2 * b[y-1,x+0]) + (-1 * b[y-1,x+1]) + (+1 * b[y+1,x-1]) + (+2 * b[y+1,x+0]) + (+1 * b[y+1,x+1]);
  54.       dy += (-1 * b[y-1,x-1]) + (+1 * b[y-1,x+1]) + (-2 * b[y+0,x-1]) + (+2 * b[y+0,x+1]) + (-1 * b[y+1,x-1]) + (+1 * b[y+1,x+1]);
  55.  
  56.       Mag[y,x] := Sqrt(Sqr(dx * 0.333333334) + Sqr(dy * 0.333333334));
  57.       theta := ArcTan2(dy,dx); // approximate me please
  58.       Dir[y,x] := -1;
  59.  
  60.       if      ((theta >= -Deg22_5) and (theta <= Deg22_5))  or ((theta <= -Deg157_5) or  (theta >= Deg157_5)) then
  61.         Dir[y,x] := 0
  62.       else if ((theta >= Deg22_5)  and (theta <= Deg67_5))  or ((theta <= -Deg112_5)  and (theta >= -Deg157_5)) then
  63.         Dir[y,x] := 1
  64.       else if ((theta >= Deg67_5)  and (theta <= Deg112_5)) or ((theta <= -Deg67_5)  and (theta >= -Deg112_5)) then
  65.         Dir[y,x] := 2
  66.       else if ((theta >= Deg112_5) and (theta <= Deg157_5)) or ((theta <= -Deg22_5) and (theta >= -Deg67_5)) then
  67.         Dir[y,x] := 3;
  68.     end;
  69. end;
  70.  
  71. function NonMaximaSuppress(Gm, Gd: TSingleMatrix; low:Single = 1.0): TSingleMatrix;
  72. var
  73.   x,y,dx,dy: Int32;
  74.   mag, theta: Single;
  75. begin
  76.   Result.SetSize(Gm.Width, Gm.Height);
  77.  
  78.   for y:=1 to Gm.Height()-2 do
  79.     for x:=1 to Gm.Width()-2 do
  80.     begin
  81.       mag := Gm[y,x];
  82.       if mag < low then Continue;
  83.       dx := 0;
  84.       dy := 0;
  85.       case Round(Gd[y,x]) of
  86.         0: if (mag > Gm[y+1,x  ]) and (mag > Gm[y-1,x  ]) then
  87.              Result[y,x] := mag;
  88.         1: if (mag > Gm[y-1,x-1]) and (mag > Gm[y+1,x+1]) then
  89.              Result[y,x] := mag;
  90.         2: if (mag > Gm[y,  x+1]) and (mag > Gm[y,  x-1]) then
  91.              Result[y,x] := mag;
  92.         3: if (mag > Gm[y-1,x+1]) and (mag > Gm[y+1,x-1]) then
  93.              Result[y,x] := mag;
  94.       end;
  95.     end;
  96. end;
  97.  
  98. function CannyThreshold(Image: TSingleMatrix; low, high: Int32): TSingleMatrix;
  99. var
  100.   i,j,x,y: Int32;
  101.   isValuable, isUnsure: Boolean;
  102. begin
  103.   Result.SetSize(Image.Width, Image.Height);
  104.  
  105.   for i:=1 to Image.Height-2 do
  106.   begin
  107.     for j:=1 to Image.Width-2 do
  108.     begin
  109.       if(Image[i,j] > high) then
  110.         Result[i,j] := 255
  111.       else if(Image[i,j] < Low) then
  112.         Result[i,j] := 0
  113.       else
  114.       begin
  115.         // figure out if it's low or high, must have high neighbor
  116.         isValuable := False;
  117.         isUnsure   := False;
  118.         for y:=i-1 to i+1 do
  119.         begin
  120.           for x:=j-1 to j+1 do
  121.           begin
  122.             if(Image[y,x] > high) then
  123.             begin
  124.               Result[i,j] := 255;
  125.               isValuable := True;
  126.               break;
  127.             end
  128.             else if (Image[y,x] <= high) and (Image[y,x] >= low) then
  129.               isUnsure := True;
  130.           end;
  131.           if (isValuable) then
  132.             break;
  133.         end;
  134.  
  135.         if(not isValuable) then
  136.           Result[i,j] := 0;
  137.       end;
  138.     end;
  139.   end;
  140. end;
  141.  
  142. function CannyEdge(Image: TMufasaBitmap; TLow, THigh: Int32): TSingleMatrix;
  143. var
  144.   Gm, Gd, nms: TSingleMatrix;
  145. begin
  146.   Gradients(Image, Gm, Gd);
  147.   nms := NonMaximaSuppress(Gm, Gd);
  148.   Result := CannyThreshold(nms, TLow, THigh);
  149. end;
  150.  
  151. function Hough(Edges: TSingleMatrix; ntx, mry: Int32): TSingleMatrix;
  152. var
  153.   H,W, x,y, ts,iry: Int32;
  154.   rmax, dr,dth, th,r, col: Single;
  155. begin
  156.   W := Edges.Width;
  157.   H := Edges.Height;
  158.   mry := (mry div 2) * 2;
  159.  
  160.   Result.SetSize(ntx, mry);
  161.  
  162.   rmax := Hypot(W,H);
  163.   dr  := rmax / (mry / 2);
  164.   dth := PI / ntx;
  165.  
  166.   for y:=0 to H-1 do
  167.     for x:=0 to W-1 do
  168.     begin
  169.       if Edges[y,x] = 0 then
  170.         continue;
  171.  
  172.       for ts:=0 to ntx-1 do
  173.       begin
  174.         th  := ts * dth;
  175.         r   := (x - w/2)*Cos(th) + (y - h/2)*Sin(th);
  176.         Result[Trunc(r + mry / 2), ts] += 1;
  177.       end;
  178.     end;
  179. end;
  180.  
  181.  
  182. function HoughLine(acc: TSingleMatrix; v: TPoint; iw,ih: Int32): TBox;
  183. var
  184.   t,r,tdeg: Double;
  185. begin
  186.   tdeg := v.x / 2;
  187.   t := Radians(tdeg);
  188.   r := v.y;
  189.  
  190.   with Result do
  191.   begin
  192.     r := (r - acc.Height / 2);
  193.       if (tdeg >= 45) and (tdeg <= 135) then
  194.     begin
  195.           x1 := 0;
  196.           y1 := (ih div 2) + Trunc((r - (x1 - iw/2) * Cos(t)) / Sin(t));
  197.           x2 := iw;
  198.           y2 := (ih div 2) + Trunc((r - (x2 - iw/2) * Cos(t)) / Sin(t));
  199.       end else
  200.       begin
  201.           y1 := 0;
  202.           x1 := (iw div 2) + Trunc((r - (y1 - ih/2) * Sin(t)) / Cos(t));
  203.           y2 := ih;
  204.           x2 := (iw div 2) + Trunc((r - (y2 - ih/2) * Sin(t)) / Cos(t));
  205.     end;
  206.   end;
  207. end;
  208.  
  209. function Test(bmp: TMufasaBitmap; thresh: Double): TBoxArray;
  210. var
  211.   i: Int32;
  212.   lp: TPointArray;
  213.   acc,edges: TSingleMatrix;
  214.   t: Double;
  215. begin
  216.   edges := CannyEdge(bmp, 35,50);
  217.   acc   := Hough(edges, 360, Trunc(Sqrt(2) * Max(bmp.GetWidth, bmp.GetHeight)));
  218.  
  219.   lp := acc.Indices(acc.Max*thresh, __GT__);
  220.   lp := lp.ToATPA(3).Means();
  221.  
  222.   for i:=0 to High(lp) do
  223.   begin
  224.     Result += HoughLine(acc, lp[i], bmp.GetWidth, bmp.GetHeight);
  225.   end;
  226. end;
  227.  
  228.  
  229. var
  230.   bmp, tmp: TMufasaBitmap;
  231.   i,W,H: Int32;
  232.   TPA: TPointArray;
  233.   Lines: TBoxArray;
  234. begin
  235.   bmp.Init(client.GetMBitmaps);
  236.   bmp.LoadFromFile('Images/chess.jpg');
  237.  
  238.   (*
  239.   tmp.Init(client.GetMBitmaps);
  240.   bmp.Downsample(2,tmp);
  241.   bmp.Free();
  242.   bmp := tmp;
  243.   *)
  244.  
  245.   bmp.Blur(3); bmp.Blur(3);
  246.  
  247.   Lines := Test(bmp, 0.40);
  248.   for i:=0 to High(Lines) do
  249.   begin
  250.     TPA := TPAFromLine(Lines[i].x1, Lines[i].y1, Lines[i].x2, Lines[i].y2);
  251.     TPA := TPA + TPA.OffsetFunc(Point(1,0));
  252.     FilterPointsBox(TPA, 0,0, bmp.GetWidth-1, bmp.GetHeight-1);
  253.     bmp.DrawTPA(TPA, $00FFFF);
  254.   end;
  255.  
  256.   bmp.Debug();
  257.   bmp.Free();
  258. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement