بایگانی برچسب برای: fishk hknda

استفاده از متد WhenAll برای اجرای چندین Task به صورت همزمان در سی شارپ

فرض کنید که داخل یک متد باید چندین متد را به صورت await فراخوانی کنید. به صورت عادی زمانی که متدها فراخوانی می شوند هر بخش await بعد از تکمیل await قبلی اجرا خواهد شد و مقادیر بازگشتی به صورت یکجا در اختیار شما قرار نمیگیرند. برای مثال، کد زیر را در نظر بگیرید:

private async void AsyncBtn_Click(object sender, EventArgs e)
{
    Result1TextBox.Text = (await Task1()).ToString();
    Result12extBox.Text = (await Task2()).ToString();
}
 
private Task < long > Task1()
{
    return Task.Run<long>(() = >
    {
        var num = Enumerable.Repeat(10, 1000);
        long sum = 0;
        foreach (var item in num)
        {
            System.Threading.Thread.Sleep(2);
            sum += item;
        }
        return sum;
    });
}
private Task < long > Task2()
{
    return Task.Run<long>(() = >
    {
        var num = Enumerable.Repeat(10, 1000);
        long sum = 0;
        foreach (var item in num)
        {
            System.Threading.Thread.Sleep(2);
            sum += item;
        }
        return sum;
    });
}

 

در کد بالا، ابتدا عملیات Task1 انجام شده و نتیجه نمایش داده می شود و پس از آن Task2 اجرا شده و نتیجه نمایش داده می شود. برای رفع وقفه بین اجرای دو Task از متد WhenAll استفاده می کنیم. برای استفاده از متد WhenAll کد BtnAsync_Click را به صورت زیر تغییر می دهیم:

 

private async void AsyncBtn_Click(object sender, EventArgs e)
{
    var results = await Task.WhenAll(Task1(), Task2());
    txtBox.Text = results[0].ToString();
    txtSecond.Text = results[1].ToString();
}

 

با ایجاد تغییر کد بالا، خروجی متد WhenAll یک آرایه از نوع long خواهد بود که هر یک از اندیس های آرایه به ترتیب خروجی متدهای اول و دوم می باشد و به صورت بالا می توان خروجی ها را در TextBox ها نمایش داد.

منبع


قسمت اول آموزش-برنامه نویسی Asynchronous – آشنایی با Process ها، Thread ها و AppDomain ها

قسمت دوم آموزش- آشنایی با ماهیت Asynchronous در Delegate ها

قسمت سوم آموزش-آشنایی با فضای نام System.Threading و کلاس Thread

قسمت چهارم آموزش- آشنایی با Thread های Foreground و Background در دات نت

قسمت پنجم آموزش- آشنایی با مشکل Concurrency در برنامه های Multi-Threaded و راهکار های رفع این مشکل

قسمت ششم آموزش- آشنایی با کلاس Timer در زبان سی شارپ

قسمت هفتم آموزش-آشنایی با CLR ThreadPool در دات نت

قسمت هشتم آموزش- مقدمه ای بر Task Parallel Library و کلاس Parallel در دات نت

قسمت نهم آموزش- برنامه نویسی Parallel:آشنایی با کلاس Task در سی شارپ

قسمت دهم آموزش-برنامه نویسی Parallel در سی شارپ :: متوقف کردن Task ها در سی شارپ – کلاس CancellationToken

قسمت یازدهم آموزش- برنامه نویسی Parallel در سی شارپ :: کوئری های Parallel در LINQ

قسمت دوازدهم آموزش- آشنایی با کلمات کلیدی async و await در زبان سی شارپ

قسمت سیزدهم آموزش- استفاده از متد WhenAll برای اجرای چندین Task به صورت همزمان در سی شارپ

 

 

 

الگوریتم Canny

لبه یاب کنی توسط جان اف کنی در سال 1986 ایجاد شد و هنوز یک لبه یاب استاندارد و با دقت و کیفیت بالا میباشد.الگوریتم لبه یابی کنی یکی از بهترین لبه یابها تا به امروز است. در ادامه روش کار این الگوریتم و هم چنین کد الگوریتم Canny در C را بررسی خواهیم کرد. این الگوریتم لبه یابی از سه بخش اصلی زیر تشکیل شده است:

  • تضعیف نویز
  • پیدا کردن نقاطی که بتوان آنها را به عنوان لبه در نظر گرفت
  • جذب نقاطی که احتمال لبه بودن آنها کم است

 

معیارهایی که در لبه یاب کنی مطرح می باشد:
1 -پایین آوردن نرخ خطا- یعنی تا حد امکان هیچ لبه ای در تصویر نباید گم شود و هم چنین هیچ چیزی که لبه نیست نباید به جای لبه فرض شود. لبه هان پیدا شده تا حد ممکن به لبه ها اصلی
نزدیک باشند.

2 -لبه در مکان واقعی خود باشد- یعنی تا حد ممکن لبه ها کمترین فاصله را با مکان واقعی خود داشته باشند.
3 -بران هر لبه فقط یک پاسخ داشته باشیم.

4 -لبه ها کمترین ضخامت را داشته باشند- (در صورت امکان یک پیکسل).
لبه یاب کنی بخاطر توانایی در تولید لبه های نازک تا حد یک ییکسل برای لبه های پیوسته معروف شده است. این لبه یاب شامل چهار مرحله و چهار ورودی زیر است:
یک تصویر ورودی
یک پارامتر به نام سیگما جهت مقدار نرم کنندگی تصویر
یک حد آستانه بالا (Th)
یک حد آستانه پایین (Tl)

 

مراحل الگوریتم Canny:

1- در ابتدا باید تصویر رنگی را به جهت لبه یابی بهتر به یک تصویر سطح خاکسترن تبدیب کرد.

2- نویز را از تصویر دریافتی حذف کرد. بدلیل اینکه فیلتر گاوسین از یک ماسک ساده برای حذف نویز استفاده می کند لبه یاب کنی در مرحله اول برای حذف نویز آن را بکار می گیرد.

3- در یک تصویر سطح خاکستر جایی را که بیشترین تغییرات را داشته باشند به عنوان لبه در نظر گرفته می شوند و این مکانها با گرفتن گرادیان تصویر با استفاده عملگر سوبل بدست می آیند. سپس لبه های مات یافت شده به لبه های تیزتر تبدیل می شوند.

4- برخی از لبه های کشف شده واقعا لبه نیستند و در واقع نویز هستند که باید آنها توسط حد آستانه هیسترزیس فیلتر شوند.هیسترزیس از دو حد آستانه بالاتر (Th) و حد آستانه پایین تر (Tl) استفاده کرده و کنی پیشنهاد می کند که نسبت استانه بالا به پایین سه به یک باشد.

 این روش بیشتر به کشف لبه های ضعیف به درستی می پردازد و کمتر فریب نویز را می خورد و از بقیه روش ها بهتر است.

 

الگوریتم Canny    عملکرد الگوریتم Canny

 

 

کد الگوریتم Canny در C :

برنامه زیر یک فایل BMP سیاه و سفید 8 بیت در هر پیکسل را می خواند و نتیجه را در ‘out.bmp’ ذخیره می کند.با `-lm ‘ کامپایل می شود.

 

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
 
#define MAX_BRIGHTNESS 255
 
// C99 doesn't define M_PI (GNU-C99 does)
#define M_PI 3.14159265358979323846264338327
 
/*
 * Loading part taken from
 * http://www.vbforums.com/showthread.php?t=261522
 * BMP info:
 * http://en.wikipedia.org/wiki/BMP_file_format
 *
 * Note: the magic number has been removed from the bmpfile_header_t
 * structure since it causes alignment problems
 * bmpfile_magic_t should be written/read first
 * followed by the
 * bmpfile_header_t
 * [this avoids compiler-specific alignment pragmas etc.]
 */
 
typedef struct {
 uint8_t magic[2];
} bmpfile_magic_t;
 
typedef struct {
 uint32_t filesz;
 uint16_t creator1;
 uint16_t creator2;
 uint32_t bmp_offset;
} bmpfile_header_t;
 
typedef struct {
 uint32_t header_sz;
 int32_t width;
 int32_t height;
 uint16_t nplanes;
 uint16_t bitspp;
 uint32_t compress_type;
 uint32_t bmp_bytesz;
 int32_t hres;
 int32_t vres;
 uint32_t ncolors;
 uint32_t nimpcolors;
} bitmap_info_header_t;
 
typedef struct {
 uint8_t r;
 uint8_t g;
 uint8_t b;
 uint8_t nothing;
} rgb_t;
 
// Use short int instead `unsigned char' so that we can
// store negative values.
typedef short int pixel_t;
 
pixel_t *load_bmp(const char *filename,
 bitmap_info_header_t *bitmapInfoHeader)
{
 FILE *filePtr = fopen(filename, "rb");
 if (filePtr == NULL) {
 perror("fopen()");
 return NULL;
 }
 
 bmpfile_magic_t mag;
 if (fread(&mag, sizeof(bmpfile_magic_t), 1, filePtr) != 1) {
 fclose(filePtr);
 return NULL;
 }
 
 // verify that this is a bmp file by check bitmap id
 // warning: dereferencing type-punned pointer will break
 // strict-aliasing rules [-Wstrict-aliasing]
 if (*((uint16_t*)mag.magic) != 0x4D42) {
 fprintf(stderr, "Not a BMP file: magic=%c%c\n",
 mag.magic[0], mag.magic[1]);
 fclose(filePtr);
 return NULL;
 }
 
 bmpfile_header_t bitmapFileHeader; // our bitmap file header
 // read the bitmap file header
 if (fread(&bitmapFileHeader, sizeof(bmpfile_header_t),
 1, filePtr) != 1) {
 fclose(filePtr);
 return NULL;
 }
 
 // read the bitmap info header
 if (fread(bitmapInfoHeader, sizeof(bitmap_info_header_t),
 1, filePtr) != 1) {
 fclose(filePtr);
 return NULL;
 }
 
 if (bitmapInfoHeader->compress_type != 0)
 fprintf(stderr, "Warning, compression is not supported.\n");
 
 // move file point to the beginning of bitmap data
 if (fseek(filePtr, bitmapFileHeader.bmp_offset, SEEK_SET)) {
 fclose(filePtr);
 return NULL;
 }
 
 // allocate enough memory for the bitmap image data
 pixel_t *bitmapImage = malloc(bitmapInfoHeader->bmp_bytesz *
 sizeof(pixel_t));
 
 // verify memory allocation
 if (bitmapImage == NULL) {
 fclose(filePtr);
 return NULL;
 }
 
 // read in the bitmap image data
 size_t pad, count=0;
 unsigned char c;
 pad = 4*ceil(bitmapInfoHeader->bitspp*bitmapInfoHeader->width/32.) - bitmapInfoHeader->width;
 for(size_t i=0; i<bitmapInfoHeader->height; i++){
 for(size_t j=0; j<bitmapInfoHeader->width; j++){
 if (fread(&c, sizeof(unsigned char), 1, filePtr) != 1) {
 fclose(filePtr);
 return NULL;
 }
 bitmapImage[count++] = (pixel_t) c;
 }
 fseek(filePtr, pad, SEEK_CUR);
 }
 
 // If we were using unsigned char as pixel_t, then:
 // fread(bitmapImage, 1, bitmapInfoHeader->bmp_bytesz, filePtr);
 
 // close file and return bitmap image data
 fclose(filePtr);
 return bitmapImage;
}
 
// Return: true on error.
bool save_bmp(const char *filename, const bitmap_info_header_t *bmp_ih,
 const pixel_t *data)
{
 FILE* filePtr = fopen(filename, "wb");
 if (filePtr == NULL)
 return true;
 
 bmpfile_magic_t mag = {{0x42, 0x4d}};
 if (fwrite(&mag, sizeof(bmpfile_magic_t), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 
 const uint32_t offset = sizeof(bmpfile_magic_t) +
 sizeof(bmpfile_header_t) +
 sizeof(bitmap_info_header_t) +
 ((1U << bmp_ih->bitspp) * 4);
 
 const bmpfile_header_t bmp_fh = {
 .filesz = offset + bmp_ih->bmp_bytesz,
 .creator1 = 0,
 .creator2 = 0,
 .bmp_offset = offset
 };
 
 if (fwrite(&bmp_fh, sizeof(bmpfile_header_t), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 if (fwrite(bmp_ih, sizeof(bitmap_info_header_t), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 
 // Palette
 for (size_t i = 0; i < (1U << bmp_ih->bitspp); i++) {
 const rgb_t color = {(uint8_t)i, (uint8_t)i, (uint8_t)i};
 if (fwrite(&color, sizeof(rgb_t), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 }
 
 // We use int instead of uchar, so we can't write img
 // in 1 call any more.
 // fwrite(data, 1, bmp_ih->bmp_bytesz, filePtr);
 
 // Padding: http://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage
 size_t pad = 4*ceil(bmp_ih->bitspp*bmp_ih->width/32.) - bmp_ih->width;
 unsigned char c;
 for(size_t i=0; i < bmp_ih->height; i++) {
 for(size_t j=0; j < bmp_ih->width; j++) {
 c = (unsigned char) data[j + bmp_ih->width*i];
 if (fwrite(&c, sizeof(char), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 }
 c = 0;
 for(size_t j=0; j<pad; j++)
 if (fwrite(&c, sizeof(char), 1, filePtr) != 1) {
 fclose(filePtr);
 return true;
 }
 }
 
 fclose(filePtr);
 return false;
}
 
// if normalize is true, map pixels to range 0..MAX_BRIGHTNESS
void convolution(const pixel_t *in, pixel_t *out, const float *kernel,
 const int nx, const int ny, const int kn,
 const bool normalize)
{
 assert(kn % 2 == 1);
 assert(nx > kn && ny > kn);
 const int khalf = kn / 2;
 float min = FLT_MAX, max = -FLT_MAX;
 
 if (normalize)
 for (int m = khalf; m < nx - khalf; m++)
 for (int n = khalf; n < ny - khalf; n++) {
 float pixel = 0.0;
 size_t c = 0;
 for (int j = -khalf; j <= khalf; j++)
 for (int i = -khalf; i <= khalf; i++) {
 pixel += in[(n - j) * nx + m - i] * kernel;
 c++;
 }
 if (pixel < min)
 min = pixel;
 if (pixel > max)
 max = pixel;
 }
 
 for (int m = khalf; m < nx - khalf; m++)
 for (int n = khalf; n < ny - khalf; n++) {
 float pixel = 0.0;
 size_t c = 0;
 for (int j = -khalf; j <= khalf; j++)
 for (int i = -khalf; i <= khalf; i++) {
 pixel += in[(n - j) * nx + m - i] * kernel;
 c++;
 }
 
 if (normalize)
 pixel = MAX_BRIGHTNESS * (pixel - min) / (max - min);
 out[n * nx + m] = (pixel_t)pixel;
 }
}
 
/*
 * gaussianFilter:
 * http://www.songho.ca/dsp/cannyedge/cannyedge.html
 * determine size of kernel (odd #)
 * 0.0 <= sigma < 0.5 : 3
 * 0.5 <= sigma < 1.0 : 5
 * 1.0 <= sigma < 1.5 : 7
 * 1.5 <= sigma < 2.0 : 9
 * 2.0 <= sigma < 2.5 : 11
 * 2.5 <= sigma < 3.0 : 13 ...
 * kernelSize = 2 * int(2*sigma) + 3;
 */
void gaussian_filter(const pixel_t *in, pixel_t *out,
 const int nx, const int ny, const float sigma)
{
 const int n = 2 * (int)(2 * sigma) + 3;
 const float mean = (float)floor(n / 2.0);
 float kernel[n * n]; // variable length array
 
 fprintf(stderr, "gaussian_filter: kernel size %d, sigma=%g\n",
 n, sigma);
 size_t c = 0;
 for (int i = 0; i < n; i++)
 for (int j = 0; j < n; j++) {
 kernel = exp(-0.5 * (pow((i - mean) / sigma, 2.0) +
 pow((j - mean) / sigma, 2.0)))
 / (2 * M_PI * sigma * sigma);
 c++;
 }
 
 convolution(in, out, kernel, nx, ny, n, true);
}
 
/*
 * Links:
 * http://en.wikipedia.org/wiki/Canny_edge_detector
 * http://www.tomgibara.com/computer-vision/CannyEdgeDetector.java
 * http://fourier.eng.hmc.edu/e161/lectures/canny/node1.html
 * http://www.songho.ca/dsp/cannyedge/cannyedge.html
 *
 * Note: T1 and T2 are lower and upper thresholds.
 */
pixel_t *canny_edge_detection(const pixel_t *in,
 const bitmap_info_header_t *bmp_ih,
 const int tmin, const int tmax,
 const float sigma)
{
 const int nx = bmp_ih->width;
 const int ny = bmp_ih->height;
 
 pixel_t *G = calloc(nx * ny * sizeof(pixel_t), 1);
 pixel_t *after_Gx = calloc(nx * ny * sizeof(pixel_t), 1);
 pixel_t *after_Gy = calloc(nx * ny * sizeof(pixel_t), 1);
 pixel_t *nms = calloc(nx * ny * sizeof(pixel_t), 1);
 pixel_t *out = malloc(bmp_ih->bmp_bytesz * sizeof(pixel_t));
 
 if (G == NULL || after_Gx == NULL || after_Gy == NULL ||
 nms == NULL || out == NULL) {
 fprintf(stderr, "canny_edge_detection:"
 " Failed memory allocation(s).\n");
 exit(1);
 }
 
 gaussian_filter(in, out, nx, ny, sigma);
 
 const float Gx[] = {-1, 0, 1,
 -2, 0, 2,
 -1, 0, 1};
 
 convolution(out, after_Gx, Gx, nx, ny, 3, false);
 
 const float Gy[] = { 1, 2, 1,
 0, 0, 0,
 -1,-2,-1};
 
 convolution(out, after_Gy, Gy, nx, ny, 3, false);
 
 for (int i = 1; i < nx - 1; i++)
 for (int j = 1; j < ny - 1; j++) {
 const int c = i + nx * j;
 // G = abs(after_Gx) + abs(after_Gy);
 G = (pixel_t)hypot(after_Gx, after_Gy);
 }
 
 // Non-maximum suppression, straightforward implementation.
 for (int i = 1; i < nx - 1; i++)
 for (int j = 1; j < ny - 1; j++) {
 const int c = i + nx * j;
 const int nn = c - nx;
 const int ss = c + nx;
 const int ww = c + 1;
 const int ee = c - 1;
 const int nw = nn + 1;
 const int ne = nn - 1;
 const int sw = ss + 1;
 const int se = ss - 1;
 
 const float dir = (float)(fmod(atan2(after_Gy,
 after_Gx) + M_PI,
 M_PI) / M_PI) * 8;
 
 if (((dir <= 1 || dir > 7) && G > G[ee] &&
 G > G[ww]) || // 0 deg
 ((dir > 1 && dir <= 3) && G > G[nw] &&
 G > G[se]) || // 45 deg
 ((dir > 3 && dir <= 5) && G > G[nn] &&
 G > G[ss]) || // 90 deg
 ((dir > 5 && dir <= 7) && G > G[ne] &&
 G > G[sw])) // 135 deg
 nms = G;
 else
 nms = 0;
 }
 
 // Reuse array
 // used as a stack. nx*ny/2 elements should be enough.
 int *edges = (int*) after_Gy;
 memset(out, 0, sizeof(pixel_t) * nx * ny);
 memset(edges, 0, sizeof(pixel_t) * nx * ny);
 
 // Tracing edges with hysteresis . Non-recursive implementation.
 size_t c = 1;
 for (int j = 1; j < ny - 1; j++)
 for (int i = 1; i < nx - 1; i++) {
 if (nms >= tmax && out == 0) { // trace edges
 out = MAX_BRIGHTNESS;
 int nedges = 1;
 edges[0] = c;
 
 do {
 nedges--;
 const int t = edges[nedges];
 
 int nbs[8]; // neighbours
 nbs[0] = t - nx; // nn
 nbs[1] = t + nx; // ss
 nbs[2] = t + 1; // ww
 nbs[3] = t - 1; // ee
 nbs[4] = nbs[0] + 1; // nw
 nbs[5] = nbs[0] - 1; // ne
 nbs[6] = nbs[1] + 1; // sw
 nbs[7] = nbs[1] - 1; // se
 
 for (int k = 0; k < 8; k++)
 if (nms[nbs[k]] >= tmin && out[nbs[k]] == 0) {
 out[nbs[k]] = MAX_BRIGHTNESS;
 edges[nedges] = nbs[k];
 nedges++;
 }
 } while (nedges > 0);
 }
 c++;
 }
 
 free(after_Gx);
 free(after_Gy);
 free(G);
 free(nms);
 
 return out;
}
 
int main(const int argc, const char ** const argv)
{
 if (argc < 2) {
 printf("Usage: %s image.bmp\n", argv[0]);
 return 1;
 }
 
 static bitmap_info_header_t ih;
 const pixel_t *in_bitmap_data = load_bmp(argv[1], &ih);
 if (in_bitmap_data == NULL) {
 fprintf(stderr, "main: BMP image not loaded.\n");
 return 1;
 }
 
 printf("Info: %d x %d x %d\n", ih.width, ih.height, ih.bitspp);
 
 const pixel_t *out_bitmap_data =
 canny_edge_detection(in_bitmap_data, &ih, 45, 50, 1.0f);
 if (out_bitmap_data == NULL) {
 fprintf(stderr, "main: failed canny_edge_detection.\n");
 return 1;
 }
 
 if (save_bmp("out.bmp", &ih, out_bitmap_data)) {
 fprintf(stderr, "main: BMP image not saved.\n");
 return 1;
 }
 
 free((pixel_t*)in_bitmap_data);
 free((pixel_t*)out_bitmap_data);
 return 0;
}

 

دانلود کد فوق از طریق لینک زیر:

Canny in C

رمز فایل : behsanandish.com

الگوریتم Canny

لبه یاب کنی توسط جان اف کنی در سال 1986 ایجاد شد و هنوز یک لبه یاب استاندارد و با دقت و کیفیت بالا میباشد.الگوریتم لبه یابی کنی یکی از بهترین لبه یابها تا به امروز است. در ادامه روش کار این الگوریتم و هم چنین کد الگوریتم Canny در Visual Basic را بررسی خواهیم کرد. این الگوریتم لبه یابی از سه بخش اصلی زیر تشکیل شده:

  • تضعیف نویز
  • پیدا کردن نقاطی که بتوان آنها را به عنوان لبه در نظر گرفت
  • حذب نقاطی که احتمال لبه بودن آنها کم است

 

معیارهایی که در لبه یا کنی مطرح است:
1 -پایین آوردن نرخ خطا- یعنی تا حد امکان هیچ لبه ای در تصویر نباید گم شود و هم چنین هیچ چیزی که لبه نیست نباید به جای لبه فرض شود. لبه هان پیدا شده تا حد ممکن به لبه ها اصلی
نزدیک باشند.

2 -لبه در مکان واقعی خود باشد- یعنی تا حد ممکن لبه ها کمترین فاصله را با مکان واقعی خود داشته باشند.
3 -بران هر لبه فقط یک پاسخ داشته باشیم.

4 -لبه ها کمترین ضخامت را داشته باشند- (در صورت امکان یک پیکسل).
لبه یاب کنی بخاطر توانایی در تولید لبه های نازک تا حد یک ییکسل برای لبه های پیوسته معروف شده است. این لبه یاب شامل چهار مرحله و چهار ورودی زیر است:
یک تصویر ورودی
یک پارامتر به نام سیگما جهت مقدار نرم کنندگی تصویر
یک حد آستانه بالا (Th)
یک حد آستانه پایین (Tl)

 

مراحل الگوریتم Canny:

1- در ابتدا باید تصویر رنگی را به جهت لبه یابی بهتر به یک تصویر سطح خاکسترن تبدیب کرد.

2- نویز را از تصویر دریافتی حذف کرد. بدلیل اینکه فیلتر گاوسین از یک ماسک ساده برای حذف نویز استفاده می کند لبه یاب کنی در مرحله اول برای حذف نویز آن را بکار میگیرد.

3- در یک تصویر سطح خاکستر جایی را که بیشترین تغییرات را داشته باشند به عنوان لبه در نظر گرفته می شوند و این مکانها با گرفتن گرادیان تصویر با استفاده عملگر سوبل بدست می آیند. سپس لبه های مات یافت شده به لبه های تیزتر تبدیل می شوند.

4- برخی از لبه های کشف شده واقعا لبه نیستند و در واقع نویز هستند که باید آنها توسط حد آستانه هیسترزیس فیلتر شوند.هیسترزیس از دو حد آستانه بالاتر (Th) و حد آستانه پایین تر (Tl) استفاده کرده و کنی پیشنهاد می کند که نسبت استانه بالا به پایین سه به یک باشد.

 این روش بیشتر به کشف لبه های ضعیف به درستی می پردازد و کمتر فریب نویز را می خورد و از بقیه روش ها بهتر است.

 

الگوریتم Canny    عملکرد الگوریتم Canny

 

الگوریتم Canny در Visual Basic:

کد زیر یک کد تکمیل نشده است.تکمیل آن به عنوان تمرین به خواننده واگذار می شود.

 

Imports System.Drawing
Imports System.Drawing.Imaging

Public Class clsEdges

    Public Sub EdgeDetectDifference(ByVal b As Bitmap, ByVal threshold As Byte)
        ' first we create a clone o the image we want to find the edges on
        Dim b2 As Bitmap = b.Clone
        ' we create bitmapdata of the images at the same time locking them
        Dim bmData1 As BitmapData = b.LockBits(New Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim bmData2 As BitmapData = b2.LockBits(New Rectangle(0, 0, b2.Width, b2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        ' the stride describes the distance between image bytes
        Dim stride As Integer = bmData2.Stride
        ' scan0 is some sort of OS handle or something to identify the actual data in the memory
        Dim scan01 As IntPtr = bmData1.Scan0
        Dim scan02 As IntPtr = bmData2.Scan0
        ' we need to know how big the data is so that we can create the correct size for the file
        Dim bytes As Integer = b.Height * b.Width * 3
        ' we create the byte arrays so that we can edit them
        Dim p01(bytes - 1) As Byte
        Dim p02(bytes - 1) As Byte
        ' put the images into the byte arrays
        System.Runtime.InteropServices.Marshal.Copy(scan01, p01, 0, bytes)
        System.Runtime.InteropServices.Marshal.Copy(scan02, p02, 0, bytes)

        ' the nWidth describes the width of the actual image multiplied by three for each byte in the pixel (3 bytes per pixel 24 bits ;))
        Dim nWidth As Integer = b2.Width * 3
        ' for some reason although the original code show a formula to come up with the offset this doesn't work very well.
        ' I found that it is just easier to make the offset 0 and so all bits are handled. Basically the problem comes when 
        ' using this on files that don't have
        Dim nOffset As Integer = 0
        Dim nPixel As Integer = 0, npixelmax As Integer = 0
        Dim pos1 As Integer = stride + 3
        Dim pos2 As Integer = stride + 3
        Dim p2minusplus As Integer, p2plusminus As Integer, p2plusplus As Integer, p2minusminus As Integer
        Dim p2minusstride As Integer, p2plusstride As Integer
        Dim p2plus As Integer, p2minus As Integer

        For y As Integer = 1 To b.Height - 1
            For x As Integer = 1 To nWidth - 3

                p2minusplus = pos2 - stride + 3
                p2plusminus = pos2 + stride - 3
                p2plusplus = pos2 + stride + 3
                p2minusminus = pos2 - stride - 3
                p2minusstride = pos2 - stride
                p2plusstride = pos2 + stride
                p2minus = pos2 - 3
                p2plus = pos2 + 3
                If p2minusplus <= p02.Length - 1 And p2minusplus >= 0 And p2plusminus <= p02.Length - 1 And p2plusminus >= 0 And _
                p2plusplus <= p02.Length - 1 And p2plusplus >= 0 And p2minusminus <= p02.Length - 1 And p2minusminus >= 0 And _
                p2minusstride <= p02.Length - 1 And p2minusstride >= 0 And p2plusstride <= p02.Length - 1 And p2plusstride >= 0 And _
                p2plus <= p02.Length - 1 And p2plus >= 0 And p2minus <= p02.Length - 1 And p2minus >= 0 And pos1 < p01.Length Then
                    npixelmax = Math.Abs(CInt(p02(p2minusplus)) - CInt(p02(p2plusminus)))
                    nPixel = Math.Abs(CInt(p02(p2plusplus)) - CInt(p02(p2minusminus)))
                    If nPixel > npixelmax Then npixelmax = nPixel
                    nPixel = Math.Abs(CInt(p02(p2minusstride)) - CInt(p02(p2plusstride)))
                    If nPixel > npixelmax Then npixelmax = nPixel
                    nPixel = Math.Abs(CInt(p02(p2plus)) - CInt(p02(p2minus)))
                    If nPixel > npixelmax Then npixelmax = nPixel
                    If npixelmax < CInt(threshold) Then npixelmax = 0
                    p01(pos1) = CByte(npixelmax)
                End If
                pos1 += 1
                pos2 += 1

            Next
            pos1 += nOffset
            pos2 += nOffset
        Next

        System.Runtime.InteropServices.Marshal.Copy(p01, 0, scan01, bytes)

        b.UnlockBits(bmData1)
        b2.UnlockBits(bmData2)

    End Sub
    Public Sub EdgeDetectHomogenity(ByVal b As Bitmap, ByVal threshold As Byte)
        Dim b2 As Bitmap = b.Clone
        Dim bmData1 As BitmapData = b.LockBits(New Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim bmData2 As BitmapData = b2.LockBits(New Rectangle(0, 0, b2.Width, b2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim stride As Integer = bmData2.Stride
        Dim scan01 As IntPtr = bmData1.Scan0
        Dim scan02 As IntPtr = bmData2.Scan0
        Dim bytes As Integer = b.Height * b.Width * 3
        Dim p01(bytes - 1) As Byte
        Dim p02(bytes - 1) As Byte

        System.Runtime.InteropServices.Marshal.Copy(scan01, p01, 0, bytes)
        System.Runtime.InteropServices.Marshal.Copy(scan02, p02, 0, bytes)
        Dim nWidth As Integer = b2.Width * 3
        Dim nOffset As Integer = 0
        Dim nPixel As Integer = 0, npixelmax As Integer = 0
        Dim pos1 As Integer = stride + 3
        Dim pos2 As Integer = stride + 3

        Dim p2plusminus As Integer, p2plusstride As Integer, p2plusplus As Integer, p2minusstride As Integer, _
        p2minusminus As Integer, p2minusplus As Integer

        For y As Integer = 1 To b.Height - 1
            For x As Integer = 1 To nWidth - 3

                p2plusminus = pos2 + stride - 3
                p2plusstride = pos2 + stride
                p2plusplus = pos2 + stride + 3
                p2minusstride = pos2 - stride
                p2minusminus = pos2 - stride - 3
                p2minusplus = pos2 - stride + 3

                If p2plusminus < p02.Length And p2plusminus >= 0 And p2plusstride < p02.Length And p2plusstride >= 0 And _
                p2plusplus < p02.Length And p2plusplus >= 0 And p2minusstride < p02.Length And p2minusstride >= 0 And _
                p2minusstride < p02.Length And p2minusstride >= 0 And p2minusminus < p02.Length And p2minusminus >= 0 And _
                p2minusplus < p02.Length And p2minusplus >= 0 Then

                    npixelmax = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2plusminus)))
                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2plusstride)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2plusplus)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2minusstride)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2plusstride)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2minusminus)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2minusstride)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2)) - CInt(p02(p2minusplus)))
                    If nPixel > npixelmax Then npixelmax = nPixel


                    If npixelmax < threshold Then npixelmax = 0

                    p01(pos1) = CByte(npixelmax)

                End If

                pos1 += 1
                pos2 += 1
            Next
            pos1 += nOffset
            pos2 += nOffset
        Next

        System.Runtime.InteropServices.Marshal.Copy(p01, 0, scan01, bytes)

        b.UnlockBits(bmData1)
        b2.UnlockBits(bmData2)

    End Sub


    Public Function EdgeEnhance(ByVal b As Bitmap, ByVal threshold As Byte) As Boolean
        Dim b2 As Bitmap = b.Clone
        Dim bmData1 As BitmapData = b.LockBits(New Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim bmData2 As BitmapData = b2.LockBits(New Rectangle(0, 0, b2.Width, b2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim stride As Integer = bmData2.Stride
        Dim scan01 As IntPtr = bmData1.Scan0
        Dim scan02 As IntPtr = bmData2.Scan0
        Dim bytes As Integer = b.Height * b.Width * 3
        Dim p01(bytes - 1) As Byte
        Dim p02(bytes - 1) As Byte

        System.Runtime.InteropServices.Marshal.Copy(scan01, p01, 0, bytes)
        System.Runtime.InteropServices.Marshal.Copy(scan02, p02, 0, bytes)
        Dim nWidth As Integer = b2.Width * 3
        Dim nOffset As Integer = 0
        Dim nPixel As Integer = 0, npixelmax As Integer = 0
        Dim pos1 As Integer = stride + 3
        Dim pos2 As Integer = stride + 3
        Dim p2minusplus As Integer, p2plusminus As Integer, p2plusplus As Integer, p2minusminus As Integer
        Dim p2minusstride As Integer, p2plusstride As Integer
        Dim p2plus As Integer, p2minus As Integer

        For y As Integer = 1 To b.Height - 1
            For x As Integer = 1 To nWidth - 3

                p2minusplus = pos2 - stride + 3
                p2plusminus = pos2 + stride - 3
                p2plusplus = pos2 + stride + 3
                p2minusminus = pos2 - stride - 3
                p2minusstride = pos2 - stride
                p2plusstride = pos2 + stride
                p2minus = pos2 - 3
                p2plus = pos2 + 3
                If p2minusplus <= p02.Length - 1 And p2minusplus >= 0 And p2plusminus <= p02.Length - 1 And p2plusminus >= 0 And _
                p2plusplus <= p02.Length - 1 And p2plusplus >= 0 And p2minusminus <= p02.Length - 1 And p2minusminus >= 0 And _
                p2minusstride <= p02.Length - 1 And p2minusstride >= 0 And p2plusstride <= p02.Length - 1 And p2plusstride >= 0 And _
                p2plus <= p02.Length - 1 And p2plus >= 0 And p2minus <= p02.Length - 1 And p2minus >= 0 And pos1 < p01.Length Then
                    npixelmax = Math.Abs(CInt(p02(pos2 - stride + 3)) - CInt(p02(pos2 + stride - 3)))
                    nPixel = Math.Abs(CInt(p02(pos2 + stride + 3)) - CInt(p02(pos2 - stride - 3)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2 - stride)) - CInt(p02(pos2 + stride)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    nPixel = Math.Abs(CInt(p02(pos2 + 3)) - CInt(p02(pos2 - 3)))
                    If nPixel > npixelmax Then npixelmax = nPixel

                    If npixelmax > threshold And npixelmax > p01(pos1) Then
                        p01(pos1) = CByte(Math.Max(CInt(p01(pos1)), npixelmax))
                    End If

                End If

                pos1 += 1
                pos2 += 1
            Next
            pos1 += nOffset
            pos2 += nOffset
        Next

        System.Runtime.InteropServices.Marshal.Copy(p01, 0, scan01, bytes)

        b.UnlockBits(bmData1)
        b2.UnlockBits(bmData2)

        Return True
    End Function

End Class

 

 

این کد کامل نیست!

دانلود کد فوق از طریق لینک زیر:

CannyInVisualBasic

رمز فایل : behsanandish.com

 

مقدمه

الگوریتم های لبه یابی- انسان مي تواند بسیاري از اشیاء را از روي تصویر خطوط آنها شناسایي كند. بهترین مثال برای آن تصاویر کارتنی است. سیستم بینایي انسان قبل از بازشناسي رنگ یا شدت روشنایي نوعی كشف لبه انجام مي دهد. بنابراین انجام كشف لبه قبل از تفسیر تصاویر در سیستمهاي خودكار منطقي به نظر مي رسد. انجام عملیات كشف لبه پردازش مهمي در بسیاري از سیستمهاي بینایي مصنوعي محسوب مي شود. هدف اصلی لبه یابی کاهش حجم داده ها در تصویر به همراه حفظ ساختار و شکل اصلی تصویر است. مرزماند سایه یک واقعیت فیزیکی نیست و عبارت است از جایی که بخشی از تصویر شروع یا تمام میشود. لبه را میتوان به عنوان جایی که صفحات افقی و عمودی جسم به هم میرسند در نظر گرفت.

یکی از متداولترین اعمال در تحلیل تصویر تشخیص لبه می باشد به این دلیل که لبه مرز میان یک شی و زمینهء آن است به عبارت دیگر لبه تغییر دو سطح خاکستري یا مقادیر مربوط به روشنایی دو پیکسل مجاور است که در مکان خاصی از تصویر رخ می دهد.هر چه این تغییر در سطح بیشتر باشد تشخیص لبه ساده تر خواهد بود.

نقاطي از تصویر كه داراي تغییرات روشنایي ناگھاني ھستند اغلب لبه یا نقاط لبه نامیده مي شوند. نقاط لبه معمولا ً شامل مرزھاي اشیاء و دیگر انواع تغییرات روشنایي و ھمچنین لبه ھاي نویزي مي باشند.

انواع لبه:

انواع لبه در لبه یابی

انواع الگوریتم های لبه یابی

1- الگوریتم soble

این متد لبه ها را با استفاده از تخمین زدن مشتق پیدا می کند، که لبه ها را در آن نقاطی بر می گرداند که گرادیان تصویر I ، max است. در فیلتر سوبل دو ماسک به صورت زیر وجود دارد:

ماسک سوبل عمودی         ماسک سوبل افقی

ماسک سوبل افقی بیشتر لبه هاي افقی را مشخص میکند و ماسک سوبل عمودي،لبه هاي عمودي را مشخص میکند.

براي مشخص شدن کلیه لبه ها:
اگر Gو Gy تصاویر فیلتر شده به وسیله ماسک افقی و عمودي باشند، آنگاه تصویر  فرمول الگوریتم سوبل    لبه هاي تصویر را بهتر نشان میدهد. روال فوق به عملگر یا الگورریتم سوبل موسوم است.
در عمل، به منظور کاهش هزینه محاسبات، به جاي  فرمول الگوریتم سوبل  میتوان از تقریب [Gx] + [Gy] استفاده میشود. توجه شود که نتیجه این دو فرمول تقریبا یکسان است ولی فرمول دوم با هزینه کمتري قابل محاسبه است.

تأثیر عملگر سوبل بر لبه یابی تصاویر

 

کد الگوریتم Sobel در Matlab:

clc; clear; close all; warning off; 
I=imread('lena.bmp');
I=im2double(I);
I=imnoise(I, 'gaussian', 0, 0.001);
figure(1);
imshow(I);title('org img');
[height width R]=size(I);
for i=2:height-1
    for j=2:width-1
        Dx(i,j)=[I(i+1,j-1)-I(i-1,j-1)]+2*[I(i+1,j)-I(i-1,j)]+[I(i+1,j+1)-I(i-1,j+1)];
        Dy(i,j)=[I(i-1,j+1)-I(i-1,j-1)]+2*[I(i,j+1)-I(i,j-1)]+[I(i+1,j+1)-I(i+1,j-1)];
        S(i,j)=sqrt(Dx(i,j)^2+Dy(i,j)^2);
        if Dx(i,j)&lt;1
            Dx(i,j)=0;
        else Dx(i,j)=1;
        end
        if Dy(i,j)&lt;1
            Dy(i,j)=0;
        else Dy(i,j)=1;
        end
    end
end
figure(2);
imshow(Dx,[]);
figure(3);
imshow(Dy,[]);
for i=1:255
    for j=1:255
       if (S(i,j)&lt;1)
            S(i,j)=0;
        else S(i,j)=1;
        end
    end
end
دانلود کد فوق از طریق لینک زیر:

الگوریتم سوبل به زبان متلب

رمز فایل : behsanandish.com

 


2- الگوریتم Canny

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

  • تضعیف نویز
  • پیدا کردن نقاطی که بتوان آنها را به عنوان لبه در نظر گرفت
  • حذب نقاطی که احتمال لبه بودن آنها کم است

 

معیارهایی که در لبه یا کنی مطرح است:
1 -پایین آوردن نرخ خطا- یعنی تا حد امکان هیچ لبه ای در تصویر نباید گم شود و هم چنین هیچ چیزی که لبه نیست نباید به جای لبه فرض شود. لبه هان پیدا شده تا حد ممکن به لبه ها اصلی
نزدیک باشند.

2 -لبه در مکان واقعی خود باشد- یعنی تا حد ممکن لبه ها کمترین فاصله را با مکان واقعی خود داشته باشند.
3 -بران هر لبه فقط یک پاسخ داشته باشیم.

4 -لبه ها کمترین ضخامت را داشته باشند- (در صورت امکان یک پیکسل).
لبه یاب کنی بخاطر توانایی در تولید لبه های نازک تا حد یک ییکسل برای لبه های پیوسته معروف شده است. این لبه یاب شامل چهار مرحله و چهار ورودی زیر است:
یک تصویر ورودی
یک پارامتر به نام سیگما جهت مقدار نرم کنندگی تصویر
یک حد آستانه بالا (Th)
یک حد آستانه پایین (Tl)

 

و مراحل شامل

1- در ابتدا باید تصویر رنگی را به جهت لبه یابی بهتر به یک تصویر سطح خاکسترن تبدیب کرد.

2- نویز را از تصویر دریافتی حذف کرد. بدلیل اینکه فیلتر گاوسین از یک ماسک ساده برای حذف نویز استفاده می کند لبه یاب کنی در مرحله اول برای حذف نویز آن را بکار میگیرد.

3- در یک تصویر سطح خاکستر جایی را که بیشترین تغییرات را داشته باشند به عنوان لبه در نظر گرفته می شوند و این مکانها با گرفتن گرادیان تصویر با استفاده عملگر سوبل بدست می آیند. سپس لبه های مات یافت شده به لبه های تیزتر تبدیل می شوند.

4- برخی از لبه های کشف شده واقعا لبه نیستند و در واقع نویز هستند که باید آنها توسط حد آستانه هیسترزیس فیلتر شوند.هیسترزیس از دو حد آستانه بالاتر (Th) و حد آستانه پایین تر (Tl) استفاده کرده و کنی پیشنهاد می کند که نسبت استانه بالا به پایین سه به یک باشد.

 این روش بیشتر به کشف لبه های ضعیف به درستی می پردازد و کمتر فریب نویز را می خورد و از بقیه روش ها بهتر است.

 

الگوریتم Canny    عملکرد الگوریتم Canny

 

clear; clc; close all; warning off;
I=imread('siahosefid.bmp');
I=imnoise(I, 'gaussian', 0, 0.001);
figure(1)
imshow(I);
A=filter2(fspecial('average',3),I)/255; 
figure(2)
imshow(A);
gauss_I=I;
Isize=size(I);
ans=zeros(size(I));
dir=zeros(size(I));
I=double(I);
gauss_I=double(gauss_I);
fx=0;
fy=0;
for i=2:Isize(1)-1
    for j=2:Isize(2)-1
        fx=gauss_I(i,j)+gauss_I(i,j+1)-gauss_I(i+1,j)-gauss_I(i+1,j+1);
        fy=gauss_I(i,j)+gauss_I(i+1,j)-gauss_I(i,j+1)-gauss_I(i+1,j+1);
        ans(i,j)=sqrt(fx*fx+fy*fy);
        dir(i,j)=atan(fy/fx);
    end
end
figure(3)
imshow(ans)
for i=2:Isize(1)-1
    for j=2:Isize(2)-1
        if dir(i,j)&gt;=-pi/8 &amp; dir(i,j)&lt;pi/8&lt;/pre&gt;
&lt;pre&gt;           if ans(i,j)&lt;=ans(i,j-1) | ans(i,j)&lt;=ans(i,j+1)
                ans(i,j)=0;
            end
        end
        if dir(i,j)&gt;=pi/8 &amp; dir(i,j)&lt;3*pi/8
            if ans(i,j)&lt;=ans(i-1,j+1) | ans(i,j)&lt;=ans(i+1,j-1)
                ans(i,j)=0;
            end
        end
        if dir(i,j)&gt;=3*pi/8 | dir(i,j)&lt;-3*pi/8
            if ans(i,j)&lt;=ans(i-1,j) | ans(i,j)&lt;=ans(i+1,j)
                ans(i,j)=0;
            end
        end
        if dir(i,j)&lt;-pi/8 &amp; dir(i,j)&gt;=3*pi/8
            if ans(i,j)&lt;=ans(i-1,j-1) | ans(i,j)&lt;=ans(i+1,j+1)
                ans(i,j)=0;
            end
        end
        if ans(i,j)&lt;40
            ans(i,j)=0;
        else
            ans(i,j)=255;
        end
    end
end
figure(4)
imshow(ans)

 

دانلود کد فوق از طریق لینک زیر:

رمز فایل : behsanandish.com

 


 3- الگوریتم Roberts

این الگوریتم به نویز حساسیت زیادی دارد وپیکسل های کمتری را برای تقریب گرادیان بکار می برد،درضمن نسبت به الگوریتم canny هم قدرت کمتری دارد.

 

الگوریتم Robertsعملکرد الگوریتم Roberts

 

clc; clear; close all; warning off;
I=imread('siahosefid.bmp');
I=imnoise(I, 'gaussian', 0, 0.001);
I=im2double(I);
figure(1);
imshow(I);
[height width R]=size(I);
for i=2:height-1
    for j=2:width-1
        R(i,j)=abs(I(i+1,j+1)-I(i,j))+abs(I(i+1,j)-I(i,j+1));
        Z(i,j)=abs(I(i+1,j+1)-I(i,j));
        X(i,j)=abs(I(i+1,j)-I(i,j+1));
    end
end
for i=1:height-1
    for j=1:width-1
        if (R(i,j)&lt;0.25)
            R(i,j)=0;
        else R(i,j)=1;
        end
        if (Z(i,j)&lt;0.25)
            Z(i,j)=0;
        else Z(i,j)=1;
        end
        if (X(i,j)&lt;0.25)
            X(i,j)=0;
        else X(i,j)=1;
        end
    end
end
figure(2);
imshow(Z,[]);
figure(3);
imshow(X,[]);
figure(4);
imshow(R,[]);

دانلود کد فوق از طریق لینک زیر:

Robert in Matlab

رمز فایل : behsanandish.com

 


4- الگوریتم Prewitt

این الگوریتم شباهت زیادی با الگوریتم sobel دارد با این تفاوت که ضرایب ماسک آنها با هم فرق می کند.

 

الگوریتم Prewittعملکرد الگوریتم Prewitt

I=imread('siahosefid.bmp');
I=im2double(I);
I=imnoise(I, 'gaussian', 0, 0.001);
figure(1);
imshow(I,[]); 
[height width R]=size(I);
for i=2:height-1
    for j=2:width-1
        Dx(i,j)=[I(i+1,j-1)-I(i-1,j-1)]+[I(i+1,j)-I(i-1,j)]+[I(i+1,j+1)-I(i-1,j+1)];
        Dy(i,j)=[I(i-1,j+1)-I(i-1,j-1)]+[I(i,j+1)-I(i,j-1)]+[I(i+1,j+1)-I(i+1,j-1)];
        P(i,j)=sqrt(Dx(i,j)^2+Dy(i,j)^2);
        if Dx(i,j)&lt;0.5
           Dx(i,j)=0;
        else Dx(i,j)=1;
        end
        if Dy(i,j)&lt;0.5
           Dy(i,j)=0;
        else Dy(i,j)=1;
        end
    end
end
figure(2);
imshow(Dx,[]); 
figure(3);
imshow(Dy,[]);
for i=1:height-1
    for j=1:width-1
        if (P(i,j)&lt;0.5)
            P(i,j)=0;
        else P(i,j)=1;
        end
    end
end
figure(4);
imshow(P,[]);

 

دانلود کد فوق از طریق لینک زیر:

Prewitt In Matlab

رمز فایل : behsanandish.com

 


5- الگوریتم Zerocross

این الگوریتم قسمت هایی از لاپلاس یک تصویر را جستجو می کند که مقدار لاپلاس از صفر می گذرد. به عبارت دیگر نقاطی که لاپلاس علامت را تغییر می دهد.

 

الگوریتم Zerocrossعملکرد الگوریتم Zerocross

 

[BW,threshOut] =edge(graypic,'zerocross')
[BW,threshOut] = edge(graypic,'zerocross',sensitive,filter name);
sensitive -> حساسیت
بین 0 و 1 و حساس ترین حالت 0

 

دانلود کد فوق از طریق لینک زیر:

Zerocross In Matlab

رمز فایل : behsanandish.com

 


6- الگوریتم  LOG)Laplacian of gaussian)

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

 

الگوریتم LOGعملکرد الگوریتم LOG-2

 

 

clc; clear; close all; warning off; 
f=imread('siahosefid.bmp');
%f=imnoise(f, 'gaussian', 0, 0.001);
k=double(f);
figure(1)
imshow(f)
[m,n]=size(f);
k=[zeros(m,1) k zeros(m,1)];
k=[zeros(1,n+2);k;zeros(1,n+2)];
T=30; 
for i=2:m+1 
    for j=2:n+1 
        g(i,j)=k(i-1,j)+k(i+1,j)+k(i,j-1)+k(i,j+1)-4*k(i,j);
    end
end
for i=2:m+1  
    for j=2:n+1
        if  g(i,j)&lt;T 
            g(i,j)=0;
        else
            g(i,j)=1;
        end
    end
end    
figure(2)
imshow(g)

 

دانلود کد فوق از طریق لینک زیر:

LOG In Matlab

رمز فایل : behsanandish.com

 

الگوریتم sobel

کد الگوریتم سوبل – متد سوبل لبه ها را با استفاده از تخمین زدن مشتق پیدا می کند، که لبه ها را در آن نقاطی بر می گرداند که گرادیان تصویر I ، max است. پیشنهاد می کنیم جهت آشنایی با الگوریتم های لبه یابی، مطلب «الگوریتم های لبه یابی و انواع آن» را مشاهده نمایید. در فیلتر سوبل دو ماسک به صورت زیر وجود دارد:

ماسک سوبل عمودی         ماسک سوبل افقی

ماسک سوبل افقی بیشتر لبه هاي افقی را مشخص میکند و ماسک سوبل عمودي،لبه هاي عمودي را مشخص میکند.

براي مشخص شدن کلیه لبه ها:
اگر Gو Gy تصاویر فیلتر شده به وسیله ماسک افقی و عمودي باشند، آنگاه تصویر  فرمول الگوریتم سوبل    لبه هاي تصویر را بهتر نشان میدهد. روال فوق به عملگر یا الگورریتم سوبل موسوم است.
در عمل، به منظور کاهش هزینه محاسبات، به جاي  فرمول الگوریتم سوبل  میتوان از تقریب [Gx] + [Gy] استفاده میشود. توجه شود که نتیجه این دو فرمول تقریبا یکسان است ولی فرمول دوم با هزینه کمتري قابل محاسبه می باشد.

تأثیر عملگر سوبل بر لبه یابی تصاویر

 

کد الگوریتم سوبل( Sobel ) در Matlab:

 

clc; clear; close all; warning off; 

I=imread('lena.bmp');
I=im2double(I);
I=imnoise(I, 'gaussian', 0, 0.001);
figure(1);
imshow(I);title('org img');

[height width R]=size(I);

for i=2:height-1
    for j=2:width-1
        Dx(i,j)=[I(i+1,j-1)-I(i-1,j-1)]+2*[I(i+1,j)-I(i-1,j)]+[I(i+1,j+1)-I(i-1,j+1)];
        Dy(i,j)=[I(i-1,j+1)-I(i-1,j-1)]+2*[I(i,j+1)-I(i,j-1)]+[I(i+1,j+1)-I(i+1,j-1)];
        S(i,j)=sqrt(Dx(i,j)^2+Dy(i,j)^2);
        if Dx(i,j)&amp;lt;1
            Dx(i,j)=0;
        else Dx(i,j)=1;
        end
        if Dy(i,j)&amp;lt;1
            Dy(i,j)=0;
        else Dy(i,j)=1;
        end
    end
end
figure(2);
imshow(Dx,[]);

figure(3);
imshow(Dy,[]);

for i=1:255
    for j=1:255
       if (S(i,j)&amp;lt;1)
            S(i,j)=0;
        else S(i,j)=1;
        end
    end
end
figure(4);
imshow(S,[]);
دانلود کد فوق از طریق لینک زیر:

الگوریتم سوبل به زبان متلب

رمز فایل : behsanandish.com


 

کد الگوریتم سوبل( Sobel ) در #C:

1.کد برای فیلتر کانولوشن: بخش اول این تابع برای گرفتن اطلاعات تصویر و ذخیره آن به آرایه اختصاص داده شده است.

 

private static Bitmap ConvolutionFilter(Bitmap sourceImage, 
    double[,] xkernel, 
    double[,] ykernel, double factor = 1, int bias = 0, bool grayscale = false)
{

    //Image dimensions stored in variables for convenience
    int width = sourceImage.Width;
    int height = sourceImage.Height;

     //Lock source image bits into system memory
    BitmapData srcData = sourceImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

     //Get the total number of bytes in your image - 32 bytes per pixel x image width x image height -&amp;gt; for 32bpp images
    int bytes = srcData.Stride * srcData.Height;

     //Create byte arrays to hold pixel information of your image
    byte[] pixelBuffer = new byte[bytes];
    byte[] resultBuffer = new byte[bytes];

     //Get the address of the first pixel data
    IntPtr srcScan0 = srcData.Scan0;

     //Copy image data to one of the byte arrays
    Marshal.Copy(srcScan0, pixelBuffer, 0, bytes);

    //Unlock bits from system memory -&amp;gt; we have all our needed info in the array
    sourceImage.UnlockBits(srcData);

 

2.کد تبدیل سیاه و سفید: از آنجایی که اپراتور Sobel اغلب برای تصاویر سیاه و سفید استفاده می شود، در اینجا یک کد برای تبدیل به سیاه و سفید است که توسط پارامتر boolean شما می توانید انتخاب کنید تبدیل کردن را یا نه.

 

//Convert your image to grayscale if necessary
if (grayscale == true)
{
    float rgb = 0;
    for (int i = 0; i &amp;lt; pixelBuffer.Length; i += 4)
    {
        rgb = pixelBuffer[i] * .21f;
        rgb += pixelBuffer[i + 1] * .71f;
        rgb += pixelBuffer[i + 2] * .071f;
        pixelBuffer[i] = (byte)rgb;
        pixelBuffer[i + 1] = pixelBuffer[i];
        pixelBuffer[i + 2] = pixelBuffer[i];
        pixelBuffer[i + 3] = 255;
    }
}

 

3.کد برای تنظیم متغیرهای مورد استفاده در فرآیند کانولوشن:

 

/Create variable for pixel data for each kernel
double xr = 0.0;
double xg = 0.0;
double xb = 0.0;
double yr = 0.0;
double yg = 0.0;
double yb = 0.0;
double rt = 0.0;
double gt = 0.0;
double bt = 0.0;

//This is how much your center pixel is offset from the border of your kernel
//Sobel is 3x3, so center is 1 pixel from the kernel border
int filterOffset = 1;
int calcOffset = 0;
int byteOffset = 0;

//Start with the pixel that is offset 1 from top and 1 from the left side
//this is so entire kernel is on your image
for (int OffsetY = filterOffset; OffsetY &amp;lt; height - filterOffset; OffsetY++)
{
    for (int OffsetX = filterOffset; OffsetX &amp;lt; width - filterOffset; OffsetX++)
    {
        //reset rgb values to 0
        xr = xg = xb = yr = yg = yb = 0;
        rt = gt = bt = 0.0;

        //position of the kernel center pixel
        byteOffset = OffsetY * srcData.Stride + OffsetX * 4;

 

4. اعمال کانولوشن هسته به پیکسل فعلی:

 

//kernel calculations
for (int filterY = -filterOffset; filterY &amp;lt;= filterOffset; filterY++)
{
for (int filterX = -filterOffset; filterX &amp;lt;= filterOffset; filterX++)
{
calcOffset = byteOffset + filterX * 4 + filterY * srcData.Stride;
xb += (double)(pixelBuffer[calcOffset]) * xkernel[filterY + filterOffset, filterX + filterOffset];
xg += (double)(pixelBuffer[calcOffset + 1]) * xkernel[filterY + filterOffset, filterX + filterOffset];
xr += (double)(pixelBuffer[calcOffset + 2]) * xkernel[filterY + filterOffset, filterX + filterOffset];
yb += (double)(pixelBuffer[calcOffset]) * ykernel[filterY + filterOffset, filterX + filterOffset];
yg += (double)(pixelBuffer[calcOffset + 1]) * ykernel[filterY + filterOffset, filterX + filterOffset];
yr += (double)(pixelBuffer[calcOffset + 2]) * ykernel[filterY + filterOffset, filterX + filterOffset];
}
}

//total rgb values for this pixel
bt = Math.Sqrt((xb * xb) + (yb * yb));
gt = Math.Sqrt((xg * xg) + (yg * yg));
rt = Math.Sqrt((xr * xr) + (yr * yr));

//set limits, bytes can hold values from 0 up to 255;
if (bt &amp;gt; 255) bt = 255;
else if (bt &amp;lt; 0) bt = 0;
if (gt &amp;gt; 255) gt = 255;
else if (gt &amp;lt; 0) gt = 0;
if (rt &amp;gt; 255) rt = 255;
else if (rt &amp;lt; 0) rt = 0;

//set new data in the other byte array for your image data
resultBuffer[byteOffset] = (byte)(bt);
resultBuffer[byteOffset + 1] = (byte)(gt);
resultBuffer[byteOffset + 2] = (byte)(rt);
resultBuffer[byteOffset + 3] = 255;
}
}

 

5. کد خروجی تصویر پردازش شده:

 

//Create new bitmap which will hold the processed data
    Bitmap resultImage = new Bitmap(width, height);

    //Lock bits into system memory
    BitmapData resultData = resultImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

    //Copy from byte array that holds processed data to bitmap
    Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);

    //Unlock bits from system memory
    resultImage.UnlockBits(resultData);

    //Return processed image
    return resultImage;
}

 

6. کد برای هسته سوبل:

 

//Sobel operator kernel for horizontal pixel changes
private static double[,] xSobel
{
    get
    {
        return new double[,]
        {
            { -1, 0, 1 },
            { -2, 0, 2 },
            { -1, 0, 1 }
        };
    }
}

//Sobel operator kernel for vertical pixel changes
private static double[,] ySobel
{
    get
    {
        return new double[,]
        {
            {  1,  2,  1 },
            {  0,  0,  0 },
            { -1, -2, -1 }
        };
    }
}

 

همه این کد در اینجا موجود است (پروژه با ویژوال استودیو 2015 ایجاد شد):

SobelOperatorInC#

رمز فایل : behsanandish.com

 

کد الگوریتم sobel در #C

 


 

کد الگوریتم سوبل( Sobel ) در ++C:

در ادامه دو کد برای الگوریتم Sobel  در ++C آماده کردیم:

1.

 

#include&lt;iostream&gt;
#include&lt;cmath&gt;
#include&lt;opencv2/imgproc/imgproc.hpp&gt;
#include&lt;opencv2/highgui/highgui.hpp&gt;

using namespace std;
using namespace cv;

 
// Computes the x component of the gradient vector
// at a given point in a image.
// returns gradient in the x direction
int xGradient(Mat image, int x, int y)
{
    return image.at&lt;uchar&gt;(y-1, x-1) +
                2*image.at&lt;uchar&gt;(y, x-1) +
                 image.at&lt;uchar&gt;(y+1, x-1) -
                  image.at&lt;uchar&gt;(y-1, x+1) -
                   2*image.at&lt;uchar&gt;(y, x+1) -
                    image.at&lt;uchar&gt;(y+1, x+1);
}

// Computes the y component of the gradient vector
// at a given point in a image
// returns gradient in the y direction

int yGradient(Mat image, int x, int y)
{
    return image.at&lt;uchar&gt;(y-1, x-1) +
                2*image.at&lt;uchar&gt;(y-1, x) +
                 image.at&lt;uchar&gt;(y-1, x+1) -
                  image.at&lt;uchar&gt;(y+1, x-1) -
                   2*image.at&lt;uchar&gt;(y+1, x) -
                    image.at&lt;uchar&gt;(y+1, x+1);
}

int main()
{

      Mat src, dst;
      int gx, gy, sum;

      // Load an image
      src = imread(&quot;lena.jpg&quot;, CV_LOAD_IMAGE_GRAYSCALE);
      dst = src.clone();
      if( !src.data )
      { return -1; }

        for(int y = 0; y &lt; src.rows; y++)
            for(int x = 0; x &lt; src.cols; x++)
                dst.at&lt;uchar&gt;(y,x) = 0.0;

        for(int y = 1; y &lt; src.rows - 1; y++){
            for(int x = 1; x &lt; src.cols - 1; x++){
                gx = xGradient(src, x, y);
                gy = yGradient(src, x, y);
                sum = abs(gx) + abs(gy);
                sum = sum &gt; 255 ? 255:sum;
                sum = sum &lt; 0 ? 0 : sum;
                dst.at&lt;uchar&gt;(y,x) = sum;
            }
        }

        namedWindow(&quot;final&quot;);
        imshow(&quot;final&quot;, dst);

        namedWindow(&quot;initial&quot;);
        imshow(&quot;initial&quot;, src);

      waitKey();

 
    return 0;
}

 

دانلود کد فوق از طریق لینک زیر:

Sobel in C++-Code1

رمز فایل : behsanandish.com

 

2.

 

#include &quot;itkImage.h&quot;
#include &quot;itkImageFileReader.h&quot;
#include &quot;itkImageFileWriter.h&quot;
#include &quot;itkSobelEdgeDetectionImageFilter.h&quot;

int main( int argc, char* argv[] )
{
  if( argc != 3 )
    {
    std::cerr &lt;&lt; &quot;Usage: &quot;&lt;&lt; std::endl;
    std::cerr &lt;&lt; argv[0];
    std::cerr &lt;&lt; &quot;&lt;InputFileName&gt; &lt;OutputFileName&gt;&quot;;
    std::cerr &lt;&lt; std::endl;
    return EXIT_FAILURE;
    }

  constexpr unsigned int Dimension = 2;

  using InputPixelType = unsigned char;
  using InputImageType = itk::Image&lt; InputPixelType, Dimension &gt;;

  using ReaderType = itk::ImageFileReader&lt; InputImageType &gt;;
  ReaderType::Pointer reader = ReaderType::New();
  reader-&gt;SetFileName( argv[1] );

  using OutputPixelType = float;
  using OutputImageType = itk::Image&lt; OutputPixelType, Dimension &gt;;

  using FilterType = itk::SobelEdgeDetectionImageFilter&lt; InputImageType, OutputImageType &gt;;
  FilterType::Pointer filter = FilterType::New();
  filter-&gt;SetInput( reader-&gt;GetOutput() );

  using WriterType = itk::ImageFileWriter&lt; OutputImageType &gt;;
  WriterType::Pointer writer = WriterType::New();
  writer-&gt;SetFileName( argv[2] );
  writer-&gt;SetInput( filter-&gt;GetOutput() );

  try
    {
    writer-&gt;Update();
    }
  catch( itk::ExceptionObject &amp; error )
    {
    std::cerr &lt;&lt; &quot;Error: &quot; &lt;&lt; error &lt;&lt; std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}

 

دانلود کد فوق از طریق لینک زیر:

Sobel in C++-Code2

رمز فایل : behsanandish.com

 


کد الگوریتم سوبل( Sobel ) در C:

 

/* sobel.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;float.h&gt;
#include &quot;mypgm.h&quot;

void sobel_filtering( )
     /* Spatial filtering of image data */
     /* Sobel filter (horizontal differentiation */
     /* Input: image1[y][x] ---- Outout: image2[y][x] */
{
  /* Definition of Sobel filter in horizontal direction */
  int weight[3][3] = {{ -1,  0,  1 },
      { -2,  0,  2 },
      { -1,  0,  1 }};
  double pixel_value;
  double min, max;
  int x, y, i, j;  /* Loop variable */

  /* Maximum values calculation after filtering*/
  printf(&quot;Now, filtering of input image is performed\n\n&quot;);
  min = DBL_MAX;
  max = -DBL_MAX;
  for (y = 1; y &lt; y_size1 - 1; y++) {
    for (x = 1; x &lt; x_size1 - 1; x++) {
      pixel_value = 0.0;
      for (j = -1; j &lt;= 1; j++) {
    for (i = -1; i &lt;= 1; i++) {
      pixel_value += weight[j + 1][i + 1] * image1[y + j][x + i];
    }
      }
      if (pixel_value &lt; min) min = pixel_value;
      if (pixel_value &gt; max) max = pixel_value;
    }
  }
  if ((int)(max - min) == 0) {
    printf(&quot;Nothing exists!!!\n\n&quot;);
    exit(1);
  }

  /* Initialization of image2[y][x] */
  x_size2 = x_size1;
  y_size2 = y_size1;
  for (y = 0; y &lt; y_size2; y++) {
    for (x = 0; x &lt; x_size2; x++) {
      image2[y][x] = 0;
    }
  }
  /* Generation of image2 after linear transformtion */
  for (y = 1; y &lt; y_size1 - 1; y++) {
    for (x = 1; x &lt; x_size1 - 1; x++) {
      pixel_value = 0.0;
      for (j = -1; j &lt;= 1; j++) {
    for (i = -1; i &lt;= 1; i++) {
      pixel_value += weight[j + 1][i + 1] * image1[y + j][x + i];
    }
      }
      pixel_value = MAX_BRIGHTNESS * (pixel_value - min) / (max - min);
      image2[y][x] = (unsigned char)pixel_value;
    }
  }
}

main( )
{
  load_image_data( );   /* Input of image1 */ 
  sobel_filtering( );   /* Sobel filter is applied to image1 */
  save_image_data( );   /* Output of image2 */
  return 0;
}
دانلود کد فوق از طریق لینک زیر:

Sobel in C

رمز فایل : behsanandish.com


 

کد الگوریتم سوبل( Sobel ) در Visual Basic:

 

Private Sub bEdge_Click(sender As Object, e As EventArgs) _
Handles bEdge.Click

'Sobel Edge'
Dim tmpImage As Bitmap = New Bitmap(picOriginal.Image)
Dim bmpImage As Bitmap = New Bitmap(picOriginal.Image)

Dim intWidth As Integer = tmpImage.Width
Dim intHeight As Integer = tmpImage.Height

Dim intOldX As Integer(,) = New Integer(,) {{-1, 0, 1}, _
{-2, 0, 2}, {-1, 0, 1}}
Dim intOldY As Integer(,) = New Integer(,) {{1, 2, 1}, _
{0, 0, 0}, {-1, -2, -1}}

Dim intR As Integer(,) = New Integer(intWidth - 1, _
intHeight - 1) {}
Dim intG As Integer(,) = New Integer(intWidth - 1, _
intHeight - 1) {}
Dim intB As Integer(,) = New Integer(intWidth - 1, _
intHeight - 1) {}

Dim intMax As Integer = 128 * 128

For i As Integer = 0 To intWidth - 1

For j As Integer = 0 To intHeight - 1

intR(i, j) = tmpImage.GetPixel(i, j).R
intG(i, j) = tmpImage.GetPixel(i, j).G
intB(i, j) = tmpImage.GetPixel(i, j).B

Next

Next

Dim intRX As Integer = 0
Dim intRY As Integer = 0
Dim intGX As Integer = 0
Dim intGY As Integer = 0
Dim intBX As Integer = 0
Dim intBY As Integer = 0

Dim intRTot As Integer
Dim intGTot As Integer
Dim intBTot As Integer

For i As Integer = 1 To tmpImage.Width - 1 - 1

For j As Integer = 1 To tmpImage.Height - 1 - 1

intRX = 0
intRY = 0
intGX = 0
intGY = 0
intBX = 0
intBY = 0

intRTot = 0
intGTot = 0
intBTot = 0

For width As Integer = -1 To 2 - 1

For height As Integer = -1 To 2 - 1

intRTot = intR(i + height, j + width)
intRX += intOldX(width + 1, height + 1) * intRTot
intRY += intOldY(width + 1, height + 1) * intRTot

intGTot = intG(i + height, j + width)
intGX += intOldX(width + 1, height + 1) * intGTot
intGY += intOldY(width + 1, height + 1) * intGTot

intBTot = intB(i + height, j + width)
intBX += intOldX(width + 1, height + 1) * intBTot
intBY += intOldY(width + 1, height + 1) * intBTot

Next

Next

If intRX * intRX + intRY * intRY &gt; intMax OrElse
intGX * intGX + intGY * intGY &gt; intMax OrElse
intBX * intBX + intBY * intBY &gt; intMax Then

bmpImage.SetPixel(i, j, Color.Black)

Else

bmpImage.SetPixel(i, j, Color.Transparent)

End If

Next

Next

picModified.Image = bmpImage

End Sub
دانلود کد فوق از طریق لینک زیر:

Sobel in VB

رمز فایل : behsanandish.com

 

کد الگوریتم sobel در VB

 


 

پیشنهاد می کنیم جهت آشنایی با الگوریتم های لبه یابی، مطلب «الگوریتم های لبه یابی و انواع آن» را مشاهده نمایید.

 

Interpolation يا درون یابی

Interpolation يا درون یابی (كه گاهي resampling نيز ناميده ‌مي‌شود) يك روش گرافيكي براي افزايش يا كاهش تعداد پيكسل‌هاي يك تصوير ديجيتالي است. دوربين‌هاي ديجيتالي از اين روش براي زوم ديجيتال و يا افزايش مصنوعي ابعاد تصوير، نسبت به تصوير اصلي ثبت شده توسط حسگر خود استفاده مي‌كنند. كيفيت تصوير نهايي حاصل از درون‌يابي به پيچيدگي الگوريتم ساخت تصوير بستگي دارد. حالت‌هاي متفاوت درون‌يابي عبارتند است از:

Nearest Neighbor Interpolation

اين روش ساده‌ترين عمليات درون‌يابي محسوب مي‌شود كه اساساً پيكسل‌هاي بزرگ‌تري را ايجاد مي‌كند و رنگ هر پيكسل در تصوير جديد، با رنگ نزديك‌ترين پيكسل در تصوير اصلي مطابقت دارد. به عنوان مثال اگر شما يك تصوير را 200 درصد بزرگ كنيد، يك پيكسل تصوير به يك فضاي چهار پيكسلي (دو پيكسل در دو پيكسل) با رنگ پيكسل اوليه تبديل مي‌شود. بسياري از دوربين‌هاي ديجيتالي براي زوم‌كردن روي يك سوژه از اين روش استفاده مي‌كنند. زيرا اين روش هيچ تأثيري بر اطلاعات رنگي تصوير نمي‌گذارد. اصولاً بهتر است از اين روش براي افزايش ابعاد تصوير استفاده نشود. چرا كه موجب ايجاد حالت شطرنجي در تصوير مي‌گردد.

Bilinear Interpolation

اين روش ارزش يك پيكسل رنگي را براساس چهار پيكسل در جهت‌هاي عمودي و افقي پيكسل در تصوير اصلي معين‌مي‌كند. تصوير جديد داراي خاصيت Anti-aliasing است و تقريباً هيچ اثري از پيكسل‌هاي شطرنجي در آن ديده نمي‌شود.

Bicubic Interpolation

اين روش داراي پيچيده‌ترين الگوريتم درون‌يابي است و تصويري كه با اين روش به دست مي‌آيد، لبه‌هاي بسيارنرم‌تري پيدا مي‌كند. در اين حالت پيكسل جديد براساس ارزش تخميني 16 پيكسل (چهار پيكسل در چهار پيكسل) برآورد‌مي‌شود.

شايان ذكر است كه اغلب دوربين‌ها، چاپگرها و نرم‌افزارهاي گرافيكي براي تغيير تعداد پيكسل‌هاي يك تصوير از اين روش استفاده مي‌كنند.
نرم‌افزار Photoshop CS دو نوع Sharper و Smoother اين درون‌يابي را نيز ارائه مي‌دهد.

Fractal Interpolation

اين روش براي بزرگ كردن تصوير در ابعاد خيلي بزرگ (به‌عنوان مثال چاپ روي بدنه يك اتوبوس) روش بسيار مناسبي به‌شمار مي‌رود. زيرا با دقت خوبي مي‌تواند شكل اجزاي تصوير را حفظ كند. لبه‌هاي بسيار تميزتر و صاف‌تري را نيز برجا مي‌گذارد. در اين حالت مناطق محوي كه در لبه‌هاي تصوير در روش‌هاي قبل وجود داشتند، به ندرت ديده مي‌شوند. البته روش‌هاي ديگري هم وجود دارند كه جز در برنامه‌هاي گرافيكي پيشرفته، به‌ندرت از آن‌ها استفاده مي‌شود.

اشکالات

پلتفرم

منبع چارچوب دات‌نت مایکروسافت برای اجرا فقط ویندوز است. پیاده‌سازی‌های دیگری برای اجرای برنامه‌های #C در ویندوز، لینوکس،BSD یا Mac OS X وجود دارند اما هنوز کامل نیستند: Mono و DotGNU در نوامبر سال ۲۰۰۲ توسط مایکروسافت (نسخه ۱٫۰) برای پیاده‌سازی CLI برای کار در Free BSD و Mac OS X ۱۰٫۲ ارائه شد، اما نسخه‌های بعدی آن‌ها فقط قابل اجرا بر رویویندوز بود.

پیشرفت در آینده

نسخه بعدی این زبان، سی شارپ ۴ است که از اکتبر سال ۲۰۰۸ در حال ساخته شدن است. مایکروسافت لیستی از ویژگی‌های جدید سی شارپ ۴ را در کنفرانس توسعه دهندگان حرفه‌ای اعلام کرده‌است. تمرکز اصلی در ورژن بعدی روی قابلیت هماهنگی فریم ورک‌ها و نوع زبان‌هایی است که کامال پویا یا قیمتی پویا هستند، مانند dynamic language runtime و COM. ویژگی‌های زیر تاکنون اعلام شده‌اند:

پارامترهای نوع generic از نوع Covariant و contravariant

پارامترهای واسط‌های generic و deletageها می‌توانند با استفاده از کلمات out و in از دو نوع Covariant و contravariant باشند. این تعیین نوع‌ها بعداً برای تبدیل انواع به یکدیگر، چه از نوع صریح یا مجازی و چه از نوع compile-time یا run-time به کار می‌رود. به عنوان مثال، واسط IEnumerable<T> در زیر دوباره تعریف شده‌است:

interface IEnumerable < out T >
{
  IEnumerator < T > GetEnumerator();
}

بنابراین، هر کلاس مشتق شده‌ای که از IEnumerable<Derived> استفاه کرده باشد، با تمام کلاس‌های پایه که IEnumerable<Base> را دارند سازگار است. به عنوان تمرین، کد زیر نوشته شده‌است:

void PrintAll(IEnumerable < object > objects)
{
  foreach (object o in objects)
  {
    Console.WriteLine(o);
  }
}

IEnumerable < string > strings = new List < string > ();
PrintAll(strings);// IEnumerable<string> is implicitly converted to IEnumerable < object >

برای contravariance، رابط IComparer < T > به صورت زیر دوباره تعریف شده‌است:

 public interface IComparer < in T >
{
    int Compare(T x, T y);
}

بنابراین، هر کلاسی که IComparer < Base > را برای یک کلاس پایه بیان می‌کند، با IComparer < Derived > در تمام واسط‌ها و کلاس‌هایی که از آن کلاس پایه مشتق شده‌اند، سازگار است. این امر نوشتن کد زیر را میسر می‌سازد:

IComparer < object > objectComparer = GetComparer();
IComparer < string > stringComparer = objectComparer;IComparer < object > objectComparer = GetComparer();
IComparer < string > stringComparer = objectComparer;

جستجوی عضو پویا

در سامانه انواع داده‌های #C یک نوع جدید با نام شبه-نوع معرفی شده‌است که مانند System.Object رفتار می‌کند، ولی در ادامه، هر دسترسی به اعضا یا برنامه‌هایی که از این نوع استفاده می‌کنند، بدون چک شدن نوع داده‌هایشان اجازه کار دارند و تجزیه آن‌ها تا زمان اجرا به تعویق می‌افتد. به عنوان مثال:

// Returns the value of Length property or field of any object
  int GetLength(dynamic obj)
  {
    return obj.Length;
  }

  GetLength("Hello, world");// a string has a Length property,
  GetLength(new int[] { 1, 2, 3 });// and so does an array,
  GetLength(42);// but not an integer - an exception will be thrown here at run-time

صدا زده شدن‌های متد پویا، مانند پارامترهای صریح یا مجازی با مقدار نوع dynamic راه‌اندازی می‌شوند. به عنوان مثال:

 void Print(dynamic obj)
  {
     Console.WriteLine(obj);// which overload of WriteLine() to call is decided at run-time
  }

  Print(123);// ends up calling WriteLine(int)
  Print("abc");// ends up calling WriteLine(string)

جستجوی پویا تحت سه مکانیزم مشخص اجرا می‌شود: COM IDispatch برای اشیاء COM، رابط IDynamicObject DLR برای اشیاء دارای این واسط و Reflection برای بقیه اشیا؛ بنابراین هر کلاس #C می‌تواند صدا زده شدن‌های پویای خود را با اجرای IDynamicObject در نمونه‌های خود جدا کند. در مورد متدهای پویا و مشخص‌کننده صدا زدن‌ها، تجزیه و تحلیل اضافه بار مطابق انواع اصلی که به عنوان آرگومان‌ها هستند، در زمان اجرا اتفاق می‌افتد، در غیر این صورت بر اساس قوانین تجزیه و تحلیل اضافه بار #C عمل خواهد شد. به علاوه، در مواردی که در صدا زدن پویا، گیرنده خودش پویا نیست، تجزیه و اضافه بار زمان اجرا تنها به متدهایی که در زمان کامپایل به صورت گیرنده ظاهر شده‌اند، رسیدگی می‌کند. به عنوان مثال:

class Base
{
  void Foo(double x);
}

class Derived: Base
{
  void Foo(int x);
}

dynamic x = 123;
Base b = new Derived();
b.Foo(x);// picks Base.Foo(double) because b is of type Base, and Derived.Foo(int) is not exposed
dynamic b1 = b;
b1.Foo(x);// picks Derived.Foo(int)

هر مقداری که توسط دستیابی به عضو پویا برگردانده شده باشد، خودش از نوع پویا است. مقادیر نوع پویا به سایر نوع‌ها و از سایر نوع عا قابل تبدیل هستند. در نمونه کد بالا، این امر به تابع GetLength اجازه با مقدار بازگردانده شده از Length بدون هیچ صریحی به عنوان integer استفاده کند. در زمان اجرا، مقدار واقعی به نوع خواسته شده تبدیل می‌شود.

کلمه کلیدی اختیاری ref

در حال حاضر کلمه کلیدی ref برای متدهای صدا زننده اختیاری است. کد زیر را در نظر بگیرید:

void Increment(ref int x)
{
  ++x;
}

int x = 0;
Increment(ref x);

به صورت زیر هم می‌تواند نوشته شود:

void Increment(ref int x)
{
  ++x;
}

int x = 0;
Increment(x);

آرگومان‌های نام‌گذاری شده و پارامترهای اختیاری

در سی شارپ ۴ پارامترهای اختیاری ای با مقادیر پیش‌فرض موجود در ++C معرفی می‌شوند. به عنوان مثال:

void Increment(ref int x, int dx = 1)
{
  x += dx;
}

int x = 0;
Increment(ref x);// dx takes the default value of 1
Increment(x, 2);// dx takes the value 2

به علاوه، برای کامل کردن پارامترهای اختیاری، می‌توانید صریحاً نام پارامترها را در صدازدن‌های متدها تعیین کنید. این کار به شما اجازه تصویب کردن انتخابی برای هر زیر مجموعه اختیاری از پارامترهای متد را می‌دهد. تنها محدودیت موجود این است که پارامترهای نام دار باید بعد از پارامترهای بدون نام بیایند. نام پارامترها می‌توانند برای هر دو نوع پارامترهای اختیاری و ضروری تعیین شوند و می‌توانند برای بهبود خوانایی و فراخوانی دوباره آرگومان‌ها مفید باشند. به عنوان مثال:

Stream OpenFile(string name, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) { ... }

OpenFile("file.txt");// use default values for both "mode" and "access"
OpenFile("file.txt", mode: FileMode.Create);// use default value for "access"
OpenFile("file.txt", access: FileAccess.Read);// use default value for "mode"
OpenFile(name: "file.txt", access: FileAccess.Read, mode: FileMode.Create);// name all parameters for extra readability, and use order different from method declaration

پارامترهای اختیاری inter-operating را با COMراحت تر می‌کنند. در گذشته، #C مجبور بود تمام پارامترهای متد سازنده COM را پشت سر بگذارد، حتی آنهایی را که اختیاری بودند؛ به عنوان مثال:

object fileName = "Test.docx";
object missing = System.Reflection.Missing.Value;

doc.SaveAs(ref fileName,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing);

با پشتیبانی از پارامترهای اختیاری، کد بالا می‌تواند به صورت زیر خلاصه بشود:

doc.SaveAs("Test.docx");

کتابخانه‌ها

جزئیات مشخصات سی شارپ، حداقل تعداد نوع‌ها و کتابخانه‌های کلاس است که کامپایلر نیاز به وجود آن‌ها دارد. عملاً، اغلب سی شارپ توسط بیشترین استفاده از CLI را می‌کند، که استاندارد شده ECMA-۳۳۵ است.

مثال Hello world

در زیر یک مثال ساده از برنامه سی شارپ آمده‌است، نسخه‌ای از مثال کلاسیک Hello World:

class ConsoleApp1
{
    static void Main()
    {
        // a first program in C#.net
        System.Console.Write("Hello, World!");
    }
}

نتیجه، چاپ شدن متن زیر در خروجی است:

Hello, world!

هر خط هدفی دارد:

class ExampleClass

در بالا، تعریف کلاس آمده‌است. هر چیزی که در بین در علامت پرانتز باشد،ExampleClass را توصیف می‌کند:

static void Main()

این یک تابع عضو کلاس را در زمان شروع اجرای برنامه اعلان می‌کند. دات نت در زمان اجرا، تابع Main را صدا می‌زند (نکته: Main ممکن است از هر جای دیگری نیز صدا زده شود، مثلاً توسط تابع ExampleClass و با کد ()Main). کلمه کلیدی static تابع را بدون داشتن نمونه‌ای از ExampleClass قابل دسترس می‌کند. هر تابع Main در هر کنسولی باید به صورت static تعریف شود. در غیر این صورت برنامه به یک نمونه نیاز خواهد داشت و هر نمونه به یک برنامه نیاز دارد. برای اجتناب از این وابستگی دایره‌ای تجزیه ناپذیر، کامپایلرهای سی شارپ در صورت Static نبودن تابع Main، یک خطا اعلام می‌کنند. کلمه کلیدی void نشان دهنده این است که تابع Main هیچ مقداری را برنمی‌گرداند.

Console.WriteLine("Hello, world!");

خط بالا، خروجی را می‌نویسد. در فضای اسم System, Console یک کلاس استاتیک است که یک میانجی بین ورودی، خروجی و خطای کنسول می‌باشد. برنامه‌ای که متدWriteLine را از کنسول صدا می‌زند، خروجی رشته «Hello, world!» را در خروجی نمایش می‌دهد.

استانداردسازی

در آگوست سال ۲۰۰۰، شرکت مایکروسافت، و Hewlett-Packard و شرکت اینتل به عنوان پشتیبان مشخصات سی شارپ را مانند CLI به سازمان استانداردسازی ECMA ارائه کردند. در دسامبر سال ۲۰۰۱، این سازمان، ECMA-۳۳۴ را با عنوان مشخصات زبان #C منتشر کرد. سی شارپ در سال ۲۰۰۳ به عنوان یک استاندارد ISO به ثبت رسید(ISO/IEC ۲۳۲۷۰). در سال ۲۰۰۲، ECMA دومین ویرایش از خصوصیات زبان سی شارپ را پذیرفت.

در ژوئن سال ۲۰۰۵، ECMA سومین ویرایش را با اضافه کردن مواردی همچون کلاس‌های partial، متدهای ناشناس، انواع nullable و Genericها منتشر کرد. در ژوئیه ۲۰۰۵، ECMA استانداردها و TRها را همراه با پردازش Fast-Track اخیر به ISO/IEC JTC پیشنهاد کرد. این روند معمولاً ۶ تا ۹ ماه زمان می‌برد. آخرین ویرایش این زبان در ۱۵ آگوست سال ۲۰۱۲ در قالب Framework ۴٫۵ارائه گردید

کارایی

با توجه به توابع موجود در چارچوب دات‌نت امکان استفاده از این توابع وجود دارد که می‌توان گفت برای هر کاری شرکت مایکروسافت تابعی پیش‌بینی کرده؛ که این امکان را ایجاد می‌کند که به فایل اصلی پروژه هیچ فایل کتابخانی را اضافه نکنید (هم به صورت دستی یا خود کامپایلر). این موضوع خود باعث ایجاد فایل‌های خروجی با حجم بسیار کم می‌شود. این موضوع در بسیاری از موارد بسیار اهمیت دارد. برنامه‌های سی شارپ، همچون تمام برنامه‌های نوشته شده در چارچوب دات‌نت و سایر محیط‌های ماشینی مجازی مانند جاوا، نیازمند منابع سامانه و حافظه بیشتری نسبت به برنامه‌های نوشته شده با سایر زبان‌ها مانند سی پلاس پلاس است و هم چنین سرعت کمتری نیز دارد. هر چند تعریف زبان سی شارپ و CLI تحت استانداردهای ISO و ECMA استاندارد شده‌اند،CLI تنها قسمتی از Base Class Library (BCL) مایکروسافت می‌باشد که شامل کلاس‌های غیر استاندارد استفاده شده در برنامه‌های #C نیز می‌شود. از این گذشته، بعضی از قسمت‌های BCL تحت حق امتیاز مایکروسافت هستند که ممکن است پیاده‌سازی کامل framework را مختل کند، زیرا تنها بخش‌های استاندارد دارای حق محافظت RAND در برابر مدعیان را دارند.

پیاده‌سازی‌ها

متداول‌ترین کامپایلر سی شارپ، Microsoft Visual C# می‌باشد.

کامپایلرهای سی شارپ
  • پروژه Microsoft Rotor (در حال حاضر به عنوان Shared Source Common Language Infrastructure شناخته می‌شود) (ثبت شده فقط برای استفاده آموزشی و تحقیقی) یک پیاده‌سازی منبع اشتراکی از CLR Runtime را فراهم می‌آورد و یک کامپایلر سی شارپ، و یک زیرمجموعه از کتابخانه]] CLI Framework مورد نیاز.
  • پروژه Mono یک اوپن سورس از کامپایلر سی شارپ است، یک پیاده‌سازی اوپن سورس کامل از CLI شامل کتابخانه‌های Framework مورد نیاز که در ECMA ظاهر شده‌اند، و یک پیاده‌سازی کامل نزدیک به بقیه کتابخانه‌های اختصاصی کلاس چارچوب دات‌نت مایکروسافت.
  • پروژه DotGNU نیز یک اوپن سورس از کامپایلر سی شارپ است، که پیاده‌سازی آن بسیار نزدیک به Common Language Infrastructure می‌باشد و کتابخانه‌های framework مورد نیاز موجود در ECMA و زیر مجموعه‌ای از کلاس‌های کتابخانه‌ای شخصی مایکروسافت در دات نت و دات نت ۲ را دربردارد.

کاملاً شبیه به پروژه Mono.

نام زبان

اسم سی شارپ از علامت موسیقی شارپ گرفته شده‌است که در موسیقی بیان گر این است که متن نوشته شده باید نیم قدم از خط بالاتر باشد. مطابق با ECMA-۳۳۴، بخش ۶، مخفف‌ها و اختصارها، نام زبان به صورت «#C» نوشته می‌شود(«کلمه لاتین C (U+۰۰۴۳) به همراه علامت عددی #(U+۰۰۲۳)») که به صورت «سی شارپ» تلفظ می‌شود. علامت «#» نباید با علامت شارپدر موسیقی(♯، U+266F) که در یک صفحه کلید استاندارد وجود ندارد اشتباه گرفته شود. پسوند شارپ، توسط بسیاری دیگر از زبان‌های دات نت مانند #J، #A و #F نیز به کار رفته‌است. پیاده‌سازی اولیه از زبان ایفل تحت دات نت نیز #Eiffel نام داشت که الان زبان ایفل را به‌طور کامل پشتیبانی می‌کند. هم چنین این پسوند بعضی وقت‌ها در کتابخانه‌ها نیز به کار می‌رود، مانند #Gtk، #Cocoa و#Qt.

کلمات اختصاری به کار رفته در این متن

منبع

آشنایی با #C قسمت 1
آشنایی با #C قسمت 2
آشنایی با #C قسمت 3

کانال شرکت بهسان اندیش در سایت اشتراک ویدئو آپارات (Aparat)

کانال شرکت بهسان اندیش در سایت آپارات – در دنیای مجازی که شبکه های اجتماعی همچون کشوری مستقل عمل می کنند دسته ای از کاربران متناسب با فعالیت خود نیاز به امکاناتی خاص تر دارند. سازمان های دولتی و خصوصی، برند ها، شخصیت های سیاسی، هنری، فرهنگی و… برای ایجاد ارتباط و پیشبرد فعالیت خود نیاز به اعتماد مخاطب دارند.

در شبکه های اجتماعی ، گاه هویت واقعی یک کاربر مشخص نیست و ممکن است دیگران به اسم سازمان ها و اشخاص صفحاتی را ایجاد کنند و نام آن برند یا شخص را خدشه دار نمایند و با توجه به آنکه ایجاد اعتماد در مخاطب، امری مشکل است ، آپارات با رسمیت بخشیدن به صفحات و تایید آنها این رویکرد را متفاوت کرده است.

شرکت بهسان اندیش به منظور ارائه خدمات و فعالیت های خود در شبکه های اجتماعی اقدام به راه اندازی کانال شرکت بهسان اندیش در سایت آپارات نموده که علاقمندان می توانند از طریق لینک زیر در این سایت ما را دنبال کنید:

ورود به صفحه شخصی شرکت بهسان اندیش در سایت اشتراک ویدئو آپارات

 

شرکت بهسان اندیش در آپارات

www.aparat.com

بهینه سازیبهینه‌سازی چیست؟

بهینه‌سازی یک مسئله ریاضی و کلی است که از قرن‌ها پیش مطرح بوده است و در حال حاضر هم یک مسئله و موضوع در دست بررسی و پژوهش است. هنوز راه حلی کلی برای تمام مسائل بهینه‌سازی مطرح نشده است. البته در بعضی موارد محدود که در آن تابع هدف کاملا مشخص شده و معین است و مسائلی مانند مشتق‌پذیری در آن وجود دارد؛ می‌توانیم بصورت دقیق آن را حل کنیم. در بعضی از مسائل هم جواب نهایی وجود دارد ولی زمان محاسبه آن بسیار زیاد طول خواهد کشید. با این حال هنوز برای بعضی از مسائل راه حل معقول و مشخصی ابداع نشده است. بر همین اساس، طبقه‌بندی‌های مختلفی برای اینگونه مسائل از لحاظ پیچیدگی و یا پارامترهای دیگر تعیین شده است. بطور مثال: مسائل برنامه‌ریزی خطی (LP)، برنامه‌ریزی غیر خطی (NLP)، مسائل درجه دوم (QP)، مسائل NP,NP-hard و…

بهینه سازی

مسئله فروشنده دوره‌گرد (TSP)

یکی از ساده‌ترین و در عین حال، پرکاربردترین و مفیدترین مسائل مطرح شده در حوزه بهینه‌سازی مسئله فروشنده دوره‌گرد (Traveling Salesman Problem) است.

در این مسئله فرض شده است که یک فروشنده دوره‌گرد قصد دارد N شهر را بگردد و برای این موضوع یک سری شرایط مطرح شده است. بطور مثال از یک شهر نباید دوبار عبور کرد و از همه شهرها باید یک بار عبور کند و دوباره به شهر اولیه برگردد. سوالی که اینجا پیش می‌آید و مورد بررسی قرار می‌گیرد این است که چگونه این فروشنده در کمترین زمان، این مسافرت را طی می کند و یا اینکه چگونه کمترین مسافت را در این سفر خواهد داشت؟

این مسئله در طبقه‌بندی مسائل NP-hard قرار می‌گیرد و روش‌های عادی نمی تواند پاسخی برای این مسئله پیدا کند. اما بعضی از الگوریتم‌های فراابتکاری و یا تکاملی، می‌توانند در این خصوص پاسخ نه کاملا بهینه اما نزدیک به آن را به ما بدهند.

این مسئله و حل آن می‌تواند در مسائل صنعتی زیادی به ما کمک کند و کاربرد داشته باشد. بطور مثال تعیین مسیر ربات‌هایی که کار سوراخ کردن فیبرهای مدار چاپی را انجام می‌دهند. و همچنین مسائل صنعتی دیگری مانند زمان‌بندی و…

بصورت کلی بیشتر سیستمهای زمان‌بندی و توزیع می‌توانند به نوعی از این مسئله الگوبرداری کنند. هر جا صحبت از ظرفیت است و می‌خواهیم از کمترین ظرفیت استفاده کنیم مسئله ما جایگشتی است و باید از روش و الگوی مسئله TSP کمک گرفته شود.

برای حل این مسئله باید تمام راه حل‌های ممکن و یا حداقل بیشتر آن‌ها بررسی شود تا به جواب و راه حل بهتر دست پیدا کنیم. مشکل ما در این بررسی، فاکتور زمان است. بطور مثال اگر در مسئله فروشنده دوره گرد N شهر داشته باشیم؛ N فاکتوریل هم راه حل خواهیم داشت.

بهینه سازی

ارتباط بهینه‌سازی و الگوریتم‌های فراابتکاری

بصورت کلی در حل مسائل بهینه‌سازی، مشکلی که ما با آن روبرو هستیم این است که یک مسئله دارای بی‌نهایت راه حل و پاسخ باشد و ما باید بهترین پاسخ را در بین آنها پیدا کنیم. در واقع عمل جستجو (search) و بهینه‌سازی (optimization) در این مسائل بکار برده می شوند و از یک نوع معقوله و در راستای هم هستند و الگوریتم‌هایی در این جا کاربردی تر هستند که یک بخش عمده پاسخ‌ها را بررسی کنند و در بین آنها به جواب نهایی برسند.

بهترین و کارآمدترین الگوریتم‌ها باید یک سری ویژگی‌ها را داشته باشند. بطور مثال: قابلیت کشف و جستجوی بالا (exploration) و قابلیت استخراج کردن (exploitation)

الگوریتم‌های بهینه‌سازی کلاسیک، اغلب این قابلیت‌ها را به صورت متعادل ندارند. بطور مثال قابلیت Global search برای استخراج کردن را ندارند. مکانیزم این گونه الگوریتم‌ها Local search است. همچنین الگوریتم‌های Random search (جستجوی تصادفی) در این بین هستند که Global search خوبی دارند ولی در نهایت نمی توانند به همگرایی مورد نیاز برسند. در واقع روشی که در بین این الگوریتم‌ها بصورت هوشمندانه عمل کند و در نهایت به همگرایی برسد، همان الگوریتمهای فراابتکاری و تکاملی است.

بهینه سازی

الگوریتم ژنتیک

یکی از الگوریتم‌های تکاملی و فراابتکاری، الگوریتم ژنتیک است که از طبعیت ژنتیکی، وراثت، جهش در کروموزم ها و تئوری انتخاب داروین الگوبرداری کرده است. در این الگوریتم ابتدا یک سری جواب و پاسخ و یا راه حل مطرح می‌شود و بعد از آن، راه حل‌ها مانند اتفاقی که در زاد و ولد حیوانات می‌افتد با هم ترکیب می‌شوند. این موجودات یک سری از ویژگی‌های خودشان را برای فرزندانشان به ارث می‌گذارند. اگر فرزند از هر دو والد خود یعنی پدر و مادر، یک ویژگی خوب را به ارث ببرد، نتیجه و جواب بهتری خواهیم گرفت. این روش و الگوریتم نه به صورت کاملا Random و تصادفی و نه کاملا به صورت حریصانه عمل می‌کند و در واقع روشی بین این دو است و به همین علت یک روش کارآمد محسوب می شود.

در این روش نمی توان هم به همگرایی بالایی در کمترین زمان رسید و هم تمام مناطق را به صورت کامل جستجو کرد. با افزایش هر کدام از این پارامترها دیگری کاهش پیدا می کند. اما اغلب الگوریتمهای تکاملی، یک توازن نسبی بین این دو را برقرار کرده‌اند و منشا بیشتر و کارآمدترین آن‌ها طبیعت است.

دیگر الگوریتم‌های فراابتکاری

الگوریتم‌های دیگری نیز در حوزه بهینه‌سازی و محاسبات تکاملی مطرح شده اند مانند: الگوریتم مورچگان (ACO)، الگوریتم ازدحام ذرات (PSO)، الگوریتم کلونی زنبور عسل (ABC)، الگوریتم رقابت استعماری (ICA) و …

نقطه مشترک این الگوریتم‌ها، استناد به یک پدیده طبیعی و واقعی است. بطور مثال الگوریتم ازدحام ذرات از کوچ پرندگان و الگوریتم رقابت استعماری از روابط اجتماعی و انسانی الهام گرفته شده است و همین پدیده‌ها را تبدیل به یک مدل ریاضی و روش حل مسئله بهینه‌سازی می‌کنند.

همان طور که قبلا ذکر شد؛ مسئله بهینه‌سازی با عمل جستجو (search)، رابطه مستقیم دارد و ارتباط این موضوع با الهام گرفتن این الگوریتم‌ها از طبیعت به این صورت است که بطور مثال مورچگان، همیشه به دنبال بهترین منبع غذایی و ذخیره کردن آن هستند. زنبورها به دنبال بهترین گل برای تهیه عسل هستند و بطور کلی طبیعت به دنبال این است که مقاوم‌ترین و برترین موجودات را بسازد.

در ارائه این الگوریتم‌ها از یک زمانی به بعد، الگوریتم‌های مشابه زیادی معرفی شد و بعضی از آن‌ها گاها بسیار به هم شباهت دارند و تفاوت آن‌ها در بعضی مواقع، در حد اسم آنها است. اما هنوز هم این حوزه مورد مطالعه و رو به رشد است و جای پیشرفت بیشتری هم دارد. بطور مثال بهینه‌سازی چند هدفه، یکی از شاخه‌های جذاب بهینه‌سازی است که می تواند مورد مطالعه بیشتری قرار گیرد.

منبع


منابع

1.http://bio1.ir

2.http://www.artaseminar.com

3.https://blog.faradars.org/

بهينه‌سازی و معرفي روش‌های آن قسمت 1
بهينه‌سازی و معرفي روش‌های آن قسمت 2
بهينه‌سازی و معرفي روش‌های آن قسمت 3