شرح مشتق:
۱. مشتق (Derivative) چیه؟
در ریاضیات، مشتق یک تابع، نرخ تغییرات لحظهای اون رو نشون میده. سه حالت داریم:
· مشتق بزرگ مثبت: تابع به سرعت در حال افزایش هست.
· مشتق بزرگ منفی: تابع به سرعت در حال کاهش هست.
· مشتق نزدیک صفر: تابع تقریباً ثابت و بدون تغییر هست.
حالا این مفهوم چطوری به تصویر ربط پیدا میکنه؟
---
۲. تعریف مجدد "تابع" در تصویر
در پردازش تصویر، "تابع" ما یک عکس هست. هر عکس رو میشه به صورت یک تابع دوبعدی در نظر گرفت:
f(x, y) = \text{شدت روشنایی پیکسل در مختصات } (x, y)
پس:
· در یک تصویر، x و y مختصات پیکسل هستند.
· مقدار f(x, y) یک عدد (مثلاً بین ۰ تا ۲۵۵ در تصاویر خاکستری) هست که شدت روشنایی رو نشون میده.
ایده اصلی در تشخیص لبه اینه:
لبهها جاهایی از تصویر هستن که "مشتق" این تابع، ناگهان خیلی بزرگ میشه.
---
۳. چطور مشتق روی پیکسلها اعمال میشه؟
چون تصویر یک موجودیت گسسته است (شامل پیکسلهای جدا از هم)، نمیتونیم از فرمولهای مشتق پیوسته (با حد و ε) استفاده کنیم. به جاش از تقریبهای گسسته استفاده میکنیم. سادهترین تقریب برای مشتق به این شکله:
\frac{df}{dx} \approx f(x+1) - f(x)
این یعنی:
برای پیدا کردن مشتق افقی در یک نقطه، کافیه مقدار پیکسل همسایه راست رو از مقدار همسایه چپ کم کنیم.
مثال کاملاً شفاف:
یک ردیف از پیکسلهای یک تصویر رو با شدت روشنایی زیر در نظر بگیرید. میخوایم ببینیم لبه کجاست:
... ۲۰ , ۲۰ , ۲۰ , ۲۰ , ۱۵۰ , ۱۵۰ , ۱۵۰ , ۱۵۰ ...
موقعیت مقدار پیکسل سادهترین تقریب مشتق (تغییرات)
... ۲۰ -
پیکسل قبل از لبه ۲۰ ۲۰ - ۲۰ = ۰ (بدون تغییر)
پیکسل روی لبه ۱۵۰ ۱۵۰ - ۲۰ = ۱۳۰ (تغییر شدید!)
پیکسل بعد از لبه ۱۵۰ ۱۵۰ - ۱۵۰ = ۰ (بدون تغییر)
... ۱۵۰ -
میبینی؟ مشتق دقیقاً روی پیکسلی که جهش روشنایی داشته، یک عدد خیلی بزرگ (۱۳۰) رو نشون میده و جای دیگه صفره. این یعنی همون نقطه، یک لبه رو تشخیص داده.
---
۴. تقریب سوبل — چرا فقط کم کردن دو تا پیکسل کافی نیست؟
روش بالا (کم کردن پیکسل همسایه) به شدت به نویز حساسه. اگه یه پیکسل تصادفاً یکم روشنتر باشه، مشتق اشتباهی یه عدد بزرگ رو نشون میده. راه حل، استفاده از هستههای سوبل هست که چندتا کارو همزمان انجام میده:
۱. مشتقگیری (پیدا کردن نرخ تغییرات):
به ردیف وسط هستهها دقت کن:
G_x = \begin{bmatrix} -1 & 0 & +1 \\ -2 & 0 & +2 \\ -1 & 0 & +1 \end{bmatrix}
اینجا داریم پیکسلهای سمت چپ رو از پیکسلهای سمت راست کم میکنیم (مفهوم اصلی مشتق که گفتم). علت اینکه پیکسلهای وسط صفر هستن اینه که میخوایم تغییرات رو حول پیکسل مرکزی بسنجیم (مشتق مرکزی).
۲. میانگینگیری برای کاهش نویز:
ببین که عمل تفریق فقط در یک ردیف انجام نمیشه، بلکه در سه ردیف تکرار میشه و مقادیر با هم جمع میشن:
· تفریق در ردیف بالا: (-1) + 0 + (+1)
· تفریق در ردیف وسط: (-2) + 0 + (+2)
· تفریق در ردیف پایین: (-1) + 0 + (+1)
این کار معادل اینه که اول یک فیلتر میانگینگیر نرمکننده (Smoothing) در راستای عمودی اعمال کنیم، و بعد مشتق افقی رو بگیریم. این همون ویژگی منحصربهفرد سوبل هست: مشتقگیری + کاهش نویز در یک عملیات.
اگر نماد ریاضی دوست دارید، هسته سوبل حاصلضرب یک فیلتر مشتقگیر [ -1 , 0 , +1 ] در یک فیلتر نرمکننده [ 1 , 2 , 1 ] هست که به صورت ماتریسی در هم ضرب شدن.
---
۵. آیا OpenCV خودش مشتق داشته باشه؟
خود OpenCV مفهوم "مشتق" به عنوان یک شیء (Object) نداره. بلکه مشتق از طریق توابعی که شامل هستههای مشتقگیر هستن محاسبه و اعمال میشه.
مهمترین تابعی که مستقیم به سوبل مربوطه cv::Sobel() هست:
```cpp
cv::Sobel(src, dst, ddepth, dx, dy, ksize);
```
· dx=1, dy=0: یعنی فقط Gx (تغییرات افقی) رو حساب کن.
· dx=0, dy=1: یعنی فقط Gy (تغییرات عمودی) رو حساب کن.
· dx=1, dy=1: مشتق ترکیبی میده که خروجیش معمولاً اون چیزی نیست که برای تشخیص لبه میخوای.
همچنین تابع قدرتمندتر cv::Scharr() هم وجود داره که یک بهینهسازی از سوبل با هسته ۳x۳ هست و برای تشخیص تغییرات با فرکانس بالا دقت بیشتری داره. cv::Laplacian() هم مشتق مرتبه دوم رو حساب میکنه.
پس خلاصه اینکه: OpenCV خودش مفهوم مشتق رو به صورت انتزاعی ذخیره نمیکنه، بلکه توابعی داره که اون رو با کانولوشن هستههای خاص (مثل هسته سوبل) روی تصویر اعمال میکنن و خروجی (که همون نقشه مشتق/لبههاست) رو بهت تحویل میدن.