آموزش OpenCV – قسمت چهارم : وقتشه دست به کار شیم!

آموزش OpenCV – قسمت چهارم : وقتشه دست به کار شیم!

در این قسمت ساختار های داده پایه، ماتریس ها و دیگر ساختار های مورد نیازدر پروژه ها را معرفی می کنیم. همچنین در مورد چگونگی ذخیره متغیر ها و داده ها در فایل مشابه به وسیله توابع OpenCV صحبت خواهد شد.

  • خواندن و نوشتن عکس
  • خواندن ویدئو و دسترسی به دستگاه های دوربین
  • ساختار های تصویر اصلی و دیگر ساختار های مهم پایه در ماتریس

 

تصویرکردن و ماتریس ها

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

این مقدار معمولا یک عدد صحیح بین ۰ تا ۲۵۵ هستند ولی می توانند مقادیر دیگری هم داشته باشند. مانند ۰ تا ۱ برای اعداد اعشاری.

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

W*H*N

W عرض تصویر، H ارتفاع تصویر و N تعداد کانال های رنگ تصویر(۱ کانال برای عکس خاکستری و ۳ کانال برای عکس رنگی)

کلاس Mat فقط برای ذخیره عکس استفاده نمی شود بلکه ماتریس هایی با اندازه دلخواه و مقدار دلخواه را نیز ذخیره می کند و شما می توانید اعمال جبری را بر روی این ماتریس ها انجام دهید. ماتریس ها  در حافظه ذخیره می شوند. در دسترسی موثر به جای استفاده از تابع در حافظه، ماتریس به عنوان یک آرایه یا توالی از مقادیر که به وسیله سطر و ستون مرتب شده اند ذخیره می شود. توالی پیکسل ها در OpenCV به صورت BGR Pixel است.

دسترسی به پیکسل ها به وسیله فرمت پیش رو می‌باشد:

توابع OpenCV برای دسترسی تصادفی کاملا بهینه شده اند ولی گاهی اوقات دسترسی مستقیم به حافظه (کار با حساب اشاره گر(Pointer Arithmatic)) کار آمد تر است. مثلا زمانی که می خواهیم به تمامی پیکسل ها در یک حلقه دسترسی داشته باشیم.

خواندن/نوشتن عکس ها

بعد از مقدمه گفته شده درباره ماتریس‌، ما ادامه آموزش را با یک کد ساده OpenCV ادامه می‌دهیم. در ابتدا باید بدانیم که عکس‌ها را چگونه بخوانیم و ذخیره کنیم.

 

خب بیایید کد را با هم بررسی کنیم :

// Read images
Mat color= imread(“../color.jpg”);
Mat gray= imread(“../color.jpg”, 0);

تابع imread تابع اصلی برای خواندن عکس ها است. این تابع عکس را باز کرده و به فرمت ماتریس ذخیره می کند. پارامتر اول رشته ای است که مسیر عکس می باشد و پارامتر دوم اختیاری است که به صورت پیش فرض عکس را رنگی بارگذاری می کند. پارامتر دوم به صورت زیر است:

CV_Load_Image_Anydepth

اگر بدین صورت کد نویسی کنیم زمانی که ورودی عمق متناظر را دارد تصویر یک عکس ۱۶-۳۲ بیتی می باشد در غیر این صورت تابع imread عکس را به ۸ بیت تبدیل می کند.

CV_Load_Image_Color

اگر به این صورت تنظیم شود عکس به صورت رنگی تبدیل می کند.

CV_Load_Image_Grayscale

اگر این مقدار ثابت تنظیم شود، همیشه عکس را به grayscale تبدیل می‌کند.

ذخیره عکس Imwrite

برای ذخیره تصویر در کامپیوتر ازimwrite استفاده می کنیم.

// Write images
imwrite(“colorgray.jpg”, gray);

پارامتر اول مسیر و فرمتی که ما می خواهیم ذخیره کنیم و پارامتر دوم عکسی است که می خواهیم ذخیره شود. در نمونه کد ما، ما ابتدا یک نمونه خاکستری از عکس ساخته و آن را ذخیره می‌کنیم و سپس با فرمت JPG عکس خاکستری را که در متغییر gray بارگذاری کردیم ذخیره می‌کنیم.

دسترسی به پیکسل های عکس

// get same pixel with opencv function
int myRow=color.cols-1;
int myCol=color.rows-1;

با استفاده از خصوصیات .raws و  .cols می توانیم به تعداد سطر و ستون های ماتریسی دسترسی داشته باشیم.

Vec3b pixel= color.at<Vec3b>(myRow, myCol);
cout << “Pixel value (B,g,R): (” << (int)pixel[0] << “,” << (int)
pixel[1] << “,” << (int)pixel[2] << “)” << endl;

برای دسترسی به یک پیکسل از یک عکس ما از کلاس Mat OpenCV CV::Mat::at<typename t>(row, col)  استفاده می کنیم. پارامتر typename در عکس رنگی ۸ بیتی یک کلاس به نام Vec3b میباشد که Unsigned Char را ذخیره میکند. Vec = vector)، ۳=تعداد کامپوننت و b=1byte). برای عکس خاکستری، میتوانیم مستقیما از uchar یا تعداد فرمت‌های دیگری که در عکس استفاده می‌شود، مانند uchar pixel= color.at<uchar>(myRow, myCol) استفاده کنیم.

درنهایت، برای نمایش عکس‌ها، می‌توانیم از تابع imshow برای ساخت پنجره با عنوان پنجره که پارامتر اولش و پارامتر دوم ماتریس عکس می‌باشد استفاده می‌کنیم.

// show images
imshow(“color BgR”, color);
imshow(“color gray”, gray);
// wait for any key press
waitKey(0);

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

نتیجه نهایی کد در پایین نشان داده شده است که در عکس، سمت چپ رنگی و عکس سمت را خاکستری است.

 

Other basic object types

در اینجا دیگر انواع پایه ای مورد نیاز در پروژه ها را معرفی می کنیم

 

وکتور vector

vec یک کلاس کلی است که اصطلاحا برای بردار های عددی مورد استفاده قرار می گیرد. ما هر نوع بردار و یک تعداد —- را میتوانیم تعریف کنیم.

Vec < double , 19> myvector

یا می‌توانیم از دیگر انواع تعریف شده استفاده کنیم.

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;

typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

تمام عملیات‌های برداری مورد انتظار به صورت زیر اجرا می‌شود.

v1 = v2 + v3
v1 = v2 – v3
v1 = v2 * scale
v1 = scale * v2
v1 = -v2
v1 += v2
v1 == v2, v1 != v2
norm(v1) (euclidean norm)

اسکالر scalar

نوع بعدی scalar است که از کلاس vec مشتق شده و دارای ۴ المان است. scalar به طور زیادی برای خواندن و فرستادن مقدار پیکسل ها استفاده می شود. برای دسترسی به مقدار پیکسل ها از عملگر [] استفاده می کنیم.

نقطه Point

کلاس رایج دیگر point  می‌باشد . این کلاس یک نقطه ۲d را تعریف می کند که به وسیله مختصات X و y مشخص می شود. برای نقطه ۳d هم از  point3استفاده میکنیم.

همانند کلاس Vec، OpenCV انواع مختلفی از این کلاس را برای ما تعریف می‌کند.

typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;

عملیات‌های پیش رو برای نقطه تعریف شده است.

pt1 = pt2 + pt3;
pt1 = pt2 – pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 = pt2 / a;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
pt1 /= a;
double value = norm(pt); // L2 norm
pt1 == pt2;
pt1 != pt2;

اندازه size

کلاس بعدی size می باشد که برای مشخص کردن سایز یک عکس یا مستطیل استفاده می شود. دو عضو width و height دارد و تابع مفیدی به نام area() را شامل می شود.

مستطیل Rect

کلاس کلی دیگری که مورد استفاده قرار می گیرد Rect است که یک مستطیل دو بعدی با پارامتر های زیر تعریف می شود.

  • مختصات گوشه بالا و سمت چپ
  • اندازه طول و عرض مستطیل

از کلاس کلی Rect برای تعریف ROI (region of intrest) استفاده می شود.

 مستطیل چرخیده RotatedRect

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

RotatedRect(const Point2f& center, const Size2f& size, float angle);

یکی تابع این کلاس boundingbox است که یک rect را شامل این مستطیل چرخیده برمی گرداند.

بدون دیدگاه

ارسال یک نظر

نظر
نام
ایمیل
وبسایت