# Native Code > برنامه نویسی در Delphi >  کسی با فیلتر سوبل برای تشخیص لبه در پردازش تصویر استفاده کرد

## masoode

سلام
اگر کسی با فیلترهای تشخیص لبه عکس مثل sobel کارکرده و کامپوننتی یا unit سراغ داره به من کمک کنه
ممنون

----------


## Delphi-Clinic

سلام

یه سر بزن اینجا:

ٌwww.delphi-jedi.org

----------


## araz_pashazadeh

منم می خواستم اطلاعاتی در این ضمینه بدست بیارم منمنون می شم اگه دویتان در مورد این الگویتم و طریقه کار کرد اون اطلاعاتی بدن.

----------


## مصطفی ساتکی

هر فیلتر بوسیله کانولوشن انجام میشه . یعنی اعمال یک پنجره n*n در یک تصویر Grayscale. فیلتر Sobel یا مشتق مرتبه اول. در دو جهت x,y انجام میشه . شدت در هر سمت gx ,gy
gx=[-1,-2,-1
0,0,0
1,2,1
gy=[-1,0,1
-2,0,2
-1,0,1
gx, gy رو کانولوشن می کنی رو هر نقطه پس gx ,gy بدست می آید حالا بایستی  شدت رو محاسبه کنی      G=sqrt(sqr(gx)+sqr(gy))
g همون مقدار شدت محاسبه شده است. حال مقدار این شدت رو در بازه[255..0]کنترل کن اگر از صفر کوچکتر باشه صفر و اگر از 255 بزرگتر باشه 255. در هر نقطه شدتی که به دست میاری تو تصویر نهایی قرار بدیی فیلتر Sobel بدست میاد.در مورد اینکه چرا این کرنل ها در جهت x و y بدین صورت هستند به این پست مراجعه فرمائید.

----------


## araz_pashazadeh

ممنون از راهنمایی شما :لبخند: 
ولی من می خواستم اطلاعات کاملی در این ضمینه داشته باشم ممنون میشودم اگه در بدست اوردن این اطلاعات من را راهنمایی کنین :لبخند گشاده!:

----------


## مصطفی ساتکی

منظور شما رو از کامل نمی فهم.
این هم کدش.
for j := 1 to b.Height - 2 do begin
    for i := 1 to b.Width - 2 do begin
      gy[j][i] := ( p[j + 1][i - 1].r - p[j - 1][i - 1].r ) + 2 * ( p[j + 1][i].r - p[j - 1][i].r ) + ( p[j + 1][i + 1].r - p[j - 1][i + 1].r );
      gx[j][i] := ( p[j - 1][i + 1].r - p[j - 1][i - 1].r )
        + 2 * ( p[j][i + 1].r - p[j][i - 1].r )
        + ( p[j + 1][i + 1].r - p[j + 1][i - 1].r );
      mag[j][i] := sqrt( gx[j][i] * gx[j][i] + gy[j][i] * gy[j][i] );
    end;
  end;
برای اینکه اطلاعات بیشتری بدست بیاری به این تاپیک یه سری بزن
https://barnamenevis.org/showth...ighlight=canny

----------


## مصطفی ساتکی

این هم یه Class که برات Sobel می گیره.
دیگه فکر کنم با اون توضیحات و این کد کارت راه بیفته.
unit filterSobel;


interface
uses
  filter, fparameters, filterblur, filterConvolution, filterThresholdBinary, image;

type
  TFilterSobel = class(TFilter)
  public
    constructor Create; override;
    destructor Destroy; override;
    procedure run(); override;
    procedure setParameterImage( const aName: String; const aImage: PBitmap32); override ;
  private
    parameterImageIn, parameterImageOut, parameterImageOutDirection : TParameterImage;
    parameterBlurIteration : TParameterInteger;
    parameterGain : TParameterInteger;
    parameterThresholdLower : TParameterInteger;
    parameterThresholdUpper : TParameterInteger;
    parameterModeFast : TParameterString;
    filterBlur : TFilterBlur ;
    filterConvSobelHorizontal, filterConvSobelVertical : TFilterConvolution ;
    filterThresholdBinary : TFilterThresholdBinary;
    convImageSobelHorizontal, convImageSobelVertical : PBitmap32 ;
    imageBlurOut, imageSobelHorizontalOut, imageSobelVerticalOut, imageNormOut : PBitmap32;
    imageIn : PBitmap32;
    procedure _run();
    procedure deleteImages;
    procedure processNormal(imageIn : PBitmap32);
    procedure processFast(imageIn : PBitmap32);
  end;

implementation
uses
  imageIO, Math;

constructor TFilterSobel.Create;
begin
  inherited;

  parameterImageIn := addParameterImage( 'inImage','input image');
  parameterImageOut := addParameterImage( 'outImage','output image for the magnitude (edge strength)');
  parameterImageOutDirection := addParameterImage( 'outImageDirection','output image for the edge direction');
  parameterBlurIteration := addParameterInteger( 'blurIteration', 'if you want to preprocess to input image with a blur',0,50,1);
  parameterGain := addParameterInteger( 'gain', 'to amplify the magnitude', 1,1000,200);
  parameterThresholdLower := addParameterInteger( 'thresholdLower', 'if you want to postprocess the output image with a threshold',0,255,200);
  parameterThresholdUpper := addParameterInteger( 'thresholdUpper', 'if you want to postprocess the output image with a threshold',0,255,255);
  parameterModeFast := addParameterString( 'modeFast', 'TRUE/FALSE', 'TRUE');

  filterBlur :=  TFilterBlur.Create ;
  filterThresholdBinary:=TFilterThresholdBinary.Crea  te;

  filterConvSobelHorizontal := TFilterConvolution.Create ;
  convImageSobelHorizontal := image.createImage(3, 3) ;
  filterConvSobelHorizontal.setParameterImage('image  Conv',convImageSobelHorizontal);
  filterConvSobelHorizontal.setConvType(convSobelHor  izontal);

  filterConvSobelVertical := TFilterConvolution.Create ;
  convImageSobelVertical := image.createImage(3, 3) ;
  filterConvSobelVertical.setParameterImage('imageCo  nv',convImageSobelVertical);
  filterConvSobelVertical.setConvType(convSobelVerti  cal);
end;

destructor TFilterSobel.Destroy;
begin
  deleteImages;
  filterBlur.Free;
  filterConvSobelHorizontal.Free;
  filterConvSobelVertical.Free;
  filterThresholdBinary.Free;
  image.freeImage(convImageSobelHorizontal);
  image.freeImage(convImageSobelVertical);
end;

procedure TFilterSobel.deleteImages;
begin
  image.freeImage(imageBlurOut);
  image.freeImage(imageSobelHorizontalOut);
  image.freeImage(imageSobelVerticalOut);
  image.freeImage(imageNormOut);
end;

procedure TFilterSobel.setParameterImage( const aName: String; const aImage: PBitmap32);
begin
  if aName='inImage' then begin
    deleteImages;
    imageBlurOut := createImageFromImage(aImage);
    imageSobelHorizontalOut := createImageFromImage(aImage);
    imageSobelVerticalOut := createImageFromImage(aImage);
    imageNormOut := createImageFromImage(aImage);
  end;
  inherited;
end;

procedure TFilterSobel.run();
begin
  imageIn := parameterImageIn.Image;
  if (imageIn<>nil) then begin
    _run();
  end;
end;

procedure TFilterSobel._run();
var
  i : Integer;
begin
  // preprocess with blur
  if parameterBlurIteration.Value>0 then begin
    filterBlur.setParameterImage('inImage',imageIn);
    filterBlur.setParameterImage('outImage',imageBlurO  ut);
    i:=parameterBlurIteration.Value;
    while i>0 do begin
      filterBlur.Run;
      Dec(i);
      if imageIn<>parameterImageIn.Image then begin
        image.freeImage(imageIn);
      end;
      if i>0 then begin
        imageIn:=createImageFromImage(imageBlurOut);
        filterBlur.setParameterImage('inImage',imageIn);
      end;
    end;
    imageIn:=imageBlurOut;
  end;
  // process
  if parameterModeFast.Value='FALSE' then begin
    processNormal(imageIn);
  end else begin
    processFast(imageIn);
  end;
  // postprocess with Threshold
  if (parameterThresholdLower.Value<>0) and (parameterThresholdLower.Value<>255) then begin
    filterThresholdBinary.setParameterImage('inImage',  imageNormOut);
    filterThresholdBinary.setParameterImage('outImage'  ,parameterImageOut.Image);
    filterThresholdBinary.setParameterInteger('thresho  ldLower',parameterThresholdLower.Value);
    filterThresholdBinary.setParameterInteger('thresho  ldUpper',parameterThresholdUpper.Value);
    filterThresholdBinary.Run;
  end else begin
    copyImageToImage(imageNormOut, parameterImageOut.Image);
  end;
end;

procedure TFilterSobel.processNormal(imageIn : PBitmap32);
var
  pSrcGx, pSrcGy, pDest, pDestDirection : PColor32Array;
  g : Integer;
  w, h :Integer;
  x, y : Cardinal ;
  valueGx, valueGy : Integer;
  Flt : double;
  angleRad : Single;
  angleDeg : Integer;
  indexBuffer : Integer;
  const Half : double = 0.5;
begin
  // Sobel Horizontal
  filterConvSobelHorizontal.setParameterImage('inIma  ge',imageIn);
  filterConvSobelHorizontal.setParameterImage('outIm  age',imageSobelHorizontalOut);
  filterConvSobelHorizontal.setParameterInteger('z', parameterGain.Value);
  filterConvSobelHorizontal.Run;
  // Sobel Vertical
  filterConvSobelVertical.setParameterImage('inImage  ',imageIn);
  filterConvSobelVertical.setParameterImage('outImag  e',imageSobelVerticalOut);
  filterConvSobelVertical.setParameterInteger('z', parameterGain.Value);
  filterConvSobelVertical.Run;
  // g=Sqrt(Gx^2+Gy^2)
  pSrcGx := imageSobelHorizontalOut.Bits;
  pSrcGy := imageSobelVerticalOut.Bits;
  pDest := imageNormOut.Bits;
  if parameterImageOutDirection.Image<>nil then begin
    pDestDirection := parameterImageOutDirection.Image.Bits;
  end;
  h := parameterImageIn.Image.Height-1;
  w := parameterImageIn.Image.Width-1;
  for y:=h-1 downto 0 do Begin
    for x:=w-1 downto 0 do begin
      indexBuffer := y*w+x;
      valueGx := pSrcGx^[indexBuffer] and $000000FF;
      valueGy := pSrcGy^[indexBuffer] and $000000FF;
      Flt := Sqrt( valueGx*valueGx + valueGy*valueGy );
      // trunc float 'Flt' to integer 'g'
      asm
        fld Flt;
        fsub Half;
        fistp g;
      end;
    if g>255 then g:=255;
    pDest[indexBuffer] := Gray32( g );

    end;
  end ;
end;

procedure TFilterSobel.processFast(imageIn : PBitmap32);
var
  pSrc, PDest : PColor32Array;
  w,h :Integer;
  p1,p2,p3,p4,p6,p7,p8,p9 : Integer;
  g : Integer;
  imageSrcRow, imageSrcCol : Integer;
  imageSrcRowmax, imageSrcColmax : Integer;
  imageSrcNeighborRowmin, imageSrcNeighborColmin : Integer;
  imageSrcNeighborRowmax, imageSrcNeighborColmax : Integer;
begin
  h:=imageIn.Height;
  w:=imageIn.Width;
  pSrc:=imageIn.Bits;
  imageSrcRowmax:=h-1;
  imageSrcColmax:=w-1;
  for imageSrcRow:=0 to imageSrcRowmax do begin
    pDest:=imageNormOut.Bits;
    Inc(pDest,imageSrcRow*w);
    for imageSrcCol:=0 to imageSrcColmax do begin
      imageSrcNeighborRowmin:=imageSrcRow-1; if imageSrcNeighborRowmin<0 then imageSrcNeighborRowmin:=0;
      imageSrcNeighborColmin:=imageSrcCol-1; if imageSrcNeighborColmin<0 then imageSrcNeighborColmin:=0;
      imageSrcNeighborRowmax:=imageSrcRow+1; if imageSrcNeighborRowmax>imageSrcRowmax then imageSrcNeighborRowmax:=imageSrcRowmax;
      imageSrcNeighborColmax:=imageSrcCol+1; if imageSrcNeighborColmax>imageSrcColmax then imageSrcNeighborColmax:=imageSrcColmax;
      p1:=pSrc[imageSrcNeighborRowmin*w+imageSrcNeighborColmin] and $000000FF;
      p2:=pSrc[imageSrcNeighborRowmin*w+imageSrcCol] and $000000FF;
      p3:=pSrc[imageSrcNeighborRowmin*w+imageSrcNeighborColmax] and $000000FF;
      p4:=pSrc[imageSrcRow*w+imageSrcNeighborColmin] and $000000FF;
      p6:=pSrc[imageSrcRow*w+imageSrcNeighborColmax] and $000000FF;
      p7:=pSrc[imageSrcNeighborRowmax*w+imageSrcNeighborColmin] and $000000FF;
      p8:=pSrc[imageSrcNeighborRowmax*w+imageSrcCol] and $000000FF;
      p9:=pSrc[imageSrcNeighborRowmax*w+imageSrcNeighborColmax] and $000000FF;
      g:=abs((p1+2*p2+p3)-(p7+2*p8+p9))+abs((p3+2*p6+p9)-(p1+2*p4+p7));
      if g>255 then g:=255;
      // set gray value with Color32 for optimization
      pDest^[0]:= Color32(g,g,g);
      Inc(pDest);
    end;
  end;
end;

end.

----------

