บทนำ
Thresholding เป็นเทคนิคที่ง่ายและมีประสิทธิภาพในการแบ่งส่วนพื้นฐานในรูปภาพ และทำให้เป็นไบนารี่ (เปลี่ยนให้เป็นภาพไบนารี) โดยที่พิกเซลอยู่อย่างใดอย่างหนึ่ง 0
or 1
(หรือ 255
หากคุณใช้จำนวนเต็มแทนจำนวนเต็ม)
โดยทั่วไป คุณสามารถใช้การจำกัดขอบเขตเพื่อทำการแบ่งส่วนพื้นหลัง-เบื้องหน้าอย่างง่ายในรูปภาพ และรวมถึงตัวแปรโดยใช้เทคนิคง่ายๆ สำหรับแต่ละพิกเซล:
if pixel_value > threshold:
pixel_value = MAX
else:
pixel_value = 0
กระบวนการสำคัญนี้เรียกว่า เกณฑ์ไบนารี. ตอนนี้ มีหลายวิธีที่คุณสามารถปรับเปลี่ยนแนวคิดทั่วไปนี้ได้ รวมถึงการกลับการดำเนินการ (การสลับ >
ลงชื่อด้วย <
เครื่องหมาย) การตั้งค่า pixel_value
ไป threshold
แทนที่จะเป็นค่าสูงสุด/0 (เรียกว่าการตัดทอน) โดยคงค่า pixel_value
ตัวเองถ้ามันอยู่เหนือ threshold
หรือถ้ามันอยู่ด้านล่าง threshold
.
สิ่งเหล่านี้ได้ถูกนำมาใช้อย่างสะดวกใน OpenCV เช่น:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
… ตามลำดับ นี่เป็นวิธีการที่ค่อนข้าง "ไร้เดียงสา" ซึ่งค่อนข้างง่าย ไม่ต้องคำนึงถึงบริบทในรูปภาพ มีความรู้เกี่ยวกับรูปร่างที่เหมือนกัน ฯลฯ สำหรับคุณสมบัติเหล่านี้ เราต้องใช้การคำนวณที่มีราคาแพงและมีประสิทธิภาพมากขึ้น เทคนิคต่างๆ
ตอนนี้ถึงแม้จะใช้วิธี "ไร้เดียงสา" - บาง สามารถใช้ heuristics เพื่อหาเกณฑ์ที่ดีได้ ซึ่งรวมถึงวิธี Otsu และวิธีสามเหลี่ยม:
cv2.THRESH_OTSU
cv2.THRESH_TRIANGLE
หมายเหตุ การกำหนดเกณฑ์ OpenCV เป็นเทคนิคพื้นฐาน และมีความไวต่อการเปลี่ยนแปลงของแสงและการไล่ระดับสี ความแตกต่างของสี ฯลฯ ควรใช้กับรูปภาพที่ค่อนข้างสะอาด หลังจากเบลอเพื่อลดสัญญาณรบกวน โดยไม่มีความแปรปรวนของสีมากในวัตถุที่คุณต้องการแบ่งส่วน
อีกวิธีหนึ่งในการเอาชนะปัญหาบางอย่างเกี่ยวกับการกำหนดเกณฑ์พื้นฐานด้วยค่าขีดจำกัดเดียวคือการใช้ การปรับตัวตามเกณฑ์ ซึ่งใช้ค่าเกณฑ์ในแต่ละภูมิภาคเล็กๆ ในรูปภาพ แทนที่จะเป็นทั่วโลก
เกณฑ์ง่าย ๆ ด้วย OpenCV
การกำหนดเกณฑ์ใน Python API ของ OpenCV ทำได้ผ่านทาง cv2.threshold()
เมธอด – ซึ่งรับอิมเมจ (อาร์เรย์ NumPy แสดงด้วยจำนวนเต็ม) ขีดจำกัด ค่าสูงสุด และวิธีการกำหนดเกณฑ์ (วิธี threshold
และ maximum_value
ใช้แล้ว):
img = cv2.imread('objects.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blurred = cv2.GaussianBlur(img, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)
รหัสส่งคืนเป็นเพียงเกณฑ์ที่ใช้:
print(f"Threshold: {ret}")
ที่นี่เนื่องจากธรณีประตูคือ 220
และเราได้ใช้ THRESH_BINARY
วิธีการ – ทุกค่าพิกเซลด้านบน 220
จะเพิ่มขึ้นเป็น 255
ในขณะที่ทุกค่าพิกเซลด้านล่าง 220
จะลดลงเหลือ 0
สร้างภาพขาวดำด้วย "หน้ากาก" ที่ครอบคลุมวัตถุเบื้องหน้า
ทำไมต้อง 220? การรู้ว่ารูปภาพมีลักษณะอย่างไร ช่วยให้คุณคาดเดาคร่าวๆ ได้ว่าเกณฑ์ใดที่คุณสามารถเลือกได้ ในทางปฏิบัติ คุณแทบจะไม่ต้องการตั้งค่าเกณฑ์ด้วยตนเอง และเราจะครอบคลุมการเลือกเกณฑ์อัตโนมัติในอีกสักครู่
มาพล็อตผลลัพธ์กันเถอะ! หน้าต่าง OpenCV อาจค่อนข้างจู้จี้จุกจิก ดังนั้นเราจะพล็อตภาพต้นฉบับ ภาพเบลอ และผลลัพธ์โดยใช้ Matplotlib:
fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)
วิธีการกำหนดเกณฑ์
ดังที่กล่าวไว้ก่อนหน้านี้ คุณสามารถใช้เกณฑ์และค่าสูงสุดในฟังก์ชันได้หลายวิธี เราได้พิจารณาเกณฑ์ไบนารีในขั้นต้นแล้ว มาสร้างรายการวิธีการและนำไปใช้ทีละรายการโดยวางแผนผลลัพธ์:
methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']
def thresh(img_path, method, index):
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blurred = cv2.GaussianBlur(img, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 220, 255, method)
fig, ax = plt.subplots(1, 3, figsize=(12, 4))
fig.suptitle(names[index], fontsize=18)
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)
plt.tight_layout()
for index, method in enumerate(methods):
thresh('coins.jpeg', method, index)
THRESH_BINARY
และ THRESH_BINARY_INV
เป็นผกผันของกันและกัน และทำให้เป็นสองเท่าของภาพระหว่าง 0
และ 255
โดยกำหนดให้เป็นพื้นหลังและพื้นหน้าตามลำดับ และในทางกลับกัน
THRESH_TRUNC
ทำให้ภาพเป็นสองเท่าระหว่าง threshold
และ 255
.
THRESH_TOZERO
และ THRESH_TOZERO_INV
ไบนารีระหว่าง 0
และค่าพิกเซลปัจจุบัน (src(x, y)
). ลองดูที่ภาพที่ได้:
ดูคู่มือเชิงปฏิบัติสำหรับการเรียนรู้ Git ที่มีแนวทางปฏิบัติที่ดีที่สุด มาตรฐานที่ยอมรับในอุตสาหกรรม และเอกสารสรุปรวม หยุดคำสั่ง Googling Git และจริงๆ แล้ว เรียน มัน!
วิธีการเหล่านี้ใช้งานง่ายเพียงพอ แต่เราจะตั้งค่าเกณฑ์ที่ดีให้เป็นอัตโนมัติได้อย่างไร และค่า "เกณฑ์ที่ดี" หมายความว่าอย่างไร ผลลัพธ์ส่วนใหญ่จนถึงตอนนี้มีมาสก์ที่ไม่เหมาะ โดยมีเครื่องหมายและจุดอยู่ในนั้น สิ่งนี้เกิดขึ้นเนื่องจากความแตกต่างในพื้นผิวสะท้อนแสงของเหรียญ – พวกมันไม่ได้สีสม่ำเสมอเนื่องจากความแตกต่างในการสะท้อนแสงของสันเขา
เราสามารถต่อสู้กับสิ่งนี้ได้ในระดับหนึ่งโดยการค้นหาเกณฑ์ระดับโลกที่ดีกว่า
เกณฑ์อัตโนมัติ/ปรับให้เหมาะสมด้วย OpenCV
OpenCV ใช้วิธีการค้นหาเกณฑ์ทั่วโลกที่มีประสิทธิภาพสองวิธี ได้แก่ วิธีของ Otsu และวิธีสามเหลี่ยม
วิธีการของโอสึถือว่าใช้ได้นะ ไบโมดอล ภาพ รูปภาพ Bi-modal คือรูปภาพที่มีฮิสโทแกรมสีมีเพียงสองจุด (กล่าวคือ มีค่าพิกเซลที่แตกต่างกันเพียงสองค่า) เมื่อพิจารณาว่าพีคแต่ละอันเป็นของคลาสเช่น "พื้นหลัง" และ "เบื้องหน้า" - ธรณีประตูในอุดมคติจะอยู่ตรงกลาง
เครดิตภาพ: https://scipy-lectures.org/
คุณสามารถทำให้ภาพบางภาพเป็นแบบไบโมดอลมากขึ้นด้วยการเบลอแบบเกาส์เซียน แต่ไม่ใช่ทั้งหมด
อัลกอริธึมอีกทางเลือกหนึ่งซึ่งมักมีประสิทธิภาพดีกว่าคืออัลกอริธึมรูปสามเหลี่ยม ซึ่งคำนวณระยะห่างระหว่างฮิสโตแกรมระดับสีเทาสูงสุดและต่ำสุดและลากเส้น จุดที่เส้นนั้นอยู่ห่างจากส่วนที่เหลือของฮิสโตแกรมมากที่สุดจะถูกเลือกเป็น treshold:
ทั้งสองอย่างนี้ถือว่าภาพระดับสีเทา ดังนั้นเราจะต้องแปลงภาพที่ป้อนเป็นสีเทาผ่าน cv2.cvtColor()
:
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)
masked = cv2.bitwise_and(img, img, mask=mask1)
เรียกใช้รูปภาพด้วยทั้งสองวิธีและเห็นภาพผลลัพธ์:
methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']
def thresh(img_path, method, index):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 0, 255, method)
print(f"Threshold: {ret}")
fig, ax = plt.subplots(1, 3, figsize=(12, 5))
fig.suptitle(names[index], fontsize=18)
ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))
for index, method in enumerate(methods):
thresh('coins.jpeg', method, index)
ในที่นี้ วิธีสามเหลี่ยมมีประสิทธิภาพดีกว่าวิธีของ Otsu เพราะรูปภาพนี้ไม่ใช่แบบสองกิริยา:
import numpy as np
img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)
อย่างไรก็ตาม เห็นได้ชัดว่าวิธีสามเหลี่ยมสามารถทำงานกับรูปภาพและให้ผลลัพธ์ที่น่าพึงพอใจมากขึ้นได้อย่างไร
ข้อจำกัดของเกณฑ์ OpenCV
การกำหนดเกณฑ์ด้วย OpenCV นั้นง่าย ง่าย และมีประสิทธิภาพ แต่ค่อนข้างจำกัด ทันทีที่คุณแนะนำองค์ประกอบที่มีสีสัน พื้นหลังที่ไม่เท่ากัน และสภาพแสงที่เปลี่ยนแปลงไป – เกณฑ์ทั่วโลกเนื่องจากแนวคิดจะเข้มงวดเกินไป
รูปภาพมักจะซับซ้อนเกินไปสำหรับเกณฑ์เดียวที่จะเพียงพอและสามารถแก้ไขได้บางส่วนผ่าน การปรับตัวตามเกณฑ์ซึ่งมีการใช้เกณฑ์ท้องถิ่นจำนวนมากแทนเกณฑ์เดียวทั่วโลก แม้ว่าจะมีข้อจำกัดเช่นกัน แต่การจำกัดเกณฑ์แบบปรับได้นั้นมีความยืดหยุ่นมากกว่าการกำหนดเกณฑ์ทั่วไป
สรุป
ในช่วงไม่กี่ปีที่ผ่านมา การแบ่งกลุ่มแบบไบนารี (เช่นเดียวกับที่เราทำที่นี่) และการแบ่งกลุ่มแบบหลายป้ายกำกับ (ซึ่งคุณสามารถเข้ารหัสคลาสได้ตามต้องการ) ได้สร้างโมเดลสำเร็จด้วยเครือข่ายการเรียนรู้เชิงลึก ซึ่งมีประสิทธิภาพและยืดหยุ่นมากกว่ามาก นอกจากนี้ ยังสามารถเข้ารหัสบริบทส่วนกลางและท้องถิ่นลงในรูปภาพที่แบ่งกลุ่มได้ ข้อเสียคือ คุณต้องใช้ข้อมูลในการฝึกอบรม ตลอดจนเวลาและความเชี่ยวชาญ
คุณสามารถใช้ OpenCV เพื่อกำหนดขีดจำกัดแบบง่ายๆ ได้ทันที เพื่อการแบ่งส่วนระดับการผลิตที่แม่นยำ คุณจะต้องใช้โครงข่ายประสาทเทียม
ก้าวต่อไป – การเรียนรู้เชิงลึกเชิงปฏิบัติสำหรับคอมพิวเตอร์วิทัศน์
ธรรมชาติที่อยากรู้อยากเห็นของคุณทำให้คุณต้องการไปต่อหรือไม่? เราขอแนะนำให้ตรวจสอบของเรา คอร์ส: “การเรียนรู้เชิงลึกเชิงปฏิบัติสำหรับคอมพิวเตอร์วิทัศน์ด้วย Python”.
หลักสูตร Computer Vision อื่น?
เราจะไม่ทำการจำแนกตัวเลข MNIST หรือแฟชั่น MNIST พวกเขาทำหน้าที่ส่วนของตนเมื่อนานมาแล้ว ทรัพยากรการเรียนรู้จำนวนมากเกินไปมุ่งเน้นไปที่ชุดข้อมูลพื้นฐานและสถาปัตยกรรมพื้นฐาน ก่อนปล่อยให้สถาปัตยกรรมกล่องดำขั้นสูงรับภาระด้านประสิทธิภาพ
เราต้องการที่จะมุ่งเน้นไปที่ การทำให้ลึกลับ, การปฏิบัติจริง, ความเข้าใจ, ปรีชา และ โครงการจริง. ต้องการเรียน อย่างไร คุณสามารถสร้างความแตกต่าง? เราจะพาคุณเดินทางตั้งแต่วิธีที่สมองของเราประมวลผลภาพไปจนถึงการเขียนตัวแยกประเภทการเรียนรู้เชิงลึกระดับการวิจัยสำหรับมะเร็งเต้านม ไปจนถึงเครือข่ายการเรียนรู้เชิงลึกที่ "หลอน" สอนหลักการและทฤษฎีแก่คุณผ่านการทำงานจริง เพื่อให้คุณมี ความรู้และเครื่องมือในการเป็นผู้เชี่ยวชาญในการประยุกต์ใช้การเรียนรู้เชิงลึกเพื่อแก้ปัญหาคอมพิวเตอร์วิทัศน์
อะไรอยู่ข้างใน?
- หลักการมองเห็นเบื้องต้นและวิธีการสอนคอมพิวเตอร์ให้ “มองเห็น”
- งานต่างๆ และการประยุกต์ใช้คอมพิวเตอร์วิทัศน์
- เครื่องมือการค้าที่จะทำให้งานของคุณง่ายขึ้น
- การค้นหา การสร้าง และการใช้ชุดข้อมูลสำหรับคอมพิวเตอร์วิทัศน์
- ทฤษฎีและการประยุกต์ใช้ Convolutional Neural Networks
- การจัดการการเปลี่ยนแปลงโดเมน การเกิดขึ้นร่วม และอคติอื่นๆ ในชุดข้อมูล
- ถ่ายทอดการเรียนรู้และใช้เวลาฝึกอบรมและทรัพยากรการคำนวณของผู้อื่นเพื่อประโยชน์ของคุณ
- การสร้างและฝึกอบรมผู้จำแนกมะเร็งเต้านมที่ล้ำสมัย
- วิธีการใช้ความสงสัยที่ดีต่อสุขภาพกับแนวคิดกระแสหลักและทำความเข้าใจกับความหมายของเทคนิคที่นำมาใช้กันอย่างแพร่หลาย
- การแสดงภาพ "พื้นที่แนวคิด" ของ ConvNet โดยใช้ t-SNE และ PCA
- กรณีศึกษาวิธีที่บริษัทต่างๆ ใช้เทคนิคการมองเห็นด้วยคอมพิวเตอร์เพื่อให้ได้ผลลัพธ์ที่ดีขึ้น
- การประเมินแบบจำลองที่เหมาะสม การสร้างภาพพื้นที่แฝง และการระบุความสนใจของแบบจำลอง
- ดำเนินการวิจัยโดเมน ประมวลผลชุดข้อมูลของคุณเอง และสร้างการทดสอบแบบจำลอง
- สถาปัตยกรรมล้ำสมัย ความก้าวหน้าของแนวคิด สิ่งที่ทำให้มีเอกลักษณ์เฉพาะตัว และวิธีนำไปใช้
- KerasCV – ไลบรารี WIP สำหรับสร้างไปป์ไลน์และโมเดลที่ทันสมัย
- วิธีแยกวิเคราะห์และอ่านเอกสารและนำไปใช้เอง
- การเลือกรุ่นขึ้นอยู่กับการใช้งานของคุณ
- การสร้างไปป์ไลน์การเรียนรู้ของเครื่องแบบ end-to-end
- ภูมิทัศน์และสัญชาตญาณในการตรวจจับวัตถุด้วย R-CNN ที่เร็วกว่า, RetinaNets, SSD และ YOLO
- การแบ่งกลุ่มตัวอย่างและความหมาย
- การจดจำวัตถุแบบเรียลไทม์ด้วย YOLOv5
- การฝึกอบรมเครื่องตรวจจับวัตถุ YOLOv5
- การทำงานกับ Transformers โดยใช้ KerasNLP (ไลบรารี WIP ที่มีความแข็งแกร่งในอุตสาหกรรม)
- การรวม Transformers เข้ากับ ConvNets เพื่อสร้างคำบรรยายภาพ
- Deepdream
- การเพิ่มประสิทธิภาพโมเดล Deep Learning สำหรับคอมพิวเตอร์วิทัศน์