از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
آستانه تطبیقی OpenCV در پایتون با ()cv2.adaptiveThreshold
سرفصلهای مطلب
معرفی
Thresholding یک تکنیک ساده و کارآمد برای انجام تقسیم بندی اولیه در یک تصویر و باینریزه کردن آن (تبدیل آن به یک تصویر باینری) است که در آن پیکسل ها یا 0
یا 1
(یا 255
اگر از اعداد صحیح برای نشان دادن آنها استفاده می کنید).
به طور معمول، میتوانید از آستانهگذاری برای انجام بخشبندی ساده پسزمینه-پیشزمینه در یک تصویر استفاده کنید، و به انواع مختلف خلاصه میشود. روی یک تکنیک ساده برای هر پیکسل:
if pixel_value > threshold:
pixel_value = MAX
else:
pixel_value = 0
آستانه ساده مشکلات آشکاری دارد و نیاز به ورودی نسبتاً بکر دارد، که آن را برای بسیاری از موارد استفاده عملی نمی کند. متخلف اصلی یک آستانه جهانی است که برای کل تصویر اعمال می شود، در حالی که تصاویر به ندرت به اندازه کافی یکنواخت هستند تا آستانه های پتویی کار کنند، مگر اینکه مصنوعی باشند.
یک آستانه جهانی به خوبی کار خواهد کرد روی جدا کردن شخصیت ها در یک کتاب سیاه و سفید، روی صفحات اسکن شده یک آستانه جهانی به احتمال زیاد شکست خواهد خورد روی عکس گوشی از همین page، از آنجایی که شرایط نور ممکن است بین بخشهای مختلف متغیر باشد page، یک نقطه برش جهانی را به داده های واقعی بسیار حساس می کند.
برای مبارزه با این – ما می توانیم استخدام کنیم محلی آستانه ها، با استفاده از تکنیکی به نام آستانه تطبیقی. بهجای اینکه تمام قسمتهای تصویر را با یک قانون رفتار کنیم، میتوانیم آستانه را برای هر یک تغییر دهیم محلی با کسی که برای آن مناسب به نظر می رسد. این باعث می شود که آستانه تا حدودی نسبت به تغییرات نور، نویز و سایر عوامل تغییر نکند. در حالی که بسیار مفیدتر از آستانه جهانی است، آستانه گذاری به خودی خود یک تکنیک محدود و سفت و سخت است و به جای تقسیم بندی، برای کمک به پیش پردازش تصویر (به خصوص زمانی که نوبت به شناسایی تصاویر برای دور ریختن می شود) بهتر است.
برای برنامههای ظریفتر که به زمینه نیاز دارند، بهتر است از تکنیکهای پیشرفتهتر، از جمله یادگیری عمیق، که منجر به پیشرفتهای اخیر در بینایی رایانه شده است، استفاده کنید.
آستانه تطبیقی با OpenCV
بیایید در یک تصویر با شرایط نوری متغیر بارگذاری کنیم، جایی که یک قسمت از تصویر در فوکوس بیشتری نسبت به قسمت دیگر قرار دارد و عکس از زاویه گرفته شده است. عکسی که من از هارولد مک گی گرفتم “در مورد غذا و آشپزی” عالی خدمت خواهد کرد!
img = cv2.imread('book.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
اکنون، با استفاده از آستانه معمولی، میتوانیم حروف را از پسزمینه جدا کنیم، زیرا تفاوت رنگ واضحی بین آنها وجود دارد. تمام رنگ های کاغذی به عنوان پس زمینه در نظر گرفته می شوند. از آنجایی که ما واقعاً نمیدانیم آستانه چقدر باید باشد – بیایید روش Otsu را برای یافتن یک مقدار خوب اعمال کنیم، پیشبینی میکنیم که تصویر تا حدودی دو وجهی است (عمدتاً دو رنگ بر آن غالب هستند):
img = cv2.imread('book.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
ret, mask = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
print(f'Threshold: {ret}')
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax(0).imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax(1).imshow(cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
بیایید نگاهی به نتیجه بیاندازیم:
آخ. قسمت سمت چپ متن عمدتاً محو شده است، سایه اطراف ناودان کاملاً بخشی از تصویر را خورده است و متن بیش از حد اشباع شده است! این یک تصویر “در طبیعت” است و قوانین کلی مانند آستانه جهانی به خوبی کار نمی کنند. آستانه چقدر باید باشد؟ بستگی دارد روی بخشی از تصویر!
را cv2.adaptiveThreshold()
روش به ما امکان می دهد دقیقاً این کار را انجام دهیم:
cv2.adaptiveThreshold(img,
max_value,
adaptive_method,
threshold_method,
block_size,
C)
را adaptive_method
می تواند باشد cv2.ADAPTIVE_THRESH_MEAN_C
یا cv2.ADAPTIVE_THRESH_GAUSSIAN_C
، جایی که C
آخرین استدلالی است که شما تعیین کرده اید. هر دوی این روش ها آستانه را با توجه به همسایگان پیکسل مورد نظر محاسبه می کنند، جایی که block_size
تعداد همسایه هایی را که باید در نظر گرفته شود (مساحت محله) را دیکته می کند.
ADAPTIVE_THRESH_MEAN_C
میانگین همسایگان را می گیرد و کسر می کندC
، در حالی کهADAPTIVE_THRESH_GAUSSIAN_C
جمع وزنی گاوسی همسایگان را می گیرد و کسر می کندC
.
همچنین به شما امکان می دهد یک استراتژی باینریزه سازی تنظیم کنید، اما محدود به THRESH_BINARY
و THRESH_BINARY_INV
، و تغییر بین آنها به طور موثر آنچه “پس زمینه” و آنچه “پیش زمینه” است تغییر می دهد.
این روش فقط ماسک را برای تصویر برمیگرداند – نه کد بازگشتی و ماسک. بیایید با استفاده از آستانه تطبیقی، کاراکترها را در همان تصویر قبلی تقسیم بندی کنیم:
img = cv2.imread('book.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
mask = cv2.adaptiveThreshold(blurred,
255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,
31,
10)
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax(0).imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax(1).imshow(cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
plt.tight_layout()
این منجر به یک تصویر بسیار تمیزتر می شود:
توجه داشته باشید: را block_size
آرگومان باید یک عدد ناهموار باشد.
به همین ترتیب، می توانیم آستانه گاوسی را اعمال کنیم:
mask = cv2.adaptiveThreshold(blurred,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
31,
10)
که در پایان یک تصویر بسیار رضایت بخش نیز ایجاد می کند:
هر دو اندازه بلوک (منطقه همسایه) و C
فراپارامترهایی برای تنظیم در اینجا هستند. مقادیر مختلف را امتحان کنید و بهترین را انتخاب کنید روی تصویر شما به طور کلی، آستانه گاوسی حساسیت کمتری نسبت به نویز دارد و تصاویر کمی تیره تر و تمیزتر ایجاد می کند، اما این متفاوت است و بستگی دارد. روی ورودی.
محدودیت های آستانه تطبیقی
با آستانه تطبیقی، ما توانستیم از محدودیت فراگیر آستانه اجتناب کنیم، اما هنوز هم نسبتاً سفت و سخت است و برای ورودی های رنگارنگ عالی کار نمی کند. به عنوان مثال، اگر تصویری از قیچی و یک کیت کوچک با رنگهای متفاوت بارگذاری کنیم، حتی آستانه تطبیقی نیز با مشکلاتی در تقسیمبندی درست آن، با مشخص شدن برخی ویژگیهای تاریک، اما بدون در نظر گرفتن کل اشیاء، با مشکلاتی مواجه خواهد شد:
اگر اندازه بلوک و C
، میتوانیم وصلههای بزرگتر را به عنوان بخشی از یک شی در نظر بگیریم، اما سپس با ایجاد اندازههای همسایه با مشکلاتی مواجه شویم. بیش از حد جهانی، بازگشت به همان مسائل کلی در مورد آستانه جهانی:
نتیجه
در سالهای اخیر، تقسیمبندی باینری (مانند کاری که در اینجا انجام دادیم) و تقسیمبندی چند برچسبی (جایی که میتوانید تعداد دلخواه کلاسها را کدگذاری کنید) با موفقیت با شبکههای یادگیری عمیق مدلسازی شدهاند که بسیار قدرتمندتر و انعطافپذیرتر هستند. علاوه بر این، آنها می توانند زمینه جهانی و محلی را در تصاویری که در حال تقسیم بندی هستند رمزگذاری کنند. نقطه ضعف این است – برای آموزش آنها به داده ها و همچنین زمان و تخصص نیاز دارید.
برای روی- the-fly، آستانه ساده، می توانید از OpenCV استفاده کنید و با استفاده از آستانه تطبیقی به جای استراتژی های آستانه جهانی، با برخی از محدودیت ها مبارزه کنید. برای تقسیم بندی دقیق و در سطح تولید، باید از شبکه های عصبی استفاده کنید.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-03 07:59:04