از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
مقدمه ای بر پردازش تصویر در پایتون با OpenCV
سرفصلهای مطلب
معرفی
در این آموزش قصد داریم یاد بگیریم که چگونه با استفاده از زبان پایتون پردازش تصویر را انجام دهیم. ما قرار نیست خود را به یک کتابخانه یا چارچوب محدود محدود کنیم. با این حال، یکی وجود دارد که ما اغلب از آن استفاده خواهیم کرد، آن CV را باز کنید کتابخانه ما با صحبت کمی در مورد پردازش تصویر شروع می کنیم و سپس حرکت می کنیم روی برای دیدن برنامه ها/سناریوهای مختلف که در آن پردازش تصویر می تواند مفید باشد. بنابراین، بیایید شروع کنیم!
پردازش تصویر چیست؟
مهم است که بدانید پردازش تصویر دقیقاً چیست و چه نقشی در تصویر بزرگتر دارد قبل از اینکه به چگونگی آن بپردازید. پردازش تصویر معمولاً به عنوان “پردازش تصویر دیجیتال” نامیده می شود و دامنه ای که اغلب در آن استفاده می شود “Computer Vision” است. گیج نشوید – ما در مورد هر دوی این اصطلاحات و روش اتصال آنها صحبت خواهیم کرد. هر دو الگوریتم پردازش تصویر و الگوریتم های بینایی کامپیوتری (CV) یک تصویر را به عنوان ورودی می گیرند. با این حال، در پردازش تصویر، خروجی نیز یک است تصویر، در حالی که در بینایی کامپیوتر خروجی می تواند مقداری باشد ویژگی ها / اطلاعات در مورد تصویر.
چرا ما به اون احتیاج داریم؟
دادههایی که ما جمعآوری یا تولید میکنیم عمدتاً دادههای خام هستند، یعنی به دلایل احتمالی برای استفاده مستقیم در برنامهها مناسب نیستند. بنابراین لازم است ابتدا آن را تحلیل کنیم، پیش پردازش های لازم را انجام دهیم و سپس از آن استفاده کنیم.
به عنوان مثال، بیایید فرض کنیم که ما در حال تلاش برای ساختن یک طبقه بندی گربه بودیم. برنامه ما یک تصویر را به عنوان ورودی می گیرد و سپس به ما می گوید که آیا تصویر حاوی گربه است یا خیر. اولین گام برای ساخت این طبقه بندی کننده، جمع آوری صدها عکس گربه است. یکی از مشکلات رایج این است که تمام تصاویری که ما خراشیده ایم اندازه/ابعاد یکسانی ندارند، بنابراین قبل از اینکه آنها را برای آموزش به مدل بفرستیم، باید اندازه/پیش را تغییر اندازه دهیم.process همه آنها به اندازه استاندارد
این تنها یکی از دلایلی است که چرا پردازش تصویر برای هر برنامه بینایی کامپیوتری ضروری است.
پیش نیازها
قبل از ادامه، بیایید آنچه را که باید بدانید تا به راحتی این آموزش را دنبال کنید، بحث کنیم. در مرحله اول، شما باید دانش برنامه نویسی اولیه را در هر زبانی داشته باشید. در مرحله دوم، باید بدانید که یادگیری ماشین چیست و اصول اولیه روش کار آن چیست، زیرا در این مقاله از برخی الگوریتمهای یادگیری ماشین برای پردازش تصویر استفاده خواهیم کرد. به عنوان یک امتیاز، اگر قبل از رفتن با Open CV آشنا شده باشید یا دانش اولیه ای در مورد آن داشته باشید، به شما کمک خواهد کرد روی با این آموزش اما این مورد نیاز نیست.
نکته ای که برای دنبال کردن این آموزش باید حتما بدانید این است که چگونه یک تصویر در حافظه نمایش داده می شود. هر تصویر با مجموعه ای از پیکسل ها نشان داده می شود، یعنی ماتریسی از مقادیر پیکسل. برای یک تصویر در مقیاس خاکستری، مقادیر پیکسل از 0 تا 255 متغیر است و شدت آن پیکسل را نشان می دهد. به عنوان مثال، اگر تصویری با ابعاد 20×20 دارید، آن را با ماتریس 20×20 (مجموعاً مقادیر 400 پیکسل) نشان می دهید.
اگر با یک تصویر رنگی سر و کار دارید، باید بدانید که دارای سه کانال قرمز، سبز و آبی (RGB) است. بنابراین، سه ماتریس از این دست برای یک تصویر وجود دارد.
نصب و راه اندازی
توجه: از آنجایی که ما قصد داریم از OpenCV از طریق پایتون استفاده کنیم، این یک الزام ضمنی است که قبلاً پایتون (نسخه 3) را قبلاً نصب کرده باشید. روی ایستگاه کاری شما
پنجره ها
$ pip install opencv-python
سیستم عامل مک
$ brew install opencv3 --with-contrib --with-python3
لینوکس
$ sudo apt-get install libopencv-dev python-opencv
برای بررسی اینکه آیا نصب شما موفقیت آمیز بوده است یا خیر، دستور زیر را در پوسته پایتون یا خط فرمان خود اجرا کنید:
import cv2
برخی از اصولی که باید بدانید
قبل از اینکه حرکت کنیم روی برای استفاده از پردازش تصویر در یک برنامه، مهم است که ایده ای در مورد اینکه چه نوع عملیاتی در این دسته قرار می گیرند و چگونه آن عملیات را انجام دهیم، به دست آوریم. این عملیات، همراه با سایر عملیات ها، بعدا مورد استفاده قرار خواهند گرفت روی در برنامه های ما پس اجازه بدهید به این کار برسیم.
برای این مقاله از تصویر زیر استفاده خواهیم کرد:
توجه داشته باشید: تصویر برای نمایش در این مقاله کوچک شده است، اما اندازه اصلی مورد استفاده ما در حدود 1180×786 است.
احتمالاً متوجه شده اید که تصویر در حال حاضر رنگی است، یعنی با سه کانال رنگی یعنی قرمز، سبز و آبی نشان داده می شود. ما تصویر را به مقیاس خاکستری تبدیل می کنیم و همچنین تصویر را با استفاده از کد زیر به کانال های جداگانه تقسیم می کنیم.
یافتن جزئیات تصویر
پس از بارگذاری تصویر با imread()
سپس میتوانیم برخی از ویژگیهای ساده آن را بازیابی کنیم، مانند تعداد پیکسلها و ابعاد:
import cv2
img = cv2.imread('rose.jpg')
print("Image Properties")
print("- Number of Pixels: " + str(img.size))
print("- Shape/Dimensions: " + str(img.shape))
خروجی:
Image Properties
- Number of Pixels: 2782440
- Shape/Dimensions: (1180, 786, 3)
تقسیم یک تصویر به کانال های فردی
اکنون تصویر را با استفاده از OpenCV به اجزای قرمز، سبز و آبی تقسیم می کنیم و آنها را نمایش می دهیم:
from google.colab.patches import cv2_imshow
blue, green, red = cv2.split(img)
img_gs = cv2.imread('rose.jpg', cv2.IMREAD_GRAYSCALE)
cv2_imshow(red)
cv2_imshow(blue)
cv2_imshow(green)
cv2_imshow(img_gs)
برای اختصار، ما فقط تصویر خاکستری را نشان می دهیم.
تصویر خاکستری:
آستانه تصویر
مفهوم آستانه بسیار ساده است. همانطور که در بالا در نمایش تصویر مورد بحث قرار گرفت، مقادیر پیکسل می تواند هر مقداری بین 0 تا 255 باشد. فرض کنید می خواهیم یک تصویر را به یک تصویر باینری تبدیل کنیم، یعنی به یک پیکسل مقدار 0 یا 1 اختصاص دهیم. برای انجام این کار، می توانیم این کار را انجام دهیم. آستانه گذاری به عنوان مثال، اگر مقدار آستانه (T) 125 باشد، آنگاه به همه پیکسلهایی با مقادیر بیشتر از 125 مقدار 1 اختصاص داده میشود، و به تمام پیکسلهایی که مقادیر کمتر یا مساوی با آن دارند، مقدار 0 اختصاص مییابد. که از طریق کد برای درک بهتر.
تصویر مورد استفاده برای آستانه گذاری:
import cv2
img = cv2.imread('image.png', 0)
r, threshold = cv2.threshold(img, 125, 255, cv2.THRESH_BINARY)
cv2_imshow(threshold)
خروجی:
همانطور که می بینید، در تصویر حاصل، دو ناحیه ایجاد شده است، یعنی ناحیه سیاه (مقدار پیکسل 0) و ناحیه سفید (مقدار پیکسل 1). معلوم شد، آستانه ای که ما تعیین کردیم درست در وسط تصویر بود، به همین دلیل است که مقادیر سیاه و سفید در آنجا تقسیم می شوند.
برنامه های کاربردی
شماره 1: حذف نویز از یک تصویر
اکنون که ایده اولیه ای در مورد اینکه پردازش تصویر چیست و برای چه مواردی استفاده می شود به دست آورده اید، بیایید جلوتر برویم و با برخی از کاربردهای خاص آن آشنا شویم.
در بیشتر موارد، دادههای خامی که جمعآوری میکنیم دارای نویز هستند، یعنی ویژگیهای ناخواستهای که درک تصویر را سخت میکند. اگرچه می توان از این تصاویر به طور مستقیم برای استخراج ویژگی استفاده کرد، اما دقت الگوریتم به شدت آسیب خواهد دید. به همین دلیل است که پردازش تصویر روی تصویر اعمال می شود قبل از ارسال آن به الگوریتم برای دستیابی به دقت بهتر.
انواع مختلفی از نویز وجود دارد، مانند نویز گوسی، نویز نمک و فلفل، و غیره. در مورد فیلترها نیز گزینه های زیادی وجود دارد، هر کدام از آنها نقاط قوت متفاوتی دارند و از این رو برای نوع خاصی از نویز بهترین هستند.
برای درک درست این موضوع، میخواهیم نویز «نمک و فلفل» را به نسخه خاکستری تصویر رز که در بالا در نظر گرفتیم اضافه کنیم و سپس سعی کنیم آن نویز را با استفاده از فیلترهای مختلف از تصویر پر سر و صدا حذف کنیم و ببینیم کدام یک بهترین است- مناسب برای آن نوع
import numpy as np
def salt_pepper(prob):
row, col = img_gs.shape
s_vs_p = 0.5
output = np.copy(img_gs)
num_salt = np.ceil(prob * img_gs.size * s_vs_p)
coords = (np.random.randint(0, i - 1, int(num_salt))
for i in img_gs.shape)
output(coords) = 1
num_pepper = np.ceil(prob * img_gs.size * (1. - s_vs_p))
coords = (np.random.randint(0, i - 1, int(num_pepper))
for i in img_gs.shape)
output(coords) = 0
cv2_imshow(output)
return output
sp_05 = salt_pepper(0.5)
cv2.imwrite('sp_05.jpg', sp_05)
بسیار خوب، ما نویز را به تصویر گل رز خود اضافه کردهایم، و اکنون به نظر میرسد:
تصویر نویزدار:
اکنون اجازه دهید فیلترهای مختلف را اعمال کنیم روی آن را یادداشت کنید و مشاهدات ما را یادداشت کنید، یعنی اینکه هر فیلتر چقدر نویز را کاهش می دهد.
فیلتر حسابی با هسته تیز کننده
kernel_sharpening = np.array(((-1,-1,-1),
(-1, 9,-1),
(-1,-1,-1)))
print("\n\n--- Effects روی S&P Noise Image with Probability 0.5 ---\n\n")
sharpened_img = cv2.filter2D(sp_05, -1, kernel_sharpening)
cv2_imshow(sharpened_img)
تصویر حاصل از اعمال فیلتر حسابی روی تصویر با نویز نمک و فلفل، در زیر نشان داده شده است. در مقایسه با تصویر اصلی در مقیاس خاکستری، می بینیم که تصویر را بیش از حد روشن می کند و نمی تواند نقاط روشن را برجسته کند. روی گل رز نیز از این رو می توان نتیجه گرفت که فیلتر محاسباتی در حذف صدای نمک و فلفل ناتوان است.
خروجی فیلتر حسابی:
فیلتر نقطه میانی
from scipy.ndimage import maximum_filter, minimum_filter
def midpoint(img):
maxf = maximum_filter(img, (3, 3))
minf = minimum_filter(img, (3, 3))
midpoint = (maxf + minf) / 2
cv2_imshow(midpoint)
print("\n\n---Effects روی S&P Noise Image with Probability 0.5---\n\n")
midpoint(sp_05)
تصویر حاصل از اعمال فیلتر نقطه میانی روی تصویر با نویز نمک و فلفل، در زیر نشان داده شده است. پس از مقایسه با تصویر اصلی در مقیاس خاکستری، میتوانیم ببینیم که مانند روش هسته بالا، تصویر را بیش از حد روشن میکند. با این حال، می تواند نقاط روشن را برجسته کند روی گل رز. بنابراین می توان گفت که انتخاب بهتری نسبت به فیلتر حسابی است، اما باز هم تصویر اصلی را به طور کامل بازیابی نمی کند.
خروجی فیلتر نقطه میانی:
فیلتر میانگین کنترا هارمونیک
توجه داشته باشید: پیاده سازی های این فیلترها را می توان به راحتی به صورت آنلاین پیدا کرد و روش دقیق کارکرد آنها در این آموزش نمی گنجد. ما به برنامه ها از سطح انتزاعی/بالا نگاه خواهیم کرد.
def contraharmonic_mean(img, size, Q):
num = np.power(img, Q + 1)
denom = np.power(img, Q)
kernel = np.full(size, 1.0)
result = cv2.filter2D(num, -1, kernel) / cv2.filter2D(denom, -1, kernel)
return result
print("\n\n--- Effects روی S&P Noise Image with Probability 0.5 ---\n\n")
cv2_imshow(contraharmonic_mean(sp_05, (3,3), 0.5))
تصویر حاصل، از اعمال میانگین کنترهارمونیک فیلتر کنید روی تصویر با نویز نمک و فلفل، در زیر نشان داده شده است. با مقایسه با تصویر اصلی در مقیاس خاکستری، میتوانیم ببینیم که تقریباً همان تصویر اصلی را بازتولید کرده است. شدت/سطح روشنایی آن یکسان است و نقاط روشن را برجسته می کند روی گل رز نیز از این رو می توان نتیجه گرفت که فیلتر میانگین کنتراهارمونی در مقابله با صدای نمک و فلفل بسیار موثر است.
میانگین خروجی فیلتر کنتراهارمونی:
اکنون که بهترین فیلتر را برای بازیابی تصویر اصلی از یک فیلتر نویز پیدا کردهایم، میتوانیم حرکت کنیم روی به برنامه بعدی ما
شماره 2: تشخیص لبه با استفاده از Canny Edge Detector
تصویر گل رز که تا کنون استفاده کرده ایم دارای پس زمینه ثابت یعنی سیاه است، بنابراین برای بهتر نشان دادن قابلیت های الگوریتم از تصویر متفاوتی برای این اپلیکیشن استفاده خواهیم کرد. دلیل آن این است که اگر پسزمینه ثابت باشد، کار تشخیص لبه را نسبتاً ساده میکند و ما آن را نمیخواهیم.
ما قبلاً در این آموزش در مورد طبقهبندی گربه صحبت کردیم، بیایید آن مثال را به جلو ببریم و ببینیم که پردازش تصویر چگونه نقش مهمی در آن دارد.
در یک الگوریتم طبقهبندی، تصویر ابتدا برای «اشیاء» اسکن میشود، یعنی وقتی یک تصویر را وارد میکنید، الگوریتم تمام اشیاء را در آن تصویر پیدا میکند و سپس آنها را با ویژگیهای جسمی که میخواهید پیدا کنید مقایسه میکند. در مورد طبقهبندی گربه، تمام اشیاء موجود در یک تصویر را با ویژگیهای یک تصویر گربه مقایسه میکند، و اگر مطابقتی پیدا شود، به ما میگوید که تصویر ورودی حاوی یک گربه است.
از آنجایی که ما از طبقهبندی گربه به عنوان مثال استفاده میکنیم، عادلانه است که از تصویر گربه در آینده استفاده کنیم. در زیر تصویری است که ما استفاده خواهیم کرد:
تصویر مورد استفاده برای تشخیص لبه:
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.figure(figsize=(16, 16))
img_gs = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('gs.jpg', img_gs)
edges = cv2.Canny(img_gs, 100,200)
plt.subplot(121), plt.imshow(img_gs)
plt.title('Original Gray Scale Image')
plt.subplot(122), plt.imshow(edges)
plt.title('Edge Image')
plt.show()
خروجی تشخیص لبه:
همانطور که می بینید، بخشی از تصویر که حاوی یک شی است، که در این مورد یک گربه است، از طریق تشخیص لبه نقطه گذاری/جدا شده است. اکنون باید تعجب کنید که چیست؟ آشکارساز لبه Canny و چگونه این اتفاق افتاد. پس بیایید اکنون در مورد آن بحث کنیم.
برای درک مطالب فوق، سه مرحله کلیدی وجود دارد که باید مورد بحث قرار گیرد. ابتدا کاهش نویز را انجام می دهد روی تصویر به روشی مشابه که قبلا در مورد آن صحبت کردیم. دوم، از اولین مشتق در هر پیکسل برای یافتن لبه ها استفاده می کند. منطق پشت این موضوع این است که در نقطهای که یک یال وجود دارد، یک تغییر شدت ناگهانی وجود دارد که باعث افزایش در مقدار مشتق اول میشود و از این رو آن پیکسل را به یک پیکسل لبه تبدیل میکند.
در پایان، آستانه هیسترزیس را انجام می دهد. ما در بالا گفتیم که در یک لبه یک افزایش در ارزش مشتق اول وجود دارد، اما بیان نکردیم که این سنبله چقدر باید باشد تا به عنوان یک یال طبقه بندی شود – این آستانه نامیده می شود! قبلاً در این آموزش بحث کردیم که آستانه ساده چیست. آستانه هیسترزیس یک بهبود است روی که، از دو مقدار آستانه به جای یک استفاده می کند. دلیل این امر این است که اگر مقدار آستانه خیلی زیاد باشد، ممکن است برخی از یال های واقعی را از دست بدهیم (نفیات واقعی) و اگر مقدار خیلی پایین باشد، امتیازهای زیادی به عنوان یال هایی که در واقع یال نیستند (مثبت کاذب) طبقه بندی می شوند. ). یک مقدار آستانه بالا و یک مقدار پایین تنظیم شده است. تمام نقاطی که بالاتر از “مقدار آستانه بالا” هستند به عنوان لبه شناسایی می شوند، سپس تمام نقاطی که بالاتر از مقدار آستانه پایین هستند اما زیر مقدار آستانه بالا هستند، ارزیابی می شوند. نقاطی که نزدیک یا همسایه نقاطی هستند که به عنوان لبه شناسایی شده اند نیز به عنوان لبه شناسایی می شوند و بقیه کنار گذاشته می شوند.
اینها مفاهیم/روش های اساسی هستند که الگوریتم Canny Edge Detector از آنها برای شناسایی لبه ها در یک تصویر استفاده می کند.
نتیجه
در این مقاله روش نصب OpenCV، محبوب ترین کتابخانه برای پردازش تصویر در پایتون را یاد گرفتیم. روی پلتفرم های مختلف مانند Windows، MacOS و Linux، و همچنین روش تأیید موفقیت آمیز بودن نصب.
ما رفتیم روی برای بحث در مورد پردازش تصویر و کاربردهای آن در حوزه بینایی کامپیوتری یادگیری ماشین. قبل از استفاده از تصاویر در برنامه هایمان، در مورد برخی از انواع رایج نویز و روش حذف آن از تصاویر خود با استفاده از فیلترهای مختلف صحبت کردیم.
علاوه بر این، ما یاد گرفتیم که چگونه پردازش تصویر نقش مهمی در برنامههای پیشرفته مانند تشخیص اشیا یا طبقهبندی دارد. توجه داشته باشید که این مقاله فقط نوک کوه یخ بود، و Digital Image Processing چیزهای بیشتری در فروشگاه دارد که احتمالاً نمی توان در یک آموزش به آنها پرداخت. خواندن این مطلب شما را قادر می سازد عمیق تر غواصی کنید و در مورد سایر مفاهیم پیشرفته مرتبط با پردازش تصویر بیاموزید. موفق باشید!
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-18 02:17:03