لبه یابی

saalek110

Well-Known Member
انواع روشهای لبه یابی و درصد موفقیت:

در OpenCV، چهار روش اصلی برای تشخیص لبه وجود دارد که هر کدام در شرایط خاصی بهترین عملکرد را دارند. در ادامه آن‌ها را با هم مرور می‌کنیم:

---

۱. سوبل (Sobel)

· روش کار: با محاسبه مشتق (گرادیان) تصویر در دو جهت افقی و عمودی، نرخ تغییرات روشنایی را پیدا می‌کند.
· میزان موفقیت:
· ✅ پرنور و با نویز کم: خوب و سریع عمل می‌کند.
· ❌ تصاویر شلوغ و پرنویز: لبه‌های کاذب زیادی پیدا می‌کند. لبه‌ها معمولاً ضخیم و نسبتاً ضعیف هستند و نیاز به آستانه‌گیری دستی دارند.

۲. کنی (Canny) — محبوب‌ترین روش

· روش کار: یک الگوریتم چندمرحله‌ای (کاهش نویز، یافتن گرادیان، نازک‌سازی لبه‌ها و آستانه‌گیری دوگانه) است.
· میزان موفقیت:
· ✅ تقریباً در همه جا عالی: بهترین انتخاب عمومی است، لبه‌های نازک، پیوسته و دقیق می‌دهد و در برابر نویز مقاوم است.
· ⚠️ تنظیم وابسته: عملکردش به تنظیم دو پارامتر threshold1 و threshold2 وابستگی شدیدی دارد. در نور کم اگر درست تنظیم نشود، ممکن است لبه‌های اصلی را از دست بدهد.

۳. لاپلاسین (Laplacian)

· روش کار: مشتق مرتبه دوم را محاسبه می‌کند و نقاطی که شدت روشنایی در آن‌ها تغییر جهت می‌دهد (عبور از صفر) را به عنوان لبه علامت‌گذاری می‌کند.
· میزان موفقیت:
· ✅ لبه‌های تیز: برای تشخیص محل دقیق لبه‌ها خوب است.
· ❌ نویز حساسیت فوق‌العاده زیاد: کوچک‌ترین نویزی را به لبه تبدیل می‌کند. معمولاً باید حتماً با فیلتر گوسی استفاده شود (تبدیل به LoG - Laplacian of Gaussian).

۴. شِر (Scharr)

· روش کار: نسخه بهبودیافته سوبل که هسته‌های ماتریس دقیق‌تری دارد.
· میزان موفقیت:
· ✅ تغییرات کوچک: در تشخیص لبه‌های مورب و ظریف، بسیار دقیق‌تر از سوبل استاندارد عمل می‌کند.
· ❌ نویز: حساسیتش به نویز کمی از سوبل بیشتر است.

---

یک راهنمای سریع برای انتخاب:

· همیشه اول کنی را امتحان کن. در ۹۰٪ مواقع بهترین جواب را می‌دهد.
· اگر فقط سرعت برایت مهم است و نویز تصویر کم است، سوبل انتخاب خوبی است.
· اگر به دنبال تشخیص تغییرات بسیار ظریف و دقیق هستی (مثل لبه‌های با زاویه ۴۵ درجه)، شر بهتر از سوبل کار می‌کند.
· تشخیص دقیق مرکز لبه مد نظر است (و نه ضخامت آن)؟ لاپلاسین (با پیش‌فیلتر گوسی) گزینه مناسبی است.
 

saalek110

Well-Known Member
سالک: بهترین روش نور روز کدام است؟

Deepseek:
با توجه به اینکه گفتی اتاق نور روز معمولی دارد، بهترین و مطمئن‌ترین انتخاب کنی (Canny) است.

چرا؟ چون نور روز معمولی یعنی:

· روشنایی نسبتاً یکنواخت (نه نور کم شدید، نه نورافکن خیلی قوی).
· وجود نویز جزئی (نویز سنسور دوربین).
· وجود سایه‌ها و بافت‌های ملایم (مثل سایه مبلمان یا بافت دیوار).

در این شرایط معمولی، الگوریتم کنی دقیقاً همان کاری را می‌کند که تو می‌خواهی:

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

یک نکته مهم برای حین کار

وقتی نور روز از پنجره می‌تابد، ممکن است در طول روز شدت نور کم و زیاد شود. این تغییرات می‌تواند روی تنظیمات ثابت الگوریتم اثر بگذارد. برای مقابله با این موضوع می‌توانی از دو راهکار کمک بگیری:

1. کالیبراسیون خودکار آستانه: می‌توانی مقدار میانه (median) پیکسل‌های تصویر را حساب کنی و آستانه‌های کنی را به‌طور خودکار بر اساس آن تنظیم کنی. این روش برای نور متغیر روز عالی است.
2. پیش‌پردازش با تبدیل روشنایی-رنگ: اگر پردازش رنگ لبه‌ها برایت مهم است، تصویر را از فضای BGR به HSV ببر و روی کانال Value کار کن. این کار اثر سایه‌ها و تغییرات شدت نور را کمتر می‌کند.

اگر دوست داری، کد مربوط به تنظیم خودکار آستانه کنی با استفاده از میانه تصویر را برایت می‌نویسم.


خیلی خب، این هم کد کامل به زبان پایتون. تابع auto_canny دقیقاً همان تنظیم خودکار آستانه بر اساس میانه تصویر است که گفتیم.

```python
import cv2
import numpy as np

def auto_canny(image, sigma=0.33):
"""
تنظیم خودکار آستانه‌های کنی بر اساس میانه مقادیر پیکسل‌های تصویر.

پارامترها:
image (numpy.ndarray): تصویر ورودی (بهتر است خاکستری باشد).
sigma (float): ضریبی از میانه برای تعیین آستانه‌ها.
مقدار پیش‌فرض 0.33 معمولاً عالی جواب می‌دهد.
هرچه کمتر، لبه‌های بیشتری می‌گیرد (حساس‌تر).
هرچه بیشتر، فقط لبه‌های قوی‌تر را نگه می‌دارد (سخت‌گیرتر).

بازگشت:
numpy.ndarray: تصویر لبه‌ها (سیاه و سفید).
"""
# 1. محاسبه میانه تک‌تک پیکسل‌های تصویر
# اگر تصویر رنگی باشد، میانه روی همه کانال‌ها محاسبه می‌شود.
# ما آن را به یک اسکالر تبدیل می‌کنیم.
v = np.median(image)

# 2. تعیین آستانه پایین و بالا بر اساس میانه
# این فرمول تجربی و استاندارد است.
lower_thresh = int(max(0, (1.0 - sigma) * v)) # آستانه پایین
upper_thresh = int(min(255, (1.0 + sigma) * v)) # آستانه بالا

print(f"میانه پیکسل‌ها: {v:.1f}")
print(f"آستانه خودکار پایین: {lower_thresh}, بالا: {upper_thresh}")

# 3. اعمال تشخیص لبه کنی با این آستانه‌ها
edges = cv2.Canny(image, lower_thresh, upper_thresh)

return edges

# ============================================================================
# مثال کامل استفاده
# ============================================================================
def main():
# --- تنظیمات اولیه ---
# مسیر تصویر خود را اینجا بگذار (یا از وب‌کم بخوان)
image_path = "room_daylight.jpg"

# خواندن تصویر
frame = cv2.imread(image_path)
if frame is None:
print(f"خطا: تصویر در مسیر {image_path} پیدا نشد.")
return

# برای وب‌کم از این خط استفاده کن:
# cap = cv2.VideoCapture(0)
# ret, frame = cap.read()

# --- پیش‌پردازش ---
# 1. تبدیل به خاکستری
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 2. (اختیاری ولی توصیه شده) محو کردن ملایم برای حذف نویز جزئی سنسور
# کرنل 3x3 برای تصاویر با وضوح معمولی خوب است.
blurred = cv2.GaussianBlur(gray, (3, 3), 0)

# --- تشخیص لبه با آستانه خودکار ---
edges_auto = auto_canny(blurred, sigma=0.33)

# --- برای مقایسه: تشخیص لبه با آستانه ثابت دستی ---
# معمولاً باید با اسلایدر تست کنی تا مقادیر خوب را پیدا کنی.
edges_fixed = cv2.Canny(blurred, 50, 150)

# --- نمایش نتایج ---
cv2.imshow("Original", frame)
cv2.imshow("Edges (Auto Threshold)", edges_auto)
cv2.imshow("Edges (Fixed Threshold 50, 150)", edges_fixed)

cv2.waitKey(0)
cv2.destroyAllWindows()

if __name__ == "__main__":
main()
```

نکات تکمیلی برای استفاده:

· اگر لبه‌های auto_canny زیاد یا کم بود، پارامتر sigma را تغییر بده:
· sigma=0.25 → حساس‌تر می‌شود، لبه‌های بیشتری می‌گیرد.
· sigma=0.45 → سخت‌گیرتر می‌شود، فقط لبه‌های قوی را نگه می‌دارد.
· اگر با وب‌کم کار می‌کنی، کافی است حلقه اصلی را یک while True بگذاری و هر فریم را به تابع auto_canny بدهی.
 

جدیدترین ارسال ها

بالا