خوراک پی سی کدنویس

ورود کاربران

آمار سایت

اعضا : 431
محتوا : 74
پیوندها : 6
بازدیدهای محتوا : 245387

حاضرین در سایت

 285 مهمان حاضر

برای نمایش بهتر سایت، از مرورگر استاندارد فایرفاکس استفاده کنید! مرورگر اینترنت اکسپلورر متعلق به دهه گذشته است!

firefox icon

Valid XHTML 1.0 Transitional Valid CSS!

تفاوت برنامه نویسی MFC و WIN32 در ویژوال سی

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت دوشنبه 23 خرداد 1390 ساعت 12:30

در محیط ++Visual C پروژه های متنوعی می توانید ایجاد کرد که دو نوع آنها استفاده بیشتری دارد. یکی پروژه های MFC و دیگری Win32.
این دو نوع پروژه چه تفاوتی دارند و به چه کارمان می‌آیند؟
تفاوت آنها با پروژه‌ی کنسول ساده چیست؟
با ما همراه باشید...

پروژه های Win32

از اسم win32 پیداست که منظور پروژه هاییست که برای ویندوز 32 بیتی نوشته می شود (البته اگر شما برنامه 64 بیتی هم بخواهید بنویسید باز همین نوع پروژه را می توانید استفاده کنید). ویندوز یک سری کتابخانه های پویا یا همان dll دارد که در این کتابخانه ها توابع متعددی برای کار با پنجره ها در محیط ویندوز وجود دارد. این توابع که به عنوان API (مخفف Application Programming Interface) مشهور هستند نوشته شده اند که کار میکروسافت و سیستم عامل ویندوزش راه بیفتد. لیکن مایکروسافت زحمت کشیده و بخش عظیمی از این API را در اختیار برنامه نویسان هم قرار داده که کار آنها هم لنگ نماند. مثلا تابع MessageBox که یک پیام را نمایش می دهد، یا تابع CreateWindowEx که یک پنجره ایجاد می کند، یا تابع ShellExecute که یک برنامه را اجرا می کند و یا تابع GetCommState که وضعیت پورت Com (ارتباط سریال) را مشخص می کند و توابعی از این دست، همگی در فایلهایی مثل user32.dll و kernel32.dll و ... تعریف شده اند.
به کمک این توابع شما می توانید پنجره بسازید، دکمه تعریف کنید، منو بسازید، نوار ابزار ایجاد کنید و هر آنچه در یک برنامه تحت ویندوز نوعی می بینید، ایجاد کنید. لیکن تمام کارها در قالب کدنویسی صورت می گیرد.

با تعریف پروژه win32 به طور پیش فرض فایل سرآیه‌ی windows.h به پروژه شما اضافه شده، فایلهای lib لازم (مثل user32.lib و kernel32.lib) هم در تنظیمات پروژه اضافه شده و تقریبا تمام توابع لازم برای کار با پنجره ها در اختیار شما قرار می گیرد. اگر این کارها را به صورت دستی در یک پروژه کنسول ساده انجام دهید نیازی به تعریف پروژه win32 ندارید!

پروژه های Microsoft Foundation ClassesMFC

MFC مخفف Microsoft Foundation Classes یعنی کلاسهای پایه ای میکروسافت، کتابخانه ای است که شرکت میکروسافت جهت تسهیل برنامه نویسی برای ویندوز توسعه داده است. این کتابخانه چیزی نیست جز تعدادی کلاس که به صورت پوششی بر روی API ویندوز قرار گرفته و کار کردن با پنجره ها را باز هم آسانتر کرده است. به عبارتی هزاران توابع موجود در API در قالب تعدادی کلاس و به صورت مرتب درآمده اند. مثلا توابع کار با پنجره در کلاس CWnd قرار گرفته اند؛ توابع کار با دکمه در کلاس CButton و توابع کار با دیالوگ در کلاس CDialog واقع شده اند. بسیاری از کلاسهای MFC از جمله CButton، CDialog، CEdit و CRichEdit فرزند کلاس CWnd هستند.
به کمک این نوع پروژه شما می توانید، منو، دیالوگ، نوار ابزار و حتی ریبون (ویژوال استودیو 2010) را به صورت دیداری طراحی کنید و فقط کدهای لازم برای مدیریت رویدادها (مثل کلیک روی یک منوی خاص) را می نویسید. در این نوع پروژه کلاسهایی مثل CImage برای کار با تصاویر، CButton برای کار با دکمه، CFont برای کار با قلمهای ویندوز، CMenu برای منوها و ده ها کلاس متنوع دیگر وجود دارد که برنامه نویسی تحت ویندوز را بسیار تسهیل می کند.

با همه این تفاسیر کار کردن با پروژه های MFC نسبت به زبانهایی مثل #C و ویژوال بیسیک بسیار سخت تر است! به عنوان مثال در #C به محض ساختن یک Text Box با نام edit1 متغیری با همین نام در اختیار شما قرار می گیرد که به راحتی می توانید با آن کار کنید (متن آن را بخوانید یا تغییر دهید یا رنگ آن را عوض کنید) لیکن در MFC باید یک متغیر به آن تخصیص دهید و یا با دستوری مثل GetDlgItem پنجره مربوط به آن Text Box را گرفته و سپس با آن کار کنید. آن هم نه همه کاری! مثلا کارهای ساده ای مثل تغییر رنگ یک کنترل در MFC به سختی پشتک بارو زدن است! کاری که در سایر زبانها در زمان طراحی قابل انجام است. البته همین امر هم سبب شده که برنامه های نوشته شده با ویژوال سی نسبت به سایر زبانها بسیار سریعتر باشند (هر زبان را بهر کاری ساختند!)
 

جبران گذشته و رهایی از سردرگمی

آخرین به روز رسانی در شنبه 24 ارديبهشت 1390 ساعت 11:50 نوشته شده توسط مدیر سایت شنبه 17 ارديبهشت 1390 ساعت 09:07

نظر یکی از کاربران

" با سلام خواهش میکنم مطالبم را بخوانید و کمکم کنید چون من واقعا سر در گم شدم دانشجوی ترم اول مهندسی فناوری اطلاعات مقطع ارشد هستم لیسانسم را در دانشگاه ازاد در رشته نرم افزار گرفتم اما به علت مشکلاتی میخوام از صفر شروع کنم میخوام بدونم چه مطالبی از مبتدی تا پیشرفته را باید یک کارشناس نرم افزار بداند مثلا یکیش نرم افزار matlab لطفا خواهشا از ابتدا بگید که چی بخونم تا بتونم رامو پیدا کنم چه نرم افزار هایی -چه زبان هایی برنامه نویس -چه کارهایی باید بلد باشم."

 

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

می گویند دکتر شریعتی به دانشجویانش می گفت پاسخهایی را می پسندم که ناشی از تفکر باشد نه کپی متن کتاب!

جوزدگی و دور هم بودن: مشکل دانشجویان در حین تحصیل

مشکل از آنجا آغاز می شود که در نظام آموزشی ما دانش آموزان و حتی دانشجویان وادار به تفکر نمی شوند. غالب تکالیف، تقلیدی است. شما باید کتابی را بخوانید و همان را پس بدهید. هیچگاه تشویق نمی شوید که درباره زندگیتان، آینده شغلی تان، کاربرد رشته خودتان در جامعه تفکر کنید. کم می شود که مثلا استادی یا معلمی بگوید این درسی را که می خوانید چه کاربردی دارد و در آینده به چه دردتان خواهد خورد. دانشجویان هم سراغ چنین سوالاتی کمتر می روند و چون دَورهم هستند و خوشند نگران نیستند. حدیث است که می فرماید وقتی بلایی همه گیر شد، تحملش آسان می شود. این موضوع شده است بلای همه گیر، دانشجویان به یکدیگر نگاه می کنند می بینند دوستانشان دارند گیم بازی می کنند یا قهوه تلخ می بینند، آنها هم تشویق می شوند که بی خیال باشند. (البته همیشه استثنائاتی وجود دارند)

نکته بسیار قابل توجه این است که زمانی که فارغ التحصیل می شویم، تازه دوهزاریمان می افتد که ای داد بیداد. چهار سال درس خواندیم ولی ظاهرا چیزی یاد نگرفته ایم!! ممکن است مدتی هم غصه بخوریم... حالا چند راه حل وجود دارد:


  • یکی اینکه با همین تحصیلات آبدوغ خیاری برویم و در جایی استخدام شویم؛ این جا اگر دولتی بود که زیاد به جایی بر نمی خورد و باز دور هم هستیم! لیکن اگر خصوصی بود ناچاریم تازه شروع کنیم به یادگیری

  • دوم اینکه بی خیال درس شده و شغل آزاد انتخاب کنیم، آن هم از نوعی که هیچ ارتباطی با تحصیلاتمان نداشته باشد، مثلا بقالی، نصب پرده، صوتی تصویری و امثال اینها. (این کار را اگر چهار سال زودتر انجام می دادیم شاید بهتر هم بود!)

  • سوم اینکه ادامه تحصیل دهیم، شاید که جبران مافات کنیم. این کار البته دردسرش بیشتر است، چون در فوق لیسانس دیگر خودمان هم وظیفه ای داریم. باید برای هر درسی یکی دو سمینار ارائه دهیم، باید با کتابهای لاتین کنار بیاییم و حتی پیش فرضهای استاد را هم بپذیریم. مثلا استاد انتظار دارد که اولین پروژه درسی را با نرم افزار متلب (MATLAB) بنویسیم ولی ما تا کنون نمی دانستیم که به جز زبان پاسکال و C زبان دیگری هم برای برنامه نویسی هست!

بحث من در مورد افرادیست که گزینه سوم را انتخاب می کنند:

ماهی را هر وقت از آب بگیرید تازه است

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

در دوره کارشناسی ارشد یا هر زمان دیگری که متوجه شدید باید کاری کرد، آستینهای همت را بالا بزنید و دست به کار شوید. ببینید چه چیزهایی نیاز رشته شما و جامعه است، آنها را یاد بگیرید. دقت کنید که از این پس باید به فکر آینده شغلی هم باشید، لذا در یک موضوعی که نیاز جامعه هست سعی کنید متبحر شوید. مثلا در رشته نرم افزار می بینید برنامه نویسی تحت وب نیاز امروز بسیاری از سازمانهاست، آن را خوب یاد بگیرید. در رشته برق، گرایش الکترونیک، می بینید شرکتهای سخت افزاری نیاز مبرمی به افرادی که با FPGA آشنا هستند دارند، آن را بیاموزید. اصلا گاهی اوقات خوب است شما ابتدا علاقه خودتان را بیابید، و برای آن کار پیدا کنید و پایان نامه تان را هم در راستای آن تعریف کنید! این حالت ایده آل است. بگذارید تجربه شخصی ام را خیلی مختصر برایتان بگویم:

تجربه شخصی در دوران کارشناسی ارشد

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

موانع سر راه

و آمّا! بدانید که اگر با پایه ضعیف وارد دوره کارشناسی ارشد شوید (مخصوصا در رشته های فنی) با موانع زیادی رو به رو خواهید شد. مثلا شما زبان انگلیسی تان خوب نیست، لیکن کتابها و مقالاتی که استادتان معرفی می کند انگلیسی است. شما با نرم افزارهای شبیه سازی و زبانهای برنامه نویسی آشنایی ندارید لیکن هر دو هفته باید یک پروژه تحویل دهید. شما در ریاضیات 1 و 2 ضعف دارید لیکن باید فرمول های عجیب و غریب پای تخته را با تکان سر بپذیرید. (یعنی ناچارید بپذیرید که لااقل پیش سایر دانشجویان کم نیاورید) اینها واقعا مشکل است؛ بنده دارم از نزدیک می بینم. لیکن باید جبران کرد. اگر الان جبران نکنید لابد در خدمت مقدس سربازی جبران خواهید کرد؟!

کوچک که بودم برایم پذیرفتن این حدیث خیلی سخت بود: ساعتی تفکر بهتر است از هفتاد سال عبادت. الان سالهاست که دیگر برایم سخت نیست!

موفق باشید

 

 

خوشه یابی با الگوریتم K میانگین در OpenCV

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت پنجشنبه 23 دی 1389 ساعت 18:58

خوشه یابی یکی از مباحث مطرح در حوزه شناسایی الگو است که به عنوان یک طبقه بند بدون نظارت (unsupervised classifier) هم شناخته می شود. وظیفه یک الگوریتم خوشه یابی این است که داده های ورودی را تحلیل کرده و آنها را به تعدادی خوشه تقسیم کند:

خوشه بندی به روش k میانگین

نقاط پراکنده در صفحه دوبعدی به 5 خوشه تقسیم شده اند.
یکی از معروفترین الگوریتمهای خوشه بندی، الگوریتم K میانگین (K-means یا C-means) است. این الگوریتم تلاش می کند که بر اساس یک معیار فاصله، داده ها را به k خوشه تقسیم کند. معمولا هر خوشه توسط بردار میانگین داده های موجود در آن نمایندگی می شود. در روش k همسایگی، روند کار به طور ساده به این صورت است که ابتدا K بردار تصادفی به عنوان مراکز خوشه های اولیه انتخاب می شوند. این بردارها می توانند از فضای داده های ورودی انتخاب شوند یا مقادیر کاملا تصادفی داشته باشند. سپس هر داده ورودی بر اساس یک معیار فاصله (مثل فاصله اقلیدسی یا city block) با بردارهای میانگین اولیه، به یکی از خوشه ها تخصیص داده می شود. در پایان دوره اول، میانگین خوشه ها بر اساس داده هایی که به هر خوشه تخصیص داده شده است، به روز می شوند و فرایند مقایسه و تخصیص تکرار می شود. این فرایند آنقدر ادامه می یابد که بردارهای میانگین خوشه ها دیگر تغییر نکند. تمام

پیاده سازی این الگوریتم خیلی ساده است و هر برنامه نویس متوسطی می تواند پیاده سازی کند لیکن کتابخانه OpenCV این الگوریتم را دارد و شما می توانید به راحتی از آن استفاده کنید.
کد زیر یک برنامه نمونه با استفاده از OpenCV است که البته در مثالهای خود OpenCV هم مشابه آن یافت می شود. جهت استفاده از ساختار جدید OpenCV تغییراتی در آن اعمال شده که استفاده آن در سایر برنامه ها را آسانتر کند. این برنامه چند خوشه با توزیع های گاوسی مختلف تولید می کند و سپس با الگوریتم kmeans آنها را خوشه یابی می کند و در قالب یک تصویر، نتیجه خوشه بندی را نمایش می دهد:
 
#ifdef _CH_
#pragma package 
#endif
 
#define CV_NO_BACKWARD_COMPATIBILITY
 
#ifndef _EiC
#include "cv.h"
#include "highgui.h"
#include 
#endif
 
#ifdef _DEBUG
#pragma comment (lib, "highguid.lib")
#pragma comment (lib, "cxcored.lib")
#else
#pragma comment (lib, "highgui.lib")
#pragma comment (lib, "cxcore.lib")
#endif
 
int main( int argc, char** argv )
{
#define MAX_CLUSTERS 5
	CvScalar color_tab[MAX_CLUSTERS];
	IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
	CvRNG rng = cvRNG(-1);
	CvPoint ipt;
 
	color_tab[0] = CV_RGB(255,0,0);
	color_tab[1] = CV_RGB(0,255,0);
	color_tab[2] = CV_RGB(100,100,255);
	color_tab[3] = CV_RGB(255,0,255);
	color_tab[4] = CV_RGB(255,255,0);
 
	cvNamedWindow( "clusters", 1 );
 
	for(;;)
	{
  char key;
  int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 1;
  int i, sample_count = cvRandInt(&rng)%1000 + 1;
 
 
  cv::Mat _points (sample_count, 2, CV_32FC1);
  cv::Mat _clusters (sample_count, 1, CV_32SC1);
  //cv::RNG& rng = cv::theRNG();
  //rng.fill(_points, cv::RNG::NORMAL, param1, param2 );
  for(int i = 0; i < sample_count; i++){
   CvPoint center;
   CvMat point_chunk;
   center.x = cvRandInt(&rng)%img->width;
   center.y = cvRandInt(&rng)%img->height;
  }
 
  CvMat* points = cvCreateMat( sample_count, 1, CV_32FC2 );
  CvMat* clusters = cvCreateMat( sample_count, 1, CV_32SC1 );
  cluster_count = MIN(cluster_count, sample_count);
 
  /* generate random sample from multigaussian distribution */
  for( k = 0; k < cluster_count; k++ )
  {
   CvPoint center;
   CvMat point_chunk;
   center.x = cvRandInt(&rng)%img->width;
   center.y = cvRandInt(&rng)%img->height;
   cvGetRows( points, &point_chunk, k*sample_count/cluster_count,
    k == cluster_count - 1 ? sample_count :
    (k+1)*sample_count/cluster_count, 1 );
 
   cvRandArr( &rng, &point_chunk, CV_RAND_NORMAL,
    cvScalar(center.x,center.y,0,0),
    cvScalar(img->width*0.1,img->height*0.1,0,0));
  }
 
  /* shuffle samples */
  for( i = 0; i < sample_count/2; i++ )
  {
   CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
   CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
   CvPoint2D32f temp;
   CV_SWAP( *pt1, *pt2, temp );
  }
 
 
  for(int i = 0; i < sample_count; i++){   
   _points.at(i, 0) = points->data.fl[i*2];
   _points.at(i, 1) = points->data.fl[i*2+1];
  }
 
 
  //old OpenCV Style
  //cvKMeans2( points, cluster_count, clusters,
  //	cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ),
  //	5, 0, 0, 0, 0 );
 
  //New OpenCV Style
  cv::kmeans( _points, cluster_count, _clusters,
   cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ),
   5, 0, 0);
 
  cvZero( img );
 
  for( i = 0; i < sample_count; i++ )
  {
   //int cluster_idx = clusters->data.i[i];
   //ipt.x = (int)points->data.fl[i*2];
   //ipt.y = (int)points->data.fl[i*2+1];
 
   int cluster_idx = _clusters.at(i, 0);
   ipt.x = (int)_points.at (i, 0);
   ipt.y = (int)_points.at (i, 1);
 
   cvCircle( img, ipt, 2, color_tab[cluster_idx], CV_FILLED, CV_AA, 0 );
  }
 
  cvReleaseMat( &points );
  cvReleaseMat( &clusters );
 
  cvShowImage( "clusters", img );
 
  key = (char) cvWaitKey(0);
  if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
   break;
	}
 
	cvDestroyWindow( "clusters" );
	return 0;
}
 
#ifdef _EiC
main(1,"kmeans.c");
#endif
 
 
   

لینک دانلود مستقیم OpenCV 2.2

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

آخرین به روز رسانی در شنبه 07 اسفند 1389 ساعت 19:02 نوشته شده توسط مدیر سایت چهارشنبه 15 دی 1389 ساعت 22:44

با توجه به مشکل غالب کاربران در دانلود OpenCV لینک مستقیم آخرین نسخه (تا این زمان) این کتابخانه‌ی بینایی ماشین سازگار با visual c++ 2010 در اختیار کاربران قرار می گیرد. البته تغییراتی در ساختار سلسله مراتبی این کتابخانه رخ داده که با مراجعه به راهنمای آن متوجه خواهید شد.

با توجه به محدودیتهای سایت سورس فورج برای ایران: برای دانلود لینک زیر را کپی کنید (کلیک راست و copy link location یا مشابه آن) و در یکی از نرم افزارهای مدیریت دانلود مثل downthemall که از افزونه های فایرفاکس است بچسبانید.

دانلود OpenCV-2.2.0-win32-vs2010.exe (کلیک نکنید که احتمالا دانلود نمی شود، دستور بالا را بخوانید)

یک نکته اخلاقی هم در مورد سایت خدمت بازدیدکنندگان عزیز عرض کنم: این سایت برای این نیست که شما تمرین بگذارید و ما پاسخ تمرین شما را بدهیم. متاسفانه فروم هم نیست که انتظار داشته باشید سریعا به تمام سوالات شما پاسخ داده شود. تنها جایی است برای آموزش کاربردی زبان ++C به زبان شیرین فارسی. در اینجا هیچ نفع مادی مترتب کسی نیست. اینکه گاهی دیر به دیر به روز می شود به دلیل مشغله مدیر سایت است.

موفق باشید.

 

 

پردازش تصویر به کمک OpenCV : لبه یابی و تغییر اندازه

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

آخرین به روز رسانی در پنجشنبه 04 آذر 1389 ساعت 23:21 نوشته شده توسط مدیر سایت

در مثال قبل، نحوه استفاده از OpenCV را آموختیم. اکنون قصد داریم برنامه ای برای یافتن لبه های تصویر و تغییر اندازه آن بنویسیم. OpenCV توابع زیادی برای کار با تصاویر دارد. در این مثال از 5 تابع cvCanny، cvSobel، cvResize، cvConvertScale و cvSplit استفاده خواهیم کرد که هر کدام را اگر یک تازه کار بخواهد بنویسد شاید چند روز یا حتی چند هفته وقت بگیرد.

خوب بهتر است به کد برنامه نگاهی بیندازیم:

نکته: به دلیل خطاهای غیر قابل پیش بینی که در کلاسهای c++ معرفی شده در نسخه 2.1 اتفاق می افتد، فعلا از خیر این کلاسها می گذریم و از همان توابع C آن استفاده می کنیم.

 
// in the name of allah
// The second OpenCV example
// Working with some image processing functions like edge detectors
// Developed by http://www.P30CodeNevis.ir
// 2010-11-25
 
#include "cv.h"
#include "highgui.h"
 
//Canny Edge Detector
IplImage* doCanny( IplImage* in, double lowThresh, double highThresh, int aperture)
{  
   if(in->nChannels != 1)
      return(0); //Canny only handles gray scale images
   IplImage* out = cvCreateImage( cvGetSize(in), IPL_DEPTH_8U, 1 );
   cvCanny( in, out, lowThresh, highThresh, aperture );
   return( out );
};
 
//Sobel Edge Detector
IplImage* doSobel( IplImage* in, int xOrder, int yOrder, int aperture)
{  
   if(in->nChannels != 1)
      return(0); //Sobel only handles gray scale images
   IplImage* temp = cvCreateImage( cvGetSize(in), IPL_DEPTH_16S, 1 );
   IplImage* out = cvCreateImage( cvGetSize(in), IPL_DEPTH_8U, 1 );
   cvSobel( in, temp, xOrder, yOrder, aperture );
   cvConvertScale(temp, out); 
   cvReleaseImage(&temp);
   return( out );
};
 
//Image Resize
IplImage* doResize( IplImage* in, int filter = CV_INTER_LINEAR ) 
{
   IplImage* out = cvCreateImage(
   cvSize( in->width/2, in->height/2 ), in->depth, in->nChannels );
   cvResize( in, out, filter );
   return( out );
};
 
int main( int argc, char** argv ) {
 
   const char* imagename = argc > 1 ? argv[1] : "camera-man.jpg";
   IplImage* img = cvLoadImage(imagename);
 
   IplImage* resized = doResize(img);
   IplImage* g = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 1 );
   cvSplit(img, 0, g, 0, 0);
   IplImage* cedge = doCanny(g, 50, 175, 3);
   IplImage* sedge = doSobel(g, 0, 1, 3);
 
   cvShowImage("Original", img);
   cvShowImage("Green Channel", g);
   cvShowImage("Resized", resized);
   cvShowImage("Canny Edge", cedge);
   cvShowImage("Sobel Edge", sedge);
 
   cvSaveImage("Green channel.jpg", g);
   cvSaveImage("Resized.jpg", resized);
   cvSaveImage("Canny Edge.jpg", cedge);
   cvSaveImage("Sobel Edge.jpg", sedge);
   cvWaitKey(0);
 
   // Release memory and destroy window
   cvReleaseImage( &resized );
   cvReleaseImage( &g );
   cvReleaseImage( &cedge );
   cvReleaseImage( &sedge );
   cvReleaseImage( &img );
   cvDestroyWindow( "Original" );
   cvDestroyWindow( "Green Channel" );
   cvDestroyWindow( "Resized" );
   cvDestroyWindow( "Canny Edge" );
   cvDestroyWindow( "Eobel Edge" );
 
   return(0);
}
 
 

بارگذاری تصویر مانند مثال قبل، یا از طریق خط فرمان است و یا تصویر camera-man.jpg که باید در مسیر برنامه باشد. برای تغییر اندازه تصویر اصلی از تابع cvResize استفاده می کنیم. این تابع که هم اسم آن و هم رفتار آن مطابق توایع مرسوم تغییر اندازه است، سه پارامتر می گیرد: اولی تصویر ورودی، دومی تصویر خروجی که میزان تغییر مقیاس هم از روی همین تصویر تعیین می شود و سومی نوع الگوریتم است که یکی از چهار مقدار CV_INTER_LINEAR, CV_INTER_NN, CV_INTER_AREA, CV_INTER_CUBIC را می گیرد. این مقادیر به ترتیب برای الگوریتمهای bilinear و binearest neighboura و pixel area resampling و bicubic می باشد. مناسب ترین روش از نظر سرعت و کیفیت همان bilinear است.

توابع cvCanny و cvSobel دو لبه یاب معروف هستند که اولی بار محاسباتی بسیار زیادی نسبت به سوبل دارد. در هر دو مورد، تصویر ورودی باید خاکستری باشد، لذا به کمک cvSplit ما تنها کانال green تصویر را گرفته و به عنوان ورودی به این توابع ارسال می کنیم. کانال green نماینده خوبی از سطح خاکستری تصویر است.

لبه یاب سوبل سه پارامتر می گیرد، اولی نحوه مشتق گیری در راستای افقی (0: عدم مشتق گیری، 1: مشتق اول و 2: مشتق دوم) دومی نحوه مشتق گیری در راستای عمودی و سومی اندازه فیلتر که غالبا 3*3 استفاده می شود. بهتر است تصویر خروجی لبه یاب سوبل از نوع IPL_DEPTH_16S باشد چرا که محاسبات داخلی منجر به مقادیری بیش از یک بایت می شود و لذا برای هر پیکسل از یک عدد صحیح 16 بیتی علامت دار استفاده می کنیم. لیکن برای نمایش تصویر ناچاریم دوباره آن را به IPL_DEPTH_8U (هر پیکسل معادل یک عدد 8 بیتی بدون علامت) برگردانیم که برای این کار از تابع cvConvertScale استفاده می کنیم.

لبه یاب کنی هم سه پارامتر می گیرد، دو تا آستانه پایین و بالا (هر کدام بین 0 و 255) و یکی اندازه فیلتری (مانند فیلتر سوبل) که در داخل canny استفاده می شود. جزئیات بیشتر را از اینجا بخوانید.

سایر کدهای برنامه برای نمایش و ذخیره سازی تصاویر و پاکسازی حافظه است که گمان نمی کنم نیاز به توضیح داشته باشد.

تصاویر خروجی برنامه:

camera man

تصویر ورودی: camera-man.jpg

 

Green channel

تصویر خاکستری (کانال سبز): Green channel.jpg

 

canny edge

تصویر لبه کنی: Canny Edge.jpg

 

Sobel Edge

تصویر لبه سوبل: Sobel Edge.jpg

 

down sampled image

تصویر کوچک شده: Resized.jpg

   

JPAGE_CURRENT_OF_TOTAL