نمایش نتایج 1 تا 13 از 13

نام تاپیک: الگوريتم canny

  1. #1
    کاربر دائمی آواتار asefy2008
    تاریخ عضویت
    مرداد 1387
    محل زندگی
    تهران
    سن
    37
    پست
    729

    الگوريتم canny

    سلام
    كسي از دوستان كد الگوريتم canny رو داره بزاره ممنون ميشم؟(حتي المكان با سي شارپ)

  2. #2
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    سلام کدشو به دلفی واست گذاشتم که زمانیکه canny رو از Delphi به C#‎‎ می بره عملکردشو هم یاد بگیری


    unit GBlur2;

    interface

    uses
    Windows, Graphics;

    type
    PRGBTriple = ^TRGBTriple;
    TRGBTriple = packed record
    b: byte; {easier to type than rgbtBlue}
    g: byte;
    r: byte;
    end;
    PRow = ^TRow;
    TRow = array[0..1000000] of TRGBTriple;
    PPRows = ^TPRows;
    TPRows = array[0..1000000] of PRow;

    const
    MaxKernelSize = 100;

    type
    TKernelSize = 1..MaxKernelSize;
    TKernel = record
    Size: TKernelSize;
    Weights: array[-MaxKernelSize..MaxKernelSize] of single;
    end;
    {the idea is that when using a TKernel you ignore the Weights except
    for Weights in the range -Size..Size.}

    procedure GBlur(theBitmap: TBitmap; radius: double);

    implementation

    uses
    SysUtils;

    procedure MakeGaussianKernel(var K: TKernel; radius: double; MaxData, DataGranularity: double);
    {makes K into a gaussian kernel with standard deviation = radius. For the current application
    you set MaxData = 255 and DataGranularity = 1. Now the procedure sets the value of K.Size so
    that when we use K we will ignore the Weights that are so small they can't possibly matter. (Small
    Size is good because the execution time is going to be propertional to K.Size.)}
    var
    j: integer;
    temp, delta: double;
    KernelSize: TKernelSize;
    begin
    for j := Low(K.Weights) to High(K.Weights) do
    begin
    temp := j / radius;
    K.Weights[j] := exp(-temp * temp / 2);
    end;
    {now divide by constant so sum(Weights) = 1:}
    temp := 0;
    for j := Low(K.Weights) to High(K.Weights) do
    temp := temp + K.Weights[j];
    for j := Low(K.Weights) to High(K.Weights) do
    K.Weights[j] := K.Weights[j] / temp;
    {now discard (or rather mark as ignorable by setting Size) the entries that are too small to matter.
    This is important, otherwise a blur with a small radius will take as long as with a large radius...}
    KernelSize := MaxKernelSize;
    delta := DataGranularity / (2 * MaxData);
    temp := 0;
    while (temp < delta) and (KernelSize > 1) do
    begin
    temp := temp + 2 * K.Weights[KernelSize];
    dec(KernelSize);
    end;
    K.Size := KernelSize;
    {now just to be correct go back and jiggle again so the sum of the entries we'll be using is exactly 1}
    temp := 0;
    for j := -K.Size to K.Size do
    temp := temp + K.Weights[j];
    for j := -K.Size to K.Size do
    K.Weights[j] := K.Weights[j] / temp;
    end;

    function TrimInt(Lower, Upper, theInteger: integer): integer;
    begin
    if (theInteger <= Upper) and (theInteger >= Lower) then
    result := theInteger
    else if theInteger > Upper then
    result := Upper
    else
    result := Lower;
    end;

    function TrimReal(Lower, Upper: integer; x: double): integer;
    begin
    if (x < upper) and (x >= lower) then
    result := trunc(x)
    else if x > Upper then
    result := Upper
    else
    result := Lower;
    end;

    procedure BlurRow(var theRow: array of TRGBTriple; K: TKernel; P: PRow);
    var
    j, n, LocalRow: integer;
    tr, tg, tb: double; {tempRed, etc}
    w: double;
    begin
    for j := 0 to High(theRow) do
    begin
    tb := 0;
    tg := 0;
    tr := 0;
    for n := -K.Size to K.Size do
    begin
    w := K.Weights[n];
    {the TrimInt keeps us from running off the edge of the row...}
    with theRow[TrimInt(0, High(theRow), j - n)] do
    begin
    tb := tb + w * b;
    tg := tg + w * g;
    tr := tr + w * r;
    end;
    end;
    with P[j] do
    begin
    b := TrimReal(0, 255, tb);
    g := TrimReal(0, 255, tg);
    r := TrimReal(0, 255, tr);
    end;
    end;
    Move(P[0], theRow[0], (High(theRow) + 1) * Sizeof(TRGBTriple));
    end;

    procedure GBlur(theBitmap: TBitmap; radius: double);
    var
    Row, Col: integer;
    theRows: PPRows;
    K: TKernel;
    ACol: PRow;
    P: PRow;
    begin
    if (theBitmap.HandleType <> bmDIB) or (theBitmap.PixelFormat <> pf24Bit) then
    raise exception.Create('GBlur only works for 24-bit bitmaps');
    MakeGaussianKernel(K, radius, 255, 1);
    GetMem(theRows, theBitmap.Height * SizeOf(PRow));
    GetMem(ACol, theBitmap.Height * SizeOf(TRGBTriple));
    {record the location of the bitmap data:}
    for Row := 0 to theBitmap.Height - 1 do
    theRows[Row] := theBitmap.Scanline[Row];
    {blur each row:}
    P := AllocMem(theBitmap.Width * SizeOf(TRGBTriple));
    for Row := 0 to theBitmap.Height - 1 do
    BlurRow(Slice(theRows[Row]^, theBitmap.Width), K, P);
    {now blur each column}
    ReAllocMem(P, theBitmap.Height * SizeOf(TRGBTriple));
    for Col := 0 to theBitmap.Width - 1 do
    begin
    {first read the column into a TRow:}
    for Row := 0 to theBitmap.Height - 1 do
    ACol[Row] := theRows[Row][Col];
    BlurRow(Slice(ACol^, theBitmap.Height), K, P);
    {now put that row, um, column back into the data:}
    for Row := 0 to theBitmap.Height - 1 do
    theRows[Row][Col] := ACol[Row];
    end;
    FreeMem(theRows);
    FreeMem(ACol);
    ReAllocMem(P, 0);
    end;

    end.



    Example:


    procedure TForm1.Button1Click(Sender: TObject);
    var
    b: TBitmap;
    begin
    if not openDialog1.Execute then
    exit;
    b := TBitmap.Create;
    b.LoadFromFile(OpenDialog1.Filename);
    b.PixelFormat := pf24Bit;
    Canvas.Draw(0, 0, b);
    GBlur(b, StrToFloat(Edit1.text));
    Canvas.Draw(b.Width, 0, b);
    b.Free;
    end;



    راستی اگه می خوای رو موضوع خاصی کار کنی بایستی سیگما که مربوط به kernel گوس و threshold1,threshold2 رو مشخص کنی البته یه روشی واسه تعیین threshold نرمال هم وجود داره اگه خواستی تاپیک بزن.اگه کار عمومیت داره کانی به دردت نمی خوره بایستی hybrid کار کنی یعنی با NN یاFuzzy ترکیبش کنی

  3. #3
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    اون بالا فقط guassian blur چون برای انجام لبه canny ابتدا با رو تصویر اونو اعمال کنی
    function canny( b: TBitmap ): TBitmap;
    var
    kv, kh : array[0..2, 0..2] of real;
    i, j, k, l : integer;
    p : array of PArrRGB;
    mag, gx, gy : array of array of real;
    bg, br : TBitmap;
    dir : real;
    tmp, dx, dy : integer;
    pr : ParrRGB;
    ap : array of TPoint;
    edge : array of array of boolean;
    pt : array of tpoint;
    thrlow, thrhigh : real;

    function trace( x, y: integer ): boolean;
    var
    i, j : integer;

    function ok( x, y: integer ): boolean;
    begin
    result := ( x >= 0 ) and ( y >= 0 ) and ( x < b.Width ) and ( y < b.Height );
    end;
    begin
    result := false;
    if not edge[y][x] then exit;

    edge[y][x] := false;
    result := mag[y][x] >= thrhigh;
    for j := -1 to 1 do
    for i := -1 to 1 do
    if ok( x + i, y + j ) then
    result := trace( x + i, y + j ) or result;

    //jika hasil rekursi menghasilkan true
    //(terhubung dengan piksel yang nilainya lebih besar dari hi-threshold)
    if result then begin
    pr := br.ScanLine[y];
    pr[x] := rgb_hitam;//citra yang baru berwarna latar putih
    end;
    end;
    begin
    bg := gaussian( b, 1 );
    result := citra_create( b.Width, b.Height );//buat citra(bitmap) baru

    setlength( p, b.Height );
    for j := 0 to high( p ) do
    p[j] := bg.ScanLine[j];

    setlength( gx, b.Height );
    for j := 0 to high( gx ) do
    setlength( gx[j], b.Width );

    setlength( gy, b.Height );
    for j := 0 to high( gx ) do
    setlength( gy[j], b.Width );

    setlength( mag, b.Height );
    for j := 0 to high( mag ) do
    setlength( mag[j], b.Width );

    setlength( edge, b.Height );
    for j := 0 to high( edge ) do
    setlength( edge[j], b.Width );

    //hitung gradien gx dan gy menggunakan operator sobel
    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;

    //non-maximal suppression
    for j := 1 to b.Height - 2 do begin
    for i := 1 to b.Width - 2 do begin
    dir := arctan2( gy[j][i], gx[j][i] );
    dx := round( cos( dir ) );
    dy := round( sin( dir ) );

    edge[j][i] := ( mag[j][i] >= mag[j + dy][i + dx] ) and ( mag[j][i] >= mag[j - dy][i - dx] );
    if edge[j][i] then begin
    edge[j + dy][i + dx] := false;
    edge[j - dy][i - dx] := false;
    end;
    end;
    end;

    //apply hysteresis
    thrlow := 10;
    thrhigh := 90;
    br := result;
    for j := 1 to b.Height - 2 do begin
    for i := 1 to b.Width - 2 do begin
    if edge[j][i] then trace( i, j );//trace melakukan edge-linking
    end;
    end;
    end;

  4. #4
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    کانی اول اینو روی سیگنال یه بعدی پیاده کرد و بعد آوردش رو 2 بعد(تصویر).به این خاطر از فیلتر پایین گذر گوس استفاده کرد تا نویز موجود در تصویرو از بین ببره.ابتدا تصویرتو gray scale کن روش gaussian blur رو اعمال کن بعد اون بایستی از متشق مرتبه اول یا فیلتر sobel استفاده کنی
    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 همون مقدار شدت محاسبه شده است.
    برای بدست آوردن زوایه مابین gx,gy از teta=arctan(gy/gx) می کنه این زوایه شدت در هر نقطه بهت می ده .سپس با یستی این زوایایه بدست آمده رو round کنی خلاصه کلام چون kernel 3*3 می خایم تعیین کنیم زوایه در راستای کدوم چهر جهت اصلیه.
    0و90و180 یا 270
    پس از پیدا کردن بایست عمل non-maximal suppression رو انجام بدی همون طور که از اسمش پیدا یعنی هر چی غیر از جهت شدت باشه حذف می کنه بعد این بایستی hysteresis رو اعمال کنی چون تا الان اگه تصویر رو ببینی لبه خیلی ضخیمن پس بایستی لبه ها رو نازک کنی. مثل یه trace ساده نو 8 خونه مجاور یه نقطه. اون 2 تا Threshold که گفتم اگه یادت نرفته اینجا به دردت می خوره هر نقطه که پایین تر از threshold1 باشه 0 (BackColor) و هر نقطه بالاتر از threshold2 باشه 255 (EdgeColor) می شه هر نقطه هم که مابین این دو threshold باشه اگر با یک نقطه ای شدتش بزرگتر مساوی threshold2 به 255 تبدیل می شه و گرنه صفر می شه
    اینو می گن الگوریتم لبه کانی به همین راحتی

  5. #5
    کاربر دائمی آواتار asefy2008
    تاریخ عضویت
    مرداد 1387
    محل زندگی
    تهران
    سن
    37
    پست
    729

    نقل قول: الگوريتم canny

    با یک دنیا تشکر از راهنمایی هاتون ولی یه سوال داشتم :
    gaussian blur رو چطور میشه اعمل کرد (توضیح )

  6. #6
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    gaussian blur ابتدا یک kernel تولید میکنه و سپس این kernel رو بروی کل تصویر اعمال می کنه کد اول مربوط به اونه .این kernel در حالت 3 بعدی به شکل کلاه مکزیکیه.در واقع به این خاطر از این فیلتر پایین گذر استفاده می کنه که نویز موجود در تصویر رو کاهش بده. اگر شما بخاید Realtime کار کنید حتماً نبایست از Kernel گوس استفاده کنید یه فیلتر معمولی هم میشه استفاده کرد .
    خبر جدید : من فیلتر لبه ای رو با شبکه SOFM تولید کردم که جواب خیلی خوبی رو نسبت به canny می ده و Realtime عمل می کنه. Canny به چندین پارامتر وابسته است و این مشکل threshold1,threshold2 و همین Sigma که میزان تاثیر فیلتر پایین گذر رو مشخص می کنه.Canny در همهئ شرایط نمی تونه جواب مطلوب رو به شما بده.

  7. #7
    کاربر دائمی آواتار asefy2008
    تاریخ عضویت
    مرداد 1387
    محل زندگی
    تهران
    سن
    37
    پست
    729

    نقل قول: الگوريتم canny

    نمی دونم درست فهمیدم یا نه. میگم اگر اشتباه بود لطف کن و اصلاح کن :
    gaussian blur یک آرایه 3*3 به ما میده که ما اون رو کل تصویر اعمال کنیم .
    این آرایه از طریق مشتق گیری از آرایه زیر بدست میاد:
    1 2 1
    2 4 2
    1 2 1

    اگر اشتباه گفتم لطفا کامل توضیح بده چون سورس gaussian blur رو به زبان سی شارپ دانلود کردم بازم متوجه نشدم (البته سورسش اجرا نمی شد ولی شبیه کد شما بود.)

  8. #8
    کاربر دائمی آواتار asefy2008
    تاریخ عضویت
    مرداد 1387
    محل زندگی
    تهران
    سن
    37
    پست
    729

    نقل قول: الگوريتم canny

    راستی یادم رفت بگم دارم روی تشخیص هویت از طریق عنبیه کار می کنم.

  9. #9
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    نه الزاماً 3*3 می تونه هر ابعادی داشته باشه و این مقدار بستگی به Sigma داره که میزان انتشار رو مشخص مینکه.بعلت محاسبات زمانگیر Guassian blur مقدار اون را از یک حد به بالاتر نادیده می گیرند چون این اعداد حذف شده اعشاری بوده و محاسباتشون زمانگیر و البته تاثیر زیادی هر مبر خروجی نداره .این کدی رو که در بالا براتون گذاشتم برای اینکه سرعت محاسبات بالاتر باشه مثل FFT عمل میکنه.یعنی بجای اینکه درجا به صورت 2 بعدی عمل کنه 2 بار به صورت یک بعدی عمل میکنه.یکبار Kernel مد نظر مون که یک آرایه متقارن بروی سطر ها اعمال میکنه و بار دیگه بروی ستون ها.شما برای اینکه راحتر متوجه بشید Function مربوط Gblur رو تیکه تیکه اجرا کند تا خروجی هر قسمت رو بروی تصویر مقصدتون ببینید. مقادیر آرایه Kernel از قبل تعیین شده نیست و با مشخص نمودن sigma محاسبه میشه

  10. #10

    نقل قول: الگوريتم canny

    نقل قول نوشته شده توسط Delphi_CAT مشاهده تاپیک
    gaussian blur ابتدا یک kernel تولید میکنه و سپس این kernel رو بروی کل تصویر اعمال می کنه کد اول مربوط به اونه .این kernel در حالت 3 بعدی به شکل کلاه مکزیکیه.در واقع به این خاطر از این فیلتر پایین گذر استفاده می کنه که نویز موجود در تصویر رو کاهش بده. اگر شما بخاید Realtime کار کنید حتماً نبایست از Kernel گوس استفاده کنید یه فیلتر معمولی هم میشه استفاده کرد .
    خبر جدید : من فیلتر لبه ای رو با شبکه SOFM تولید کردم که جواب خیلی خوبی رو نسبت به canny می ده و Realtime عمل می کنه. Canny به چندین پارامتر وابسته است و این مشکل threshold1,threshold2 و همین Sigma که میزان تاثیر فیلتر پایین گذر رو مشخص می کنه.Canny در همهئ شرایط نمی تونه جواب مطلوب رو به شما بده.
    این روشی که شما معرفی کردید از canny بهتره؟
    من اطلاعاتی رو در مورد canny میخوام، چون با OpenCV میخوام کار کنم و توسط الگوریتم canny لبه گیری میکنه ولی من نمیدونم پارامتر های threshold رو چی بدم که جوابی که میخوام رو بهم بده!
    ممنونم میشم در این زمینه کمکم کنید!

  11. #11
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    تعیین threshold بستگی به میزان روشنایی و نویز بستگی داره که با توجه به فیلدی که در اون کار می کنید این پارامتر set میشه .اگر مایلید که این پارامتر ها به صورت هوشمندانه تعیین شوند یعنی با توجه به نور محیط میزان نویز با یستی از cnn استفاده کنید که در opencv همچین چیزی وجود نداره اگر هم کارتون تجاریه با من تماس بگیرید.
    موفق باشید

  12. #12

    نقل قول: الگوريتم canny

    سلام بچه ها من فیلترهای پردازش تصویر مثل سابل و گاوسین و لاپلاس رو نیاز دارم میشه خواهش کنم کدهاش رو بذارید

  13. #13
    کاربر دائمی آواتار مصطفی ساتکی
    تاریخ عضویت
    اردیبهشت 1386
    محل زندگی
    www.7khatcode.com
    پست
    1,193

    نقل قول: الگوريتم canny

    البته سوالي كه شما پرسيد بايستي براش يه تاپيك ايجاد مي كرديد.

    اين 3 مورد رو كه شما نياز داريد تحت عنوان فيلتر در image processing و singnal processing استفاده ميشن.در واقع با اعمال فيلتر ها در تصوير ماهيتشون رو به گونه اي تغيير ميدم كه بتونيم از تصوير بدست آمده feature هاي مورد نياز رو extract كنيم.
    در واقع براي اعمال فيلتر شما بايستي يك ماتريس رو در كل تصوير ضرب كنيد كه به اين عمل convolution گفته ميشه.
    اين ماتريسي كه در تصوير اصلي ضرب ميشه اصطلاحا kernel نام داره كه به ابعاد اون support size گفته ميشه.كه در اغلب كاربردها اين ابعاد برابره مثل 3*3 يا 5*5 هر چقدر اين اندازه بزرگتر باشه شما neighbor هاي بيشتري رو در بدست آوردن مقدار intensity پيكسل جاري شركت ميديد.
    مثلاً فيلتر اولي كه گفتيد sobel در 2 جهت بر روي تصوير اعمال ميشه x,y .
    فيلتر در واقع همون مشتق مرتبه اول در راستاي x و y .(گراديان) مشتق در واقع ميزان اختلاف رو به ما نشون ميده.
    لاپلاسين يعني حاصل جمع مشتق مرتبه دوم در راستاي x و y.
    شما در لبه اشيا ميزان intensity اختلاف زيادي داره كه در واقع با اعمال گراديان و لاپلاسين اين لبه ها نمايان ميشه.
    البته نا گفته نمونه كه شما مي تونيد از orientation و magnitude گراديان هم استفاده كنيد. در ضمن گراديان و لاپلاسين بالاگذرند
    يه فيلتر ديگه كه فرموديد gaussian هستش كه يه فيلتر پاپپن گذر .در واقع يكجور هموار كننده كه عمل smooth كردن رو انجام ميده. در مواردي كه شما در تصويرتون نويز داريد با اعمال gaussian اين نويز ها در تصوير از بين ميرن. البته اين كاربردش در تصويره در signal هم كاربردهاي متنوعي داره.
    مثلا يه مثال signal براتون بزنم شما زمانيكه در يك جريان صوتي صداي foreground قطع شده صداي background مثل
    صداي باد به گوش ميرسه شما كافي اين سيگنال رو gaussian بگيريد و از خودش كسر كنيد صداي باد از بين ميره.

    براي اعمال فيلتر ها به صورت استاتيك و در support size مشخص مثلاً 3*3 مي تونيد به صورت زير عمل كنيد.
    sobelHorizontal[3][3] = {1, 2, 1, 0, 0, 0, -1, -2, -1 };
    sobelVertical[3][3] = {1, 0, -1, 2, 0, -2, 1, 0, -1 }
    gaussian[3][3] = {1, 2, 1, 2, 4, 2, 1, 2, 1}
    Laplacian [3][3] = {-1, -1, -1, -1, 8, -1, -1, -1, -1 };

    كه توضيحاتي كه در بالا ارائه شد در حالت spatial بود كه همين فيلتر ها رو تو حوزه
    فركانس هم ميشه اعمال كرد
    آخرین ویرایش به وسیله مصطفی ساتکی : جمعه 24 تیر 1390 در 18:50 عصر

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •