معرفی
تشخیص لبه کاری است که ما به طور طبیعی انجام میدهیم، اما وقتی صحبت از تعریف قوانین برای رایانهها میشود، آسان نیست. در حالی که روشهای مختلفی ابداع شدهاند، روش حاکم در سال 1986 توسط جان اف.
این سریع، نسبتاً قوی است و تقریباً بهترین عملکرد را برای نوع تکنیکی که دارد انجام می دهد. در پایان راهنما، میدانید که چگونه میتوانید تشخیص لبهها را در زمان واقعی روی ویدیوها انجام دهید و چیزی در راستای این موارد تولید کنید:
تشخیص لبه Canny
روش Canny چیست؟ از چهار عملیات مجزا تشکیل شده است:
- صاف کردن گاوسی
- شیب محاسباتی
- سرکوب غیر حداکثری
- آستانه هیسترزیس
صاف کردن گاوسی به عنوان اولین گام برای اتو کردن تصویر ورودی و کاهش نویز استفاده می شود و خروجی نهایی را بسیار تمیزتر می کند.
گرادیان های تصویر در برنامه های قبلی برای تشخیص لبه استفاده شده است. مهمتر از همه، فیلترهای Sobel و Scharr به گرادیان تصویر متکی هستند. فیلتر سوبل به دو هسته (Gx و Gy)، جایی که Gx تغییرات افقی را تشخیص می دهد، در حالی که Gy تغییرات عمودی را تشخیص می دهد:
G
x
=
[
-
1
0
+
1
-
2
0
+
2
-
1
0
+
1
]
G
y
=
[
-
1
-
2
-
1
0
0
0
+
1
+
2
+
1
]
وقتی آنها را روی یک تصویر میکشید، هر کدام خطوط را در جهت مربوطه خود "برمیدارند" (تاکید میکنند). هسته های Scharr به همین ترتیب با مقادیر متفاوت کار می کنند:
G
x
=
[
+
3
0
-
3
+
10
0
-
10
+
3
0
-
3
]
G
y
=
[
+
3
+
10
+
3
0
0
0
-
3
-
10
-
3
]
این فیلترها، هنگامی که روی تصویر پیچیده می شوند، نقشه های ویژگی را تولید می کنند:
اعتبار تصویر: Davidwkennedy
برای این نقشه های ویژگی، می توانید محاسبه کنید قدر گرادیان و جهت گرادیان - یعنی تغییر چقدر شدید است (چقدر احتمال دارد چیزی لبه باشد) و تغییر در کدام جهت است. از آنجایی که Gy نشان دهنده تغییر عمودی (شیب Y) و Gx نشان دهنده تغییر افقی (شیب X) است - می توانید مقدار را با استفاده از قضیه فیثاغورث به سادگی محاسبه کنید تا فرضیه مثلثی که توسط "چپ" تشکیل شده است و جهت های "درست":
$$
{G} ={sqrt {{{G} _{x}}^{2}+{{G} _{y}}^{2}}}
$$
با استفاده از اندازه و جهت، می توانید تصویری با لبه های برجسته تولید کنید:
اعتبار تصویر: Davidwkennedy
با این حال - می توانید ببینید که چقدر سر و صدا از بافت آجرها گرفته شده است! گرادیان های تصویر به نویز بسیار حساس هستند. به همین دلیل است که فیلترهای Sobel و Scharr به عنوان مؤلفه مورد استفاده قرار گرفتند، اما نه تنها رویکرد در روش Canny. صاف کردن گاوسی در اینجا نیز کمک می کند.
سرکوب غیر حداکثری
یک مشکل قابل توجه در مورد فیلتر Sobel این است که لبه ها واقعاً واضح نیستند. اینطور نیست که کسی مداد را بگیرد و خطی بکشد تا تصویر خطی ایجاد کند. لبه ها معمولاً در تصاویر چندان واضح نیستند، زیرا نور به تدریج پخش می شود. با این حال، ما میتوانیم خط مشترک را در لبهها پیدا کنیم و بقیه پیکسلهای اطراف آن را مهار کنیم و به جای آن یک خط جداسازی تمیز و نازک ایجاد کنیم. این به عنوان سرکوب غیر حداکثری شناخته می شود! پیکسلهای غیر حداکثری (پیکسلهایی که کوچکتر از پیکسلهایی هستند که در یک فیلد محلی کوچک با آن مقایسه میکنیم، مانند یک هسته 3×3) سرکوب میشوند. این مفهوم برای کارهای بیشتر از این قابل استفاده است، اما بیایید فعلاً آن را به این زمینه پیوند دهیم.
آستانه هیسترزیس
بسیاری از غیر لبه ها به دلیل شرایط نوری، مواد موجود در تصویر و غیره می توانند و احتمالاً به عنوان لبه ارزیابی می شوند. به دلیل دلایل مختلفی که این محاسبات اشتباه رخ می دهد - ارزیابی خودکار از اینکه یک لبه قطعاً چیست و چه چیزی نیست دشوار است. 't. میتوانید شیبهای آستانه را تعیین کنید و فقط شیبهای قویتر را در نظر بگیرید، با این فرض که لبههای «واقعی» شدیدتر از لبههای «جعلی» هستند.
Thresholding تقریباً به همان روش معمول کار می کند - اگر گرادیان زیر آستانه پایین تر است، آن را حذف کنید (آن را به صفر برسانید) و اگر بالاتر از یک آستانه بالا است، آن را حفظ کنید. همه چیز بین کران پایین و کران بالا در "منطقه خاکستری" است. اگر هر لبه ای در بین آستانه ها به a متصل شود لبه قطعی (آنهایی که بالاتر از آستانه هستند) - آنها همچنین لبه ها در نظر گرفته می شوند. اگر متصل نباشند، احتمالاً لبههای محاسبهشده اشتباهی دارند.
این آستانه هیسترزیس است! در واقع، بسته به آنچه که به عنوان لبه کاذب طبقه بندی می کنید، به تمیز کردن خروجی نهایی و حذف لبه های کاذب کمک می کند. برای یافتن مقادیر آستانه خوب، معمولاً با مرزهای مختلف پایین و بالایی برای آستانه ها آزمایش می کنید، یا از یک روش خودکار مانند روش Otsu یا روش مثلث استفاده می کنید.
بیایید یک تصویر را بارگذاری کنیم و آن را در مقیاس خاکستری قرار دهیم (Canny، درست همانطور که Sobel/Scharr به تصاویر نیاز دارد که در مقیاس خاکستری باشند):
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('finger.jpg', cv2.IMREAD_GRAYSCALE)
img_blur = cv2.GaussianBlur(img, (3,3), 0)
plt.imshow(img_blur, cmap='gray')
تصویر نزدیک انگشت به عنوان یک محل آزمایش خوب برای تشخیص لبه عمل می کند – تشخیص اثر انگشت از روی تصویر کار آسانی نیست، اما می توانیم آن را تقریبی کنیم.
تشخیص لبه در تصاویر با ()cv2.Canny
الگوریتم Canny را می توان با استفاده از OpenCV اعمال کرد Canny()
روش:
cv2.Canny(input_img, lower_bound, upper_bound)
راهنمای عملی و عملی ما برای یادگیری Git را با بهترین روش ها، استانداردهای پذیرفته شده در صنعت و برگه تقلب شامل بررسی کنید. دستورات Google Git را متوقف کنید و در واقع یاد گرفتن آی تی!
یافتن تعادل مناسب بین کران پایین و کران بالا می تواند مشکل باشد. اگر هر دو کم باشند - لبه های کمی خواهید داشت. اگر کران پایین پایین و بالا بالا باشد - نویز خواهید داشت. اگر هر دو بالا و نزدیک به هم باشند - لبه های کمی خواهید داشت. نقطه مناسب فاصله کافی بین مرزها دارد و آنها را در مقیاس مناسب قرار می دهد. آزمایش کنید!
تصویر ورودی با روش Canny تار می شود، اما اغلب اوقات، شما از محو کردن آن سود خواهید برد. قبل از آن نیز وارد می شود. این روش قبل از انجام بقیه عملیات، یک تاری گاوسی 5×5 را روی ورودی اعمال میکند، اما حتی با این تاری، مقداری نویز همچنان میتواند از آن عبور کند، بنابراین قبل از وارد کردن آن به الگوریتم، تصویر را تار کردهایم:
edge = cv2.Canny(img_blur, 20, 30)
fig, ax = plt.subplots(1, 2, figsize=(18, 6), dpi=150)
ax[0].imshow(img, cmap='gray')
ax[1].imshow(edge, cmap='gray')
این نتیجه در:
ارزش های 20
و 30
در اینجا دلخواه نیستند - من روش را روی پارامترهای مختلف آزمایش کردهام و مجموعهای را انتخاب کردم که به نظر میرسید نتیجه مناسبی داشته باشد. آیا می توانیم سعی کنیم این را خودکار کنیم؟
آستانه خودکار برای ()cv2.Canny؟
آیا می توانید مجموعه ای بهینه از مقادیر آستانه را پیدا کنید؟ بله، اما همیشه کار نمی کند. شما می توانید محاسبه خود را برای مقداری خوب انجام دهید و سپس محدوده را با a تنظیم کنید sigma
در اطراف آن آستانه:
lower_bound = (1-sigma)*threshold
upper_bound = (1+sigma)*threshold
چه زمانی sigma
، می گویند، 0.33
- حدود خواهد بود 0.66*threshold
و 1.33*threshold
، اجازه می دهد حدود 1/3 در اطراف آن باشد. اگرچه، پیدا کردن threshold
سخت تر است OpenCV روش Otsu (برای تصاویر دو وجهی عالی کار می کند) و روش مثلث را در اختیار ما قرار می دهد. بیایید هر دوی آنها را امتحان کنیم، و همچنین یک میانه ساده از مقادیر پیکسل را به عنوان گزینه سوم در نظر بگیریم:
otsu_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_OTSU)
triangle_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_TRIANGLE)
manual_thresh = np.median(img_blur)
def get_range(threshold, sigma=0.33):
return (1-sigma) * threshold, (1+sigma) * threshold
otsu_thresh = get_range(otsu_thresh)
triangle_thresh = get_range(triangle_thresh)
manual_thresh = get_range(manual_thresh)
print(f"Otsu's Threshold: {otsu_thresh} nTriangle Threshold: {triangle_thresh} nManual Threshold: {manual_thresh}")
این نتیجه در:
Otsu's Threshold: (70.35, 139.65)
Triangle Threshold: (17.419999999999998, 34.58)
Manual Threshold: (105.18999999999998, 208.81)
اینها خیلی متفاوت هستند! با توجه به مقادیری که قبلاً دیدهایم، میتوانیم روش مثلث را در اینجا پیشبینی کنیم که بهترین عملکرد را دارد. آستانه دستی چندان آگاه نیست، زیرا فقط مقدار پیکسل میانه را می گیرد و در نهایت آستانه پایه بالایی دارد که در محدوده وسیعی برای این تصویر چند برابر می شود. روش Otsu کمتر از این آسیب می بیند، اما با این وجود رنج می برد.
اگر ما اجرا کنیم Canny()
روش با این محدوده های آستانه:
edge_otsu = cv2.Canny(img_blur, *otsu_thresh)
edge_triangle = cv2.Canny(img_blur, *triangle_thresh)
edge_manual = cv2.Canny(img_blur, *manual_thresh)
fig, ax = plt.subplots(1, 3, figsize=(18, 6), dpi=150)
ax[0].imshow(edge_otsu, cmap='gray')
ax[1].imshow(edge_triangle, cmap='gray')
ax[2].imshow(edge_manual, cmap='gray')
توجه داشته باشید: تابع انتظار آرگومان های متعدد دارد و آستانه های ما یک تاپل واحد هستند. ما میتوانیم تخریب تاپل را با قرار دادن پیشوند با آرگومان های متعدد تبدیل می کند *
. این روی لیستها و مجموعهها نیز کار میکند، و یک راه عالی برای ارائه چندین آرگومان پس از بهدستآوردن آنها با ابزارهای برنامهای است.
این نتیجه در:
روش مثلث در اینجا خیلی خوب کار کرد! این تضمینی نیست که در موارد دیگر نیز به خوبی کار کند.
تشخیص لبه بلادرنگ در ویدیوها با ()cv2.Canny
در نهایت، بیایید تشخیص لبه Canny را در زمان واقعی برای یک ویدیو اعمال کنیم! ما ویدیوی در حال پردازش (هر فریم همانطور که انجام شده است) را با استفاده از آن نمایش خواهیم داد cv2.imshow()
که پنجره ای را با قاب مورد نظر ما نمایش می دهد. اگرچه، ما همچنین ویدیو را در یک فایل MP4 ذخیره میکنیم که بعداً قابل بررسی و اشتراکگذاری است.
برای بارگذاری یک ویدیو با استفاده از OpenCV، از VideoCapture()
روش. اگر عبور کنیم 0
- از وب کم فعلی ضبط می کند، بنابراین می توانید کد را روی وب کم خود نیز اجرا کنید! اگر نام فایلی را ارسال کنید، فایل را بارگیری می کند:
def edge_detection_video(filename):
cap = cv2.VideoCapture(filename)
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))), isColor=False)
while cap.isOpened():
(ret, frame) = cap.read()
if ret == True:
frame = cv2.GaussianBlur(frame, (3, 3), 0)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edge = cv2.Canny(frame, 50, 100)
out.write(edge)
cv2.imshow('Edge detection', edge)
else:
break
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
edge_detection_video('secret_video.mp4')
La VideoWriter
چندین پارامتر را می پذیرد - نام فایل خروجی، FourCC (چهار کد کدک، نشان دهنده کدک مورد استفاده برای رمزگذاری ویدیو)، نرخ فریم و وضوح به صورت یک تایی. برای اینکه ویدیو را حدس نزنیم یا اندازه آن را تغییر ندهیم – از عرض و ارتفاع ویدیوی اصلی که از طریق VideoCapture
نمونهای که حاوی دادههایی درباره خود ویدیو است، مانند عرض، ارتفاع، تعداد کل فریمها و غیره.
در حالی که کپچر باز است، سعی می کنیم فریم بعدی را با آن بخوانیم cap.read()
، که یک کد نتیجه و فریم بعدی را برمی گرداند. کد نتیجه این است True
or False
، نشان دهنده وجود فریم بعدی یا عدم وجود آن است. فقط زمانی که یک قاب وجود داشته باشد، سعی می کنیم آن را بیشتر پردازش کنیم، در غیر این صورت، حلقه را می شکنیم. برای هر فریم معتبر، آن را از طریق یک تاری گاوسی اجرا می کنیم، آن را به مقیاس خاکستری تبدیل می کنیم، اجرا می کنیم cv2.Canny()
روی آن بنویسید و با استفاده از VideoWriter
روی دیسک، و با استفاده از آن نمایش داده شود cv2.imshow()
برای نمایش زنده
در نهایت، ضبط و نوشتن ویدئو را آزاد میکنیم، زیرا هر دو با فایلهای روی دیسک کار میکنند و تمام پنجرههای موجود را از بین میبرند.
وقتی روش را با a اجرا می کنید secret_video.mp4
ورودی - یک پنجره ظاهر می شود و پس از اتمام آن، یک فایل در دایرکتوری کاری شما:
نتیجه
در این راهنما، نگاهی به نحوه عملکرد تشخیص لبه Canny، و اجزای تشکیل دهنده آن - صاف کردن گاوسی، فیلترهای سوبل و گرادیان های تصویر، سرکوب غیر حداکثری و آستانه هیسترزیس انداخته ایم. در نهایت، روشهایی را برای جستجوی محدوده آستانه خودکار برای تشخیص لبه Canny با استفاده از آن بررسی کردهایم cv2.Canny()
، و این تکنیک را روی یک ویدیو به کار گرفت و تشخیص لبه را در زمان واقعی ارائه داد و نتایج را در یک فایل ویدیویی ذخیره کرد.
رفتن به جلو - یادگیری عمیق عملی برای بینایی کامپیوتر
طبیعت کنجکاو شما باعث می شود که بخواهید جلوتر بروید؟ توصیه می کنیم ما را بررسی کنید دوره: "یادگیری عمیق عملی برای بینایی کامپیوتر با پایتون".
یکی دیگر از دوره های بینایی کامپیوتر؟
ما طبقه بندی ارقام MNIST یا مد MNIST را انجام نخواهیم داد. آنها مدتها پیش نقش خود را انجام دادند. بسیاری از منابع یادگیری قبل از اینکه به معماریهای جعبه سیاه پیشرفته اجازه دهند بار عملکرد را به دوش بکشند، روی مجموعه دادههای پایه و معماریهای پایه تمرکز میکنند.
ما می خواهیم روی آن تمرکز کنیم ابهام زدایی, عملی بودن, درک, شهود و پروژه های واقعی. می خواهند یاد بگیرند چگونه تو می توانی تفاوت ایجاد کنی؟ ما شما را از روشی که مغزمان تصاویر را پردازش میکند تا نوشتن طبقهبندیکننده یادگیری عمیق برای سرطان سینه تا شبکههای یادگیری عمیق که «توهم میکنند»، آموزش اصول و تئوری به شما از طریق کار عملی، و تجهیز شما به دانش و ابزارهایی برای تبدیل شدن به یک متخصص در استفاده از یادگیری عمیق برای حل بینایی کامپیوتر.
داخل چیست؟
- اولین اصول بینایی و نحوه آموزش دیدن کامپیوترها
- وظایف و کاربردهای مختلف بینایی کامپیوتر
- ابزارهای تجارت که کار شما را آسان می کند
- یافتن، ایجاد و استفاده از مجموعه داده ها برای بینایی کامپیوتری
- تئوری و کاربرد شبکه های عصبی کانولوشنال
- مدیریت تغییر دامنه، همزمانی و سایر سوگیری ها در مجموعه داده ها
- آموزش را انتقال دهید و از زمان آموزشی و منابع محاسباتی دیگران به نفع خود استفاده کنید
- ساخت و آموزش پیشرفته ترین طبقه بندی سرطان سینه
- چگونه می توان دوز سالمی از شک و تردید را در ایده های جریان اصلی به کار برد و پیامدهای تکنیک های پذیرفته شده را درک کرد
- تجسم فضای مفهومی ConvNet با استفاده از t-SNE و PCA
- مطالعات موردی چگونگی استفاده شرکت ها از تکنیک های بینایی کامپیوتری برای دستیابی به نتایج بهتر
- ارزیابی صحیح مدل، تجسم فضای پنهان و شناسایی توجه مدل
- انجام تحقیقات دامنه، پردازش مجموعه داده های خود و ایجاد آزمون های مدل
- معماری های پیشرفته، پیشرفت ایده ها، آنچه آنها را منحصر به فرد می کند و نحوه اجرای آنها
- KerasCV - یک کتابخانه WIP برای ایجاد خطوط لوله و مدل های پیشرفته
- نحوه تجزیه و خواندن مقالات و پیاده سازی آنها توسط خودتان
- انتخاب مدل ها بسته به برنامه شما
- ایجاد خط لوله یادگیری ماشینی سرتاسر
- چشم انداز و شهود در تشخیص اشیا با R-CNN سریعتر، رتینا نت، SSD و YOLO
- نمونه و تقسیم بندی معنایی
- تشخیص شی در زمان واقعی با YOLOv5
- آموزش آشکارسازهای شی YOLOv5
- کار با ترانسفورماتورها با استفاده از KerasNLP (کتابخانه WIP با قدرت صنعتی)
- ادغام ترانسفورماتورها با ConvNets برای تولید شرح تصاویر
- عمیق
- بهینه سازی مدل یادگیری عمیق برای بینایی کامپیوتر