⚡ خلاصه سریع — اصل کاریها
اینها مهمترین چیزهایی هستن که اگه هیچی ندونی، فقط اینا رو بدونی کافیه:
- نکته ۱: تصویر برای کامپیوتر چیزی نیست جز یک آرایه سهبعدی از اعداد (ماتریس پیکسلها). بینایی ماشین یعنی یاد گرفتن کار با این اعداد.
- نکته ۲: در دنیای بینایی ماشین، OpenCV پادشاه میکند! این کتابخانه بهینهترین و سریعترین ابزار برای پردازش تصویر در پایتون است.
- نکته ۳: OpenCV رنگها را به ترتیب BGR (آبی، سبز، قرمز) میخواند، نه RGB! این بزرگترین تلهی مبتدیهاست.
- نکته ۴: ۸۰٪ کار بینایی ماشین، "پیشپردازش" (Pre-processing) است: خاکستری کردن، نویزگیری، آستانهگذاری و پیدا کردن لبهها.
- نکته ۵: برای کارهای پیشرفته مثل تشخیص چهره یا شیء، ترکیب OpenCV و مدلهای یادگیری عمیق (مثل YOLO یا MediaPipe) بهترین نتیجه را میدهد.
۳ اشتباه رایج:
- فراموش کردن دستور
cv2.waitKey(0)بعد ازcv2.imshow()(باعث فریز شدن و کرش کردن پنجره تصویر میشود). - استفاده از حلقههای
forدر پایتون برای پیمایش پیکسلها (باعث کندی شدید میشود؛ باید از عملیات ماتریسی NumPy استفاده کرد). - قاطی کردن رنگها هنگام استفاده از OpenCV و Matplotlib در کنار هم (یکی BGR است، دیگری RGB).
اگر فقط ۵ دقیقه وقت داری:
- کتابخانهها را نصب کن:
pip install opencv-python numpy matplotlib - یک تصویر را لود کن:
img = cv2.imread('photo.jpg') - آن را نمایش بده:
cv2.imshow('Image', img)و بعدcv2.waitKey(0)را صدا بزن. - تصویر را خاکستری کن:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - قبل از بستن برنامه حتماً
cv2.destroyAllWindows()را فراخوانی کن.
۱. مقدمه
سلام! به دنیای بینایی ماشین (Computer Vision) خوش اومدی. ببین، کامپیوترها چشم ندارن. اگه به یک انسان عکس یک گربه نشونی بدی، فوراً میفهمه گربه است. اما کامپیوتر فقط چند میلیون عدد ۰ و ۱ میبینه.
"بینایی ماشین" یعنی هنر و علم آموزش دادن به کامپیوتر برای اینکه از روی این اعداد (پیکسلها)، مفهوم رو درک کنه. "مثلاً توی این تصویر گربه هست" یا "خطوط این خط خالیه دستخط رو بخون".
در پایتون، ما با قدرتمندترین ابزار یعنی OpenCV (اوپنسیوی) کار میکنیم که در اصل به زبان C++ نوشته شده و سرعت فوقالعادهای داره.
۲. پیشنیازها
برای اینکه با من پیش بیای، به این چیزا نیاز داری:
- پایتون پایه: بلد باشی متغیر، لیست، دیکشنری، حلقه (
for/while) و تعریف تابع چیه. - کتابخانه NumPy: بینایی ماشین ۱۰۰٪ به NumPy وابسته است. تصویر در پایتون یک آرایه (Array) از NumPy است.
- یک ویرایشگر: VSCode یا PyCharm.
- حوصله: چون مسیر صفر تا صده و کلی مفهوم جدید داره.
۳. نصب و راهاندازی
بهترین کار اینه که برای پروژههات یک "محیط مجازی" (Virtual Environment) بسازی تا پکیجها قاطی نشن.
# ساخت محیط مجازی
python -m venv cv_env
# فعالسازی (در ویندوز)
cv_env\Scripts\activate
# فعالسازی (در مک و لینوکس)
source cv_env/bin/activate
# نصب کتابخانههای مورد نیاز
pip install opencv-python numpy matplotlib
نکته: پکیج opencv-python فقط توابع اصلی رو داره. اگه بخوای قابلیتهای غیر رایگان (مثل بعضی الگوریتمهای پتنس) رو داشته باشی باید opencv-contrib-python رو نصب کنی.
۴. مفاهیم پایه
بذار خیلی ساده شروع کنیم:
- پیکسل (Pixel): تصویر از مربعهای خیلی ریز به نام پیکسل تشکیل شده. هر پیکسل یک عدد است.
- تصویر خاکستری (Grayscale): فقط شدت نور رو نشون میده. از ۰ (سیاه کامل) تا ۲۵۵ (سفید کامل). یک ماتریس ۲ بعدی است.
- تصویر رنگی (Color): از ترکیب ۳ رنگ قرمز، سبز و آبی (RGB) ساخته میشه. هر پیکسل ۳ عدد داره. پس یک ماتریس ۳ بعدی است (ارتفاع × عرض × ۳ کانال رنگ).
- BGR در برابر RGB: تو OpenCV ترتیب رنگها آبی، سبز، قرمز (BGR) است. اما تو سایر کتابخانهها مثل Matplotlib قرمز، سبز، آبی (RGB) است. این موضوع خیلی مهمه!
۵. مثالهای کد ساده
بیایید اولین تصویر خودمون رو بخونیم و نمایش بدیم:
import cv2
import numpy as np
# خواندن تصویر
img = cv2.imread('my_photo.jpg')
# بررسی اینکه آیا تصویر درست خوانده شده؟
if img is None:
print("خطا: تصویر پیدا نشد! مسیر فایل رو چک کن.")
else:
# نمایش تصویر در یک پنجره
cv2.imshow('My First Image', img)
# صبر کردن تا کاربر هر کلیدی رو فشار بده (۰ یعنی بینهایت صبر)
cv2.waitKey(0)
# بستن تمام پنجرههای OpenCV
cv2.destroyAllWindows()
حالا تصویر رو خاکستری کنیم و یک خط بکشیم:
import cv2
img = cv2.imread('my_photo.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# کشیدن یک خط روی تصویر رنگی اصلی
# خط از مختصات (0,0) تا (500,500) با رنگ آبی (255,0,0 در BGR) و ضخامت 5
cv2.line(img, (0,0), (500,500), (255,0,0), 5)
cv2.imshow('Gray Image', gray_img)
cv2.imshow('Line Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
۶. مثال واقعی و کاربردی
بذار یک پروژه واقعی بسازیم: تشخیص چهره در تصویر وبکم در لحظه (Real-time).
OpenCV یک مدل از پیش آموزش دیده به نام Haar Cascades داره که برای پیدا کردن چهره عالیه.
import cv2
# لود کردن مدل از پیش آموزش دیده برای تشخیص چهره (همراه با OpenCV نصب میشه)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
# روشن کردن دوربین (عدد 0 یعنی دوربین پیشفرض)
cap = cv2.VideoCapture(0)
while True:
# خواندن فریم از دوربین
ret, frame = cap.read()
if not ret:
print("نمیتونم دوربین رو باز کنم!")
break
# مدلهای قدیمی مثل Haar روی تصاویر خاکستری بهتر کار میکنند
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# پیدا کردن چهرهها
# scaleFactor: چقدر تصویر کوچک بشه در هر مرحله
# minNeighbors: چند همسایه برای تایید یک چهره لازمه (عدد بالاتر = دقت بالاتر، تشخیص کمتر)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
# کشیدن مستطیل دور هر چهره
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # رنگ سبز
# نمایش فریم
cv2.imshow('Face Detection', frame)
# اگه کلید 'q' روی صفحهکلید فشار داده شد، خارج شو
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# آزادسازی منابع
cap.release()
cv2.destroyAllWindows()
۷. مباحث پیشرفته
وقتی پایه رو یاد گرفتی، وارد دنیای مدرن میشیم:
- تعهیه داده (Data Annotation): برای ساخت مدل خودت باید روی تصاویر با ابزارهایی مثل LabelImg برچسب بزنی.
- یادگیری عمیق (Deep Learning): Haar Cascades قدیمی شدن. امروزه از شبکههای عصبی پیچشی (CNN) استفاده میشه.
- مدلهای آماده پیشرفته:
- YOLO (You Only Look Once): سریعترین مدل برای تشخیص چندین شیء در زمان واقعی.
- MediaPipe (گوگل): عالی برای تشخیص دست، بدن، و چهره با دقت میلیثانیهای.
- Segmentation (مثل SAM متا): پیدا کردن دقیق مرز پیکسلی اشیاء (نه فقط مستطیل دور آنها).
- تقاطع بینایی ماشین و NLP: پروژههایی مثل BLIP که تصویر میگیرن و متن توصیفکننده اون رو تولید میکنن.
۸. اشتباهات رایج
- فراموش کردن
waitKey: پنجره OpenCV بدون این دستور اصلا پردازش رویدادهای سیستمعامل رو انجام نمیده و هنگ میکنه. - فهم اشتباه از ماتریس NumPy: در OpenCV مختصات پیکسل به صورت
(y, x)یعنی (ردیف، ستون) است، نه(x, y). خیلیها اینجا اشتباه میکنن. برای دسترسی به پیکسل تصویر:img[y, x]. - استفاده از
cv2.imreadبا مسیرهای دارای حروف فارسی یا فاصله: OpenCV روی ویندوز با مسیرهای یونیکد (مثل حروف فارسی) مشکل داره وNoneبرمیگردونه. همیشه مسیر رو انگلیسی بنویس یا باnumpyلود کن. - عدم توجه به نور پردازی: کیفیت نور در تصویر ۱۰۰ برابر الگوریتم مهمتره. یک تصویر تاریک رو هیچ الگوریتمی نمیتونه خوب پردازش کنه.
۹. بهترین روشها (Best Practices)
- عملیات برداری (Vectorization): هیچوقت با دو تا حلقه
forتو در تو روی تصویر پیمایش نکن. از توابع داخلی OpenCV یا NumPy استفاده کن. - تغییر سایز پیش از پردازش: اگه به دقت پیکسلی نیاز نداری، تصویر رو قبل از پردازش با
cv2.resizeکوچک کن تا سرعت ۱۰ برابر بشه. - مدیریت حافظه: در حلقههای پردازش ویدیو، متغیرهایی که دیگه لازم نداری رو
delکن یا بذار garbage collection پاکشون کنه. - استثناها (Exceptions): همیشه بعد از
cv2.VideoCaptureمقدارretرو چک کن تا مطمئن بشی دوربین قطع نشده.
۱۰. منابع و ادامه مسیر
- سایت رسمی OpenCV: (docs.opencv.org) بهترین مرجع مستندات.
- کتاب Practical Python and OpenCV: قدم به قدم و عالی برای مبتدیها.
- PyImageSearch: وبلاگ آدرین رزباک، معدن پروژههای آماده CV.
- روی GitHub: کلماتی مثل
computer-visionوopencvرو سرچ کن.
۱۱. مرجع کامل توابع و متدها (API Deep Dive)
در این بخش، دو تا از مهمترین و پراستفادهترین متدها رو موشکافی میکنیم.
متد ۱: cv2.imread()
این تابع برای بارگذاری تصویر از دیسک به حافظه (به صورت آرایه NumPy) استفاده میشود.
- امضا (Signature):
cv2.imread(filename[, flags]) -> retval - پارامترها:
| نام پارامتر | نوع داده | توضیح |
|---|---|---|
filename |
str |
مسیر فایل تصویر در دیسک. |
flags |
int |
نحوه خواندن تصویر (پیشفرض: رنگی). |
Return (خروجی): یک آرایه NumPy (اگر تصویر پیدا بشه) یا
None(اگه مسیر اشتباه باشه).گامبهگام کارکرد:
- بررسی میکند آیا فایل در مسیر مشخص شده وجود دارد؟
- هدر فایل تصویر رو میخونه تا فرمت (JPG, PNG) رو بفهمه.
- دیتای تصویر رو دیکود میکنه و به ماتریس NumPy تبدیل میکنه.
- بر اساس
flags، تصویر رو پردازش و برمیگردونه.
۲ مثال:
# مثال ۱: خواندن تصویر رنگی (پیشفرض)
img_color = cv2.imread('pic.jpg', cv2.IMREAD_COLOR) # یا عدد 1
# مثال ۲: خواندن به صورت سیاه و سفید (خاکستری) برای صرفهجویی در حافظه
img_gray = cv2.imread('pic.jpg', cv2.IMREAD_GRAYSCALE) # یا عدد 0
جدول Exceptions:
از آنجا که این تابع در پایتون به صورت wrapper نوشته شده، ارور پایتونی نمیده، بلکه در صورت شکستNoneبرمیگرداند. بنابراین به جایtry/exceptباید ازif img is None:استفاده کرد.Overloadها (حالتهای مختلف خواندن):
cv2.IMREAD_COLOR(1): تصویر رنگی (BGR).cv2.IMREAD_GRAYSCALE(0): تصویر تککاناله خاکستری.cv2.IMREAD_UNCHANGED(-1): تصویر با کانال آلفا (شفافیت) اگه داشته باشه.
اشتباهات: فراموش کردن اعداد منفی و مثبت ۱. در نسخههای قدیمی از اعداد
-1, 0, 1استفاده میشد.متدهای مرتبط:
cv2.imwrite()(برای ذخیره تصویر).
متد ۲: cv2.Canny()
الگوریتم Canny یکی از بهترین روشها برای تشخیص لبهها در تصویر است.
- امضا (Signature):
cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) -> edges - پارامترها:
| نام پارامتر | نوع داده | توضیح |
|---|---|---|
image |
numpy.ndarray |
تصویر ورودی (حتماً خاکستری ۸-بیت). |
threshold1 |
float |
آستانه اول (کم). |
threshold2 |
float |
آستانه دوم (زیاد). |
apertureSize |
int |
سایز فیلتر Sobel برای مشتقگیری (پیشفرض 3). |
L2gradient |
bool |
اگه True باشه از فرمول دقیقتر برای محاسبه گرادیان استفاده میکنه (پیشفرض False). |
Return (خروجی): یک تصویر دودویی (سیاه و سفید خالص) که لبهها سفید و بقیه جاهای تصویر سیاه است.
گامبهگام کارکرد:
- نویزگیری: تصویر با فیلتر گوسی تار (Blur) میشه.
- محاسبه گرادیان: با فیلتر Sobel زاویه و شدت لبهها حساب میشه.
- سرکوب غیر-maximum: لبههای ضخیم نازک میشن تا فقط لبههای واقعی باقی بمونن.
- آستانهگذاری هیسترزیس (Hysteresis): پیکسلهای بالای
threshold2لبه حساب میشن. پیکسلهای بینthreshold1وthreshold2فقط اگه به لبههای قطعی متصل باشن نگه داشته میشن. زیرthreshold1حذف میشن.
۲ مثال:
# مثال ۱: تشخیص لبه با آستانههای ساده
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
# مثال ۲: استفاده از L2gradient برای دقت بالاتر
edges_accurate = cv2.Canny(gray, 100, 200, L2gradient=True)
جدول Exceptions:
اگه تصویر ورودی رنگی (۳ کاناله) باشه، ارورcv2.error: OpenCV(4.x.x) ... (-215:Assertion failed) size.width > 0 && size.height > 0 in function 'cv::Canny'میده.اشتباهات: مقادیر آستانهها رو خیلی پایین در نظر گرفتن. اگه پایین باشن، هر نویزی به عنوان لبه تشخیص داده میشه. قانون تجربی:
threshold2سه برابرthreshold1باشه.متدهای مرتبط:
cv2.Sobel(),cv2.Laplacian().
۱۲. مقایسه کلاسها/توابع مشابه
بسیاری از مبتدیها نمیدونن کی از چه روشی برای فیلتر کردن استفاده کنن. این جدول بهت کمک میکنه:
| ویژگی | cv2.filter2D |
cv2.GaussianBlur |
cv2.medianBlur |
|---|---|---|---|
| کاربرد اصلی | پیچیدن (Convolve) یک فیلتر سفارشی روی تصویر | تار کردن تصویر با وزندهی گوسی | حذف نویزهای نمک و فلفلی (دانهدانه) |
| نحوه کار | شما یک ماتریس (Kernel) میسازید و میگید چطوری پیکسلهای همسایه ترکیب بشن. | ماتریس گوسی از پیش تعریف شده رو پیچیده میکنه تا تصویر نرم بشه. | مقدار میانه (Median) تمام پیکسلهای همسایه رو میذاره جای پیکسل فعلی. |
| مزیت | انعطافپذیری کامل برای ساخت فیلتر شارپن، امبوس و... | سرعت بالا، طبیعی بودن تار شدن (مثل لنز دوربین) | فوقالعاده در حذف نویزهای شدید دونگرهای بدون خراب کردن لبهها. |
| نقطه ضعف | نیازمند دانش ریاضی برای ساخت Kernel مناسب | لبههای تصویر رو تار میکنه | سرعتش نسبت به فیلتر گوسی کمتره |
| چه زمانی استفاده کنیم؟ | وقتی الگوریتمی برای تغییر تصویر داری که جایش توی OpenCV نیست. | قبل از تشخیص لبه (Canny) یا کاهش نویز پیشفرض. | وقتی عکس نویز دانهدانه (Salt and Pepper) داره. |
۱۳. سناریوهای واقعی
- خودکامیاب (Self-Checkout) در فروشگاهها: دوربین کالا رو میبینه، با الگوریتمهای تشخیص شیء کد محصول رو پیدا میکنه و قیمت رو استخراج میکنه.
- بیمارییابی گیاهی: پهپاد مزرعه رو عکس میگیره، با پردازش تصویر رنگ برگها رو بررسی میکنه و قسمتهای بیمار رو تشخیص میده.
- تشخیص پلاک خودرو: دوربین راهدارخانه عکس ماشین رو میگیره، پلاک Crop میشه، سپس با OCR متن پلاک خونده میشه.
- بیمارییابی پزشکی (MRI): پردازش تصاویر MRI مغز برای پیدا کردن خودکار تومورها.
۱۴. کارایی و Performance
در پردازش تصویر، میلیثانیهها مهمن:
- پرهیز از
forدر پایتون: پیمایش یک تصویر ۱۰۸۰p (حدود ۲ میلیون پیکسل) باforدر پایتون ۵ ثانیه طول میکشه. با توابع OpenCV زیر ۱۰ میلیثانیه! - کاهش سایز (Downscaling): اگه میخوای فقط چهره آدم رو پیدا کنی، تصویر رو قبل از پردازش به ۶۴۰x۴۸۰ تغییر بده. نیازی به ۴K نیست.
- استفاده از GPU: اگه با ویدیوهای زنده کار میکنی، از مدلهایی استفاده کن که پشتیبانی CUDA دارن تا پردازش روی کارت گرافیک انجام بشه.
- تبدیل نوع داده: تصاویر معمولا
uint8(0 تا 255) هستن. اگه کارت گرافیک دارید و متغیرها رو تعریف میکنید، ازfloat32فقط اگه واقعا به اعشاری بودن نیاز داشتید استفاده کنید، چون ۴ برابر حافظه و زمان مصرف میکنه.
۱۵. چکلیست یادگیری
برای مطمئن شدن از یادگیری، این چکلیست رو تیک بزن:
- میتونم با
imreadوimshowیک عکس رو لود و نمایش بدم. - تفاوت تصویر BGR و RGB رو میدونم و میتونم تبدیلشون کنم.
- میتونم مستطیل، خط و متن روی تصویر رسم کنم.
- میدونم چطور یک عکس رو با
cv2.GaussianBlurتار کنم. - میتونم با
cv2.Cannyلبههای یه عکس رو پیدا کنم. - پروژه تشخیص چهره از روی وبکم خودم رو انجام دادم و کار کرد.
- میدونم چطور با
cv2.VideoCaptureویدیو رو فریم به فریم بخونم. - اگه با ارور
None type objectروبرو شدم، میدونم مشکل از مسیر فایله.
به نکته آخر گوش بده: بینایی ماشین ترکیبی از هنر و ریاضیه. زیاد باهاش بازی کن، کدهای عجیب غریب بنویس، فیلترها رو امتحان کن و ترس از داشبورد اعداد (NumPy arrays) رو از دلت دربیار. موفق باشی!