Hesam Mohebi
Hesam Mohebi
خواندن ۵ دقیقه·۲ سال پیش

معرفی کتابخانه OpenCv بخش ۵

توی این پست می خوام مفهوم آستانه گذاری (thresholding) با استفاده از توابع threshold و inRange رو یه توضیحی بدم .

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

اول از تابع threshold شروع می کنم . به کمک این تابع ما میتونیم به پنج طریق آستانه گذاری کنیم ٬ برای درک بهتر مطلب فرض کنید ما یه تصویر ورودی داریم که شدت مقادیر اون به شکل زیر هست و خط افقی آبی هم آستانه ما هستش .

این تصویرو من یه توضیح اضافی بدم فرض کنید که ما همه پیکسل های تصویر رو توی محور x نمودار داریم یعنی به جای اینکه پیکسل های مختصات دو بعدی داشته باشند همشون رو ما به صف کردیم و توی محور x قرار دادیم و شدت پیسکل هم که مقدار y میشه میزان پر رنگی و کم رنگی پیکسل هست ( اگه یادتون باشه توی پست های قبلی گفتم که ما میتونیم یه تصویر رو فقط رو کانال خاکستری داشته باشیم که ۰ میشه سیاه و ۲۵۵ میشه سفید یا اینکه روی کانال BGR که رنگ های آبی و سبز و قرمز هست که هر کدوم از بازه ۰ تا ۲۵۵ متغییره حالا اینجا ما فقط روی کانال خاکستری کار می کنیم ).

آستانه باینری (Threshold Binary)

توی این روش آستانه گذاریم ما میگیم هرچی پیکسل شدتش از آستانه ما بیشتر بود ۲۵۵ باشه و هرچی پایین تر بود صفر باشه فورمول ریاضیش هم این شکلی میشه :‌

و طبق این فورمول خروجی نمودار بالا همچین چیزی میشه :‌

و اتفاقی که توی تصویر می افته اینه که پیسکل های تصویر یا سیاه هست یا سفید .

به عنوان مثال اگه تصویر ورودیمون جناب شرک باشه :

اول کار از کانال رنگی میبریمش خاکستری :‌

بعدش آستانمون رو تعیین می کنیم که توی کد به این شکل میشه :‌

_, dst = cv.threshold(src_gray, 120, 255, 0)

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

و خروجی تصویر به این شکل میشه :

آستانه باینری، معکوس(Threshold Binary, Inverted)

همون آستانه باینریه فقط اومدیم برعکس کردیم یعنی وقتی از آستانه بیشتر بود صفر باشه کمتر بود 255 .

تصویری هم که میگیریم این شکلی میشه :‌

_, dst = cv.threshold(src_gray, 120, 255, 1)

کدشم همونه فقط پارامتر آخر شده یک .

کوتاه کردن (Truncate)

توی این روش هر پیکسلی که شدتش از آستانه بیشتر بود ٬ شدتش برابر میشه با مقدار آستانه :‌

و نمودارشم این شکلی میشه :‌

کدشم همونه فقط پارامتر آخر میشه دو و خروجی تصویر هم این شکلی میشه :‌

آستانه تا صفر (Threshold to Zero)

خب فرقی که این روش با باینری داره اینه که در صورتی که کمتر از آستانه باشه صفر میشه و اگه بیشتر باشه همون مقدار خودشه .

و نمودارشم این شکلی میشه :‌

مثلا یه کاری که با این آستانه میشه کرد اینه که ببینیم روشن ترین یا تاریک ترین نقاط تصویر کجاست یا تو یه مثال پیشرفته تر میشه منبع نور رو تشخیص داد .

تصویر خروجی :‌


آستانه تا صفر معکوس (Threshold to Zero inverted)

اینم مثه همون آستانه دومیه فقط تنها فرقش اینه که به جای اینکه شدت پیکسل های 255 بشه همون مقدای که دارند میمونند .

و تصویر خروجی :‌

خب حالا میریم سره توضیح دادن کد . قبل از اینکه شروع کنم بگم که سورس کد اصلی مال خود سایت opencv بود منتهی من یکم دست بردم توش که تو درک مطلب کمک کنه .

اول کار مثل همیشه با نام و یاد خدا کتابخونه هارو اضافه می کنیم و تصویرو ورودی میگیریم و از کانال رنگی میبریمش کانال خاکستری :

src = cv.imread(&quotshrek.jpg&quot) src = cv.resize(src,(900,450)) # Convert the image to Gray src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

بعدش میایم یه پنجره میسازیم که توش دوتا بار یکی برای تعیین نوع آستانه و یکی دیگه برای مقداری آستانه قرار داره :

cv2.imwrite(&quotgray_shrek.jpg&quot, src_gray) cv.namedWindow(window_name) cv.createTrackbar(trackbar_type, window_name , 3, max_type, Threshold_Demo) # Create Trackbar to choose Threshold value cv.createTrackbar(trackbar_value, window_name , 0, max_value, Threshold_Demo)

بعدش برا اینکه تمیز تر باشه یه تابع میسازیم و کارایی که می خوایم رو توی اون انجام میدیم :‌

def Threshold_Demo(val): #0: Binary #1: Binary Inverted #2: Threshold Truncated #3: Threshold to Zero #4: Threshold to Zero Inverted threshold_type = cv.getTrackbarPos(trackbar_type, window_name) threshold_value = cv.getTrackbarPos(trackbar_value, window_name) _, dst = cv.threshold(src_gray, threshold_value, max_binary_value, threshold_type ) cv.imshow(window_name, dst)

خب اون دوتا خط بعد کامنتا میاد نوع آستانه و مقدارشو توی دوتا متغییر میریزه و بعد با استفاده از تابع threshold میام متغیر هارو جایگذاری می کنیم .

نتیجه نهایی یه ابزار مفیدی میشه واسه فیلتر کردن شدت روشنایی و کارای دیگه اینم کد کاملش :‌

from __future__ import print_function import cv2 import cv2 as cv max_value = 255 max_type = 4 max_binary_value = 255 trackbar_type = 'Type: \n 0: Binary \n 1: Binary Inverted \n 2: Truncate \n 3: To Zero \n 4: To Zero Inverted' trackbar_value = 'Value' window_name = 'Threshold Demo' def Threshold_Demo(val): #0: Binary #1: Binary Inverted #2: Threshold Truncated #3: Threshold to Zero #4: Threshold to Zero Inverted threshold_type = cv.getTrackbarPos(trackbar_type, window_name) threshold_value = cv.getTrackbarPos(trackbar_value, window_name) _, dst = cv.threshold(src_gray, threshold_value, max_binary_value, threshold_type ) cv2.imwrite(&quotbinary.jpg&quot, dst) src = cv.imread(&quotshrek.jpg&quot) src = cv.resize(src,(900,450)) # Convert the image to Gray src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY) cv.namedWindow(window_name) cv.createTrackbar(trackbar_type, window_name , 3, max_type, Threshold_Demo) cv.createTrackbar(trackbar_value, window_name , 0, max_value, Threshold_Demo) Threshold_Demo(0) # Wait until user finishes program cv.waitKey()

خب مثکه پست طولانی شد واسه همین تابع inRange و فیلتر HSV رو میزاریم توی پست بعدی توضیح میدم . امیدوارم مفید بوده باشه و مثل همیشه اگه سوالی داشتید میتونید سرچ کنید .


برنامه نویسیپایتونپردازش تصویرopencvهوش مصنوعی
شاید از این پست‌ها خوشتان بیاید