تشکر می کنم با اینکه وقت کمی دارید باز هم ادامه می دبد
پردازش تصویر به کمک OpenCV : لبه یابی و تغییر اندازه
آخرین به روز رسانی در پنجشنبه 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.jpg
تصویر خاکستری (کانال سبز): Green channel.jpg
تصویر لبه کنی: Canny Edge.jpg
تصویر لبه سوبل: Sobel Edge.jpg
تصویر کوچک شده: Resized.jpg
-
استاد یه مقدار بین دو آموزش فاصله افتاد گفتم نظرتون عوض شده.
تشکر می کنم با اینکه وقت کمی دارید باز هم ادامه می دبد
-
|*** 2010-11-28 ساعت 11:31:39 *** مسلم
سلام استاد
با این که از پردازش تصویر یکم اطلاعات قبلی داشتم ولی از مطالب این بخش هیچی عایدم نشد
اگه ممکنه یکم از بار تخصصیش کم کنین یا اینکه منبعی معرفی کنین که پیش زمینه های لازم رو داشته باشیم
با تشکر
-
|*** 2011-01-16 ساعت 17:56:33 *** yalda65 - hi
سلام من میخام همین کد را در c# بنویسم از emgu باسد استفاده کنم؟دریت نمیاد یه برنامه نوشتم ولی تابع ها رو نمیشناسه! فرم را برام نمیاره. اگه ممکنه کمکم کنید
-
|*** 2011-01-19 ساعت 08:25:04 *** مدیر سایت
بله در #C باید از EMGU استفاده کنید ولی من با آن کار نکرده ام.
-
|*** 2011-11-12 ساعت 17:43:14 *** مهدی
سلام
نظرتون راجب به امکانات جدید ویژوال سی پلاس پلاس چه
http://blogs.msdn.com/b/vcblog/archive/2011/08/24/10200097.aspx

