- 1. การแบ่งส่วนและรูปทรง
- 2. ลำดับชั้นและโหมดการดึงข้อมูล
- 3. การประมาณรูปทรงและการค้นหาตัวถังที่นูน
- 4. นูนฮัลล์
- 5. การจับคู่ Contour ตามรูปร่าง
- 6. การระบุรูปร่าง (วงกลมสี่เหลี่ยมผืนผ้าสามเหลี่ยมสี่เหลี่ยมจัตุรัสดาว)
- 7. การตรวจจับสาย
- 8. การตรวจจับหยด
- 9. การกรอง Blobs - การนับวงกลมและวงรี
ในบทช่วยสอนก่อนหน้านี้เราได้ใช้ OpenCV สำหรับการประมวลผลภาพขั้นพื้นฐานและทำการแก้ไขรูปภาพขั้นสูง ดังที่เราทราบกันดีว่า OpenCV เป็น Open Source Commuter Vision Libraryซึ่งมีอินเตอร์เฟส C ++, Python และ Java และรองรับ Windows, Linux, Mac OS, iOS และ Android ดังนั้นจึงสามารถติดตั้งได้อย่างง่ายดายใน Raspberry Pi ด้วยสภาพแวดล้อม Python และ Linux และ Raspberry Pi พร้อม OpenCV และกล้องที่แนบมาสามารถใช้เพื่อสร้างแอปพลิเคชันการประมวลผลภาพแบบเรียลไทม์มากมายเช่นการตรวจจับใบหน้าการล็อกใบหน้าการติดตามวัตถุการตรวจจับป้ายทะเบียนรถยนต์ระบบรักษาความปลอดภัยภายในบ้านเป็นต้นในบทช่วยสอนนี้เราจะเรียนรู้ว่าต้องทำอย่างไร การแบ่งส่วนภาพโดยใช้ OpenCV การดำเนินการที่เราจะดำเนินการมีดังต่อไปนี้:
- การแบ่งส่วนและรูปทรง
- ลำดับชั้นและโหมดการดึงข้อมูล
- การประมาณรูปทรงและการค้นหาตัวถังที่นูนออกมา
- Conex Hull
- การจับคู่ Contour
- การระบุรูปร่าง (วงกลมสี่เหลี่ยมผืนผ้าสามเหลี่ยมสี่เหลี่ยมจัตุรัสดาว)
- การตรวจจับเส้น
- การตรวจจับหยด
- การกรอง blobs - การนับวงกลมและจุดไข่ปลา
1. การแบ่งส่วนและรูปทรง
การแบ่งส่วนภาพเป็นกระบวนการที่เราแบ่งภาพออกเป็นภูมิภาคต่างๆ ในขณะที่รูปทรงคือเส้นหรือเส้นโค้งที่ต่อเนื่องกันซึ่งมัดหรือครอบคลุมขอบเขตทั้งหมดของวัตถุในภาพ และในที่นี้เราจะใช้เทคนิคการแบ่งส่วนภาพที่เรียกว่ารูปทรงเพื่อดึงส่วนต่างๆของภาพออกมา
รูปทรงก็มีความสำคัญมากเช่นกัน
- การตรวจจับวัตถุ
- การวิเคราะห์รูปร่าง
และพวกเขามีขอบเขตการใช้งานที่กว้างขวางมากตั้งแต่การวิเคราะห์ภาพในโลกแห่งความเป็นจริงไปจนถึงการวิเคราะห์ภาพทางการแพทย์เช่นใน MRI
มารู้วิธีใช้รูปทรงใน opencv โดยการแยกรูปทรงของสี่เหลี่ยม
import cv2 import numpy เป็น np
มาโหลดภาพง่ายๆด้วยสี่เหลี่ยมสีดำ 3 ช่อง
image = cv2.imread ('squares.jpg') cv2.imshow ('อินพุตรูปภาพ', รูปภาพ) cv2.waitKey (0)
โทนสีเทา
สีเทา = cv2.cvtColor (ภาพ cv2.COLOR_BGR2GRAY)
หาขอบที่สวยงาม
edged = cv2.Canny (สีเทา, 30,200) cv2.imshow ('ขอบบาง', ขอบ) cv2.waitKey (0)
การค้นหารูปทรง
# ใช้สำเนารูปภาพของคุณเช่น - edged.copy () เนื่องจากการค้นหารูปทรงเปลี่ยนรูปภาพ # เราต้องเพิ่ม _ ก่อนที่รูปทรงจะเป็นอาร์กิวเมนต์ว่างเนื่องจากการอัปเกรดเวอร์ชัน OpenCV _, รูปทรง, ลำดับชั้น = cv2.findContours (ขอบ cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cv2.imshow ('ขอบที่เรียบง่ายหลังเส้นขอบ', ขอบ) cv2.waitKey (0)
การพิมพ์ไฟล์รูปร่างเพื่อให้ทราบว่ารูปทรงประกอบด้วยอะไรบ้าง
พิมพ์ (รูปทรง) พิมพ์ ('จำนวนของรูปทรงที่พบ =' + str (len (รูปทรง)))
วาดรูปทรงทั้งหมด
#use -1 เป็นพารามิเตอร์ตัวที่ 3 เพื่อวาดรูปทรงทั้งหมด cv2.drawContours (รูปภาพ, รูปทรง, -1, (0,255,0), 3) cv2.imshow ('contours', รูปภาพ) cv2.waitKey (0) cv2 ทำลาย AllWindows ()
เอาต์พุตคอนโซล -],],], …,],],]], dtype = int32), อาร์เรย์ (],],
], …,
],],]], dtype = int32), อาร์เรย์ (],],], …,],],]], dtype = int32)]
จำนวนรูปทรงที่พบ = 3 ดังนั้นเราจึงพบรูปทรงทั้งหมดสามแบบ
ขณะนี้ในโค้ดข้างต้นเราก็พิมพ์ไฟล์รูปร่างโดยใช้ , ไฟล์นี้บอกว่ารูปทรงเหล่านี้ดูเหมือนเป็นพิมพ์ในการส่งออกคอนโซลข้างต้น
ในเอาต์พุตคอนโซลด้านบนเรามีเมทริกซ์ซึ่งดูเหมือนพิกัด x, y จุด OpenCV จัดเก็บรูปทรงในรายการของรายการ เราสามารถแสดงเอาต์พุตคอนโซลด้านบนได้ดังนี้:
CONTOUR 1 CONTOUR 2 CONTOUR 3
], array (], อาร์เรย์ (],],],],],],],
…,…,…,],],],],],],]], dtype = int32),]], dtype = int32),]], dtype = int32)]
ตอนนี้เมื่อเราใช้ฟังก์ชัน length ในไฟล์รูปร่างเราจะได้ความยาวเท่ากับ 3 หมายความว่ามีรายการสามรายการในไฟล์นั้นคือสามรูปทรง
ทีนี้ลองนึกภาพCONTOUR 1เป็นองค์ประกอบแรกในอาร์เรย์นั้นและรายการนั้นมีรายการพิกัดทั้งหมดและพิกัดเหล่านี้คือจุดตามรูปทรงที่เราเพิ่งเห็นเป็นกล่องสี่เหลี่ยมสีเขียว
มีวิธีการต่างๆในการจัดเก็บพิกัดเหล่านี้และเรียกว่าวิธีการประมาณโดยทั่วไปวิธีการประมาณมีสองประเภท
- cv2.CHAIN_APPROX_NONE
- cv2.CHAIN_APPROX_SIMPLE
cv2.CHAIN_APPROX_NONEเก็บจุดขอบเขตทั้งหมด แต่เราไม่จำเป็นต้องมีจุดขอบเขตทั้งหมดหากจุดนั้นเป็นเส้นตรงเราต้องการเพียงแค่จุดเริ่มต้นและจุดสิ้นสุดของเส้นนั้น
cv2.CHAIN_APPROX_SIMPLEให้เฉพาะจุดเริ่มต้นและจุดสิ้นสุดของรูปทรงขอบเขตผลที่ได้คือการจัดเก็บข้อมูลรูปร่างที่มีประสิทธิภาพมากขึ้น
_, รูปทรง, ลำดับชั้น = cv2.findContours (ขอบ, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
ในโค้ดด้านบน cv2.RETR_EXTERNAL คือโหมดการดึงข้อมูลในขณะที่ cv2.CHAIN_APPROX_NONE คือ
วิธีการประมาณ
ดังนั้นเราได้เรียนรู้เกี่ยวกับรูปทรงและวิธีการประมาณแล้วตอนนี้เรามาสำรวจลำดับชั้นและโหมดการดึงข้อมูล
2. ลำดับชั้นและโหมดการดึงข้อมูล
โหมดการดึงข้อมูลจะกำหนดลำดับชั้นในรูปทรงต่างๆเช่นรูปทรงย่อยหรือรูปทรงภายนอกหรือรูปทรงทั้งหมด
ขณะนี้มีโหมดการดึงข้อมูลสี่โหมดที่เรียงลำดับตามประเภทลำดับชั้น
cv2.RETR_LIST - ดึงรูปทรงทั้งหมด
cv2.RETR_EXTERNAL -ดึงรูปทรงภายนอกหรือภายนอกเท่านั้น
cv2.RETR_CCOMP -ดึงข้อมูลทั้งหมดในลำดับชั้น 2 ระดับ
cv2.RETR_TREE -ดึงข้อมูลทั้งหมดในลำดับชั้นแบบเต็ม
ลำดับชั้นถูกจัดเก็บในรูปแบบต่อไปนี้
ทีนี้มาดูความแตกต่างระหว่างสองโหมดการดึงข้อมูลแรกคือ cv2.RETR_LIST และ cv2.RETR_EXTERNAL
import cv2 import numpy เป็น np
ให้โหลดภาพง่ายๆด้วยสี่เหลี่ยมสีดำ 3 ช่อง
image = cv2.imread ('square donut.jpg') cv2.imshow ('input image', image) cv2.waitKey (0)
โทนสีเทา
สีเทา = cv2.cvtColor (ภาพ cv2.COLOR_BGR2GRAY)
ค้นหา Canny Edges
edged = cv2.Canny (สีเทา, 30,200) cv2.imshow ('ขอบบาง', ขอบ) cv2.waitKey (0)
การค้นหารูปทรง
# ใช้สำเนารูปภาพของคุณเช่น - edged.copy () เนื่องจากการค้นหารูปทรงจะเปลี่ยนรูปภาพ # เราต้องเพิ่ม _ ก่อนที่รูปทรงจะเป็นอาร์กิวเมนต์ว่างเนื่องจากการอัปเกรดเวอร์ชัน cv ที่เปิดอยู่ _, รูปทรง, ลำดับชั้น = cv2.findContours (ขอบ cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cv2.imshow ('ขอบที่เรียบง่ายหลังเส้นขอบ', ขอบ) cv2.waitKey (0)
การพิมพ์ไฟล์รูปร่างเพื่อให้ทราบว่ารูปทรงประกอบด้วยอะไรบ้าง
พิมพ์ (รูปทรง) พิมพ์ ('จำนวนของรูปทรงที่พบ =' + str (len (รูปทรง)))
วาดรูปทรงทั้งหมด
#use -1 เป็นพารามิเตอร์ตัวที่ 3 เพื่อวาดรูปทรงทั้งหมด cv2.drawContours (รูปภาพ, รูปทรง, -1, (0,255,0), 3) cv2.imshow ('รูปทรง', รูปภาพ) cv2.waitKey (0) cv2 ทำลาย AllWindows
import cv2 import numpy เป็น np
ให้โหลดภาพง่ายๆด้วยสี่เหลี่ยมสีดำ 3 ช่อง
image = cv2.imread ('square donut.jpg') cv2.imshow ('input image', image) cv2.waitKey (0)
โทนสีเทา
สีเทา = cv2.cvtColor (ภาพ cv2.COLOR_BGR2GRAY)
หาขอบที่สวยงาม
edged = cv2.Canny (สีเทา, 30,200) cv2.imshow ('ขอบบาง', ขอบ) cv2.waitKey (0)
การค้นหารูปทรง
# ใช้สำเนารูปภาพของคุณเช่น - edged.copy () เนื่องจากการค้นหารูปทรงจะเปลี่ยนรูปภาพ # เราต้องเพิ่ม _ ก่อนที่รูปทรงจะเป็นอาร์กิวเมนต์ว่างเนื่องจากการอัปเกรดเวอร์ชัน cv ที่เปิดอยู่ _, รูปทรง, ลำดับชั้น = cv2.findContours (ขอบ cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) cv2.imshow ('ขอบที่เรียบง่ายหลังเส้นขอบ', ขอบ) cv2.waitKey (0)
การพิมพ์ไฟล์รูปร่างเพื่อให้ทราบว่ารูปทรงประกอบด้วยอะไรบ้าง
พิมพ์ (รูปทรง) พิมพ์ ('จำนวนของรูปทรงที่พบ =' + str (len (รูปทรง)))
วาดรูปทรงทั้งหมด
#use -1 เป็นพารามิเตอร์ตัวที่ 3 เพื่อวาดรูปทรงทั้งหมด cv2.drawContours (รูปภาพ, รูปทรง, -1, (0,255,0), 3) cv2.imshow ('contours', รูปภาพ) cv2.waitKey (0) cv2 ทำลาย AllWindows ()
ดังนั้นจากการสาธิตโค้ดด้านบนเราจะเห็นความแตกต่างระหว่าง cv2.RETR_LIST และ cv2.RETR_EXTERNNAL ใน cv2.RETR_EXTERNNAL เฉพาะรูปทรงภายนอกเท่านั้นในขณะที่รูปทรงด้านในจะถูกนำมาพิจารณาเท่านั้น
ในขณะที่รูปทรงด้านใน cv2.RETR_LIST จะถูกนำมาพิจารณาด้วย
3. การประมาณรูปทรงและการค้นหาตัวถังที่นูน
ในการประมาณรูปร่างรูปร่างของเส้นชั้นความสูงจะอยู่ใกล้กับรูปทรงอื่น ๆ ซึ่งอาจไม่คล้ายกับรูปทรงแรกมากนัก
สำหรับการประมาณเราใช้ฟังก์ชันประมาณ โพลีดีพี ของ openCV ซึ่งอธิบายไว้ด้านล่าง
cv2.approxPolyDP (รูปร่าง, ความแม่นยำในการประมาณ, ปิด)
พารามิเตอร์:
- Contour - คือรูปทรงส่วนบุคคลที่เราต้องการประมาณ
- ความแม่นยำในการประมาณ - พารามิเตอร์ที่สำคัญในการกำหนดความแม่นยำของการประมาณค่าขนาดเล็กให้การประมาณที่แม่นยำค่าขนาดใหญ่ให้ข้อมูลทั่วไปมากขึ้น กฎทั่วไปที่ดีคือน้อยกว่า 5% ของเส้นขอบรูปทรง
- ปิด - ค่าบูลีนที่ระบุว่ารูปทรงโดยประมาณสามารถเปิดหรือปิดได้
ลองประมาณตัวเลขง่ายๆของบ้าน
นำเข้าnumpy เป็น np import cv2
โหลดภาพและเก็บสำเนา
image = cv2.imread ('house.jpg') orig_image = image.copy () cv2.imshow ('ภาพต้นฉบับ', orig_image) cv2.waitKey (0)
โทนสีเทาและสองมิติของภาพ
grey = cv2.cvtColor (รูปภาพ, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold (สีเทา, 127,255, cv2.THRESH_BINARY_INV)
ค้นหารูปทรง
_, รูปทรง, ลำดับชั้น = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
วนซ้ำผ่านแต่ละเส้นและคำนวณกรอบสี่เหลี่ยม
สำหรับ c ในรูปทรง: x, y, w, h = cv2.boundingRect (c) cv2.rectangle (orig_image, (x, y), (x + w, y + h), (0,0,255), 2) cv2.imshow ('Bounding rect', orig_image) cv2.waitKey (0)
วนซ้ำผ่านแต่ละเส้นและคำนวณเส้นโครงร่างโดยประมาณ
สำหรับ c ในรูปทรง:
# คำนวณความแม่นยำเป็นเปอร์เซ็นต์ของ ความแม่นยำ ของเส้นขอบรูปทรง= 0.03 * cv2.arcLength (c, True) ประมาณ = cv2.approxPolyDP (c, ความถูกต้อง, True) cv2.drawContours (ภาพ, 0, (0,255,0), 2) cv2.imshow ('ประมาณ polyDP', รูปภาพ) cv2.waitKey (0) cv2.destroyAllWindows ()
4. นูนฮัลล์
ตัวถังนูนเป็นขอบด้านนอกซึ่งแสดงด้วยการลากเส้นเหนือรูปที่กำหนด
อาจเป็นรูปหลายเหลี่ยมที่เล็กที่สุดที่สามารถพอดีกับวัตถุนั้นเอง
import cv2 import numpy เป็น np image = cv2.imread ('star.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) cv2.imshow ('original image', image) cv2.waitKey (0)
จำกัด รูปภาพ
ret, thresh = cv2.threshold (สีเทา, 176,255,0)
ค้นหารูปทรง
_, รูปทรง, ลำดับชั้น = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
จัดเรียงรูปทรงตามพื้นที่แล้วลบเส้นโครงร่างที่ใหญ่ที่สุด
n = len (รูปทรง) -1 รูปทรง = เรียงลำดับ (รูปทรง, คีย์ = cv2.contourArea, ย้อนกลับ = เท็จ)
วนซ้ำตามรูปทรงและวาดตัวถังนูน
สำหรับ c ในรูปทรง:
hull = cv2.convexHull (c) cv2.drawContours (รูปภาพ, 0, (0,255,0), 2) cv2.imshow ('ตัวถังนูน', รูปภาพ) cv2.waitKey (0) cv2.destroyAllWindows ()
5. การจับคู่ Contour ตามรูปร่าง
cv2.matchShapes (เทมเพลตรูปร่าง, วิธีเส้นขอบ, พารามิเตอร์วิธีการ)
ผลลัพธ์ - ค่าการจับคู่ (ค่าที่ต่ำกว่าหมายถึงการจับคู่ที่ใกล้กว่า)
เทมเพลตรูปร่าง - นี่คือเส้นอ้างอิงของเราที่เราพยายามค้นหาในภาพใหม่
รูปร่าง - รูปร่างแต่ละส่วนที่เรากำลังตรวจสอบ
วิธีการ - ประเภทของการจับคู่รูปร่าง (1,2,3)
พารามิเตอร์วิธีการ - ปล่อยให้อยู่คนเดียวเป็น 0.0 (ไม่ได้ใช้ใน python opencv)
import cv2 import numpy เป็น np
โหลดเทมเพลตรูปร่างหรือรูปภาพอ้างอิง
template = cv2.imread ('star.jpg', 0) cv2.imshow ('เทมเพลต', เทมเพลต) cv2.waitKey (0)
โหลดรูปภาพเป้าหมายด้วยรูปร่างที่เราพยายามจับคู่
target = cv2.imread ('shapestomatch.jpg') สีเทา = cv2.cvtColor (เป้าหมาย, cv2.COLOR_BGR2GRAY)
กำหนดทั้งสองภาพก่อนที่จะใช้ cv2.findContours
ret, thresh1 = cv2.threshold (template, 127,255,0) ret, thresh2 = cv2.threshold (สีเทา, 127,255,0)
ค้นหารูปทรงในเทมเพลต
_, contours, hierarhy = cv2.findContours (thresh1, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) # เราจำเป็นต้องเรียงลำดับรูปทรงตามพื้นที่เพื่อที่เราจะได้ลบรูปร่างที่ใหญ่ที่สุดซึ่งก็คือ
โครงร่างภาพ
sorted_contours = เรียงลำดับ (contours, key = cv2.contourArea, reverse = True) # เราแยกรูปทรงที่ใหญ่เป็นอันดับสองซึ่งจะเป็นเทมเพลตของเรา contour tempelate_contour = contours # แยกรูปทรงจากรูปภาพเป้าหมายที่สอง _, รูปทรง, ลำดับชั้น = cv2.findContours (thresh2, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) สำหรับ c ในรูปทรง: #iterate ผ่านแต่ละเส้นในภาพเป้าหมายและใช้ cv2.matchShape เพื่อเปรียบเทียบการ จับคู่ รูปร่างรูปร่าง= cv2.matchShapes (tempelate_contour, c, 1,0.0) พิมพ์ ("match") ค่าการจับคู่ #if น้อยกว่า 0.15 ถ้าตรงกัน <0.16: closest_contour = c else: closest_contour = cv2.drawContours (เป้าหมาย, - 1, (0,255,0), 3) cv2.imshow ('output', เป้าหมาย) cv2.waitKey (0) cv2.destroyAllWindows ()
เอาต์พุตคอนโซล -
0.16818605122199104
0.19946910256158912
0.18949760627309664
0.11101058276281539
มีสามวิธีที่แตกต่างกันซึ่งมีฟังก์ชันคณิตศาสตร์ที่แตกต่างกันเราสามารถทดลองกับแต่ละวิธีได้โดยเพียงแค่แทนที่ค่าวิธี cv2.matchShapes (tempelate_contour, c, 1, 0.0) ซึ่งแตกต่างกันไปตั้งแต่ 1,2 และ 3 สำหรับแต่ละค่าคุณจะได้การจับคู่ที่แตกต่างกัน ค่าในเอาต์พุตคอนโซล
6. การระบุรูปร่าง (วงกลมสี่เหลี่ยมผืนผ้าสามเหลี่ยมสี่เหลี่ยมจัตุรัสดาว)
นอกจากนี้ยังสามารถใช้ OpenCV เพื่อตรวจจับรูปร่างประเภทต่างๆโดยอัตโนมัติจากภาพ ด้วยการใช้โค้ดด้านล่างนี้เราจะสามารถตรวจจับวงกลมสี่เหลี่ยมผืนผ้าสามเหลี่ยมสี่เหลี่ยมและดาวจากรูปภาพได้
import cv2 import numpy เป็น np
โหลดภาพสเกลสีเทาแล้ว
image = cv2.imread ('shapes.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) cv2.imshow ('การระบุรูปร่าง', รูปภาพ) cv2.waitKey (0) ret, thresh = cv2.threshold (สีเทา, 127,255,1)
แยกรูปทรง
_, รูปทรง, ลำดับชั้น = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
สำหรับ cnt ในรูปทรง:
รับรูปหลายเหลี่ยม โดยประมาณประมาณ = cv2.approxPolyDP (cnt, 0.01 * cv2.arcLength (cnt, True), True) ถ้า len (โดยประมาณ) == 3: shape_name = "Triangle" cv2.drawContours (image,, 0, (0,255, 0), - 1)
ค้นหาศูนย์เส้นขอบเพื่อวางข้อความที่กึ่งกลาง
M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (รูปภาพ, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0, 0), 1) elif len (โดยประมาณ) == 4: x, y, w, h = cv2.boundingRect (cnt) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / ม.)
ตรวจสอบดูว่ารูปหลายเหลี่ยมทั้งสี่ด้านนั้นเป็นสี่เหลี่ยมจัตุรัสหรือสี่เหลี่ยมผืนผ้า
# cv2.boundingRect ส่งกลับความกว้างและความสูงด้านซ้ายเป็นพิกเซลโดยเริ่มจาก มุม บน# ด้านซ้ายสำหรับรูปสี่เหลี่ยมจัตุรัสจะเท่ากันโดยประมาณถ้า abs (wh) <= 3: shape_name = "square" #find contour center เพื่อวางข้อความที่ ศูนย์ cv2.drawContours (รูปภาพ, 0, (0,125,255), - 1) cv2.putText (รูปภาพ, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) อื่น ๆ: shape_name = "Reactangle" #find contour center เพื่อวางข้อความที่ศูนย์กลาง cv2.drawContours (image, 0, (0,0,255), - 1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (รูปภาพ, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) elif len (โดยประมาณ) == 10: shape_name = 'ดาว' cv2.drawContours (รูปภาพ, 0, (255,255,0), - 1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (รูปภาพ shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) elif len (ประมาณ)> = 15: shape_name = 'circle' cv2.drawContours (รูปภาพ, 0, (0,255,255), -1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (รูปภาพ, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) cv2.imshow ('การระบุรูปร่าง', รูปภาพ) cv2.waitKey (0) cv2.destroyAllWindows ()
7. การตรวจจับสาย
การตรวจจับเส้นเป็นแนวคิดที่สำคัญมากในOpenCVและมีแนวโน้มการใช้งานในโลกแห่งความเป็นจริง รถยนต์ที่เป็นอิสระใช้อัลกอริธึมการตรวจจับเส้นเพื่อตรวจจับเลนและถนน
ในการตรวจจับสายเราจะจัดการกับสองอัลกอริทึม
- อัลกอริทึม Hough Line
- Probalistic Hough สายอัลกอริทึม
คุณอาจจำการแสดงเส้นจากคณิตศาสตร์ระดับมัธยมศึกษาตอนปลายด้วยสมการy = mx + c
อย่างไรก็ตามในบรรทัด OpenCV จะแสดงด้วยวิธีอื่น
สมการด้านบนρ = xcosӨ + ysincosӨคือการแสดง OpenCV ของเส้นโดยที่ρคือระยะตั้งฉากของเส้นจากจุดกำเนิดและӨคือมุมที่เกิดจากค่าปกติของเส้นนี้ไปยังจุดกำเนิด (วัดเป็นเรเดียนโดยที่ 1pi เรเดียน / 180 = 1 องศา)
ฟังก์ชัน OpenCV สำหรับการตรวจจับเส้นจะได้รับเป็น
cv2.HoughLines (ภาพทวิภาค, ρความแม่นยำ, Өความแม่นยำ, เกณฑ์) โดยเกณฑ์คือการโหวตขั้นต่ำเพื่อให้ถือว่าเป็นเส้น
ตอนนี้เรามาตรวจหาเส้นสำหรับภาพกล่องด้วยความช่วยเหลือของฟังก์ชัน Hough line ของ opencv
import cv2 import numpy เป็น np image = cv2.imread ('box.jpg')
ดึงขอบสีเทาและขอบเรียบ
สีเทา = cv2.cvtColor (รูปภาพ, cv2.COLOR_BGR2GRAY) ขอบ = cv2.Canny (สีเทา, 100,170, apertureSize = 3)
เรียกใช้ Hough lines โดยใช้ความแม่นยำ rho ที่ 1 พิกเซล
#theta ความแม่นยำของ (np.pi / 180) ซึ่งเป็น 1 องศา #line threshold ถูกตั้งค่าเป็น 240 (จำนวนจุดบนบรรทัด) เส้น = cv2 เส้นโครงร่าง (ขอบ, 1, np.pi / 180, 240) # เราทำซ้ำ ผ่านแต่ละบรรทัดและแปลงเป็นรูปแบบ # ต้องการโดย cv2.lines (เช่นต้องการจุดสิ้นสุด) สำหรับ i ในช่วง (0, len (เส้น)): สำหรับ rho, theta ในบรรทัด: a = np.cos (theta) b = np.sin (theta) x0 = a * rho y0 = b * rho x1 = int (x0 + 1000 * (- b)) y1 = int (y0 + 1000 * (a)) x2 = int (x0-1000 * (-b)) y2 = int (y0-1000 * (a)) cv2.line (รูปภาพ, (x1, y1), (x2, y2), (0,255,0), 2) cv2.imshow ('hough lines', รูปภาพ) cv2.waitKey (0) cv2.destroyAllWindows ()
ตอนนี้ขอทำซ้ำการตรวจจับบรรทัดด้านบนกับอัลกอริทึมอื่น ๆ ของเส้น Hough ที่น่าจะเป็น
แนวคิดเบื้องหลังเส้น Hough ที่น่าจะเป็นคือการสุ่มจุดย่อยที่เพียงพอสำหรับการตรวจจับเส้น
ฟังก์ชัน OpenCV สำหรับเส้น Hough ที่น่าจะเป็นจะแสดงเป็น cv2
ตอนนี้เรามาตรวจหาเส้นกล่องด้วยความช่วยเหลือของเส้น Hough ที่น่าจะเป็น
import cv2 import numpy เป็น np
ดึงขอบสีเทาและขอบเรียบ
image = cv2.imread ('box.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) edge = cv2.Canny (grey, 50,150, apertureSize = 3) #again เราใช้ความแม่นยำของ rho และ theta เดียวกัน # อย่างไรก็ตาม เราระบุการโหวตขั้นต่ำ (คะแนนตามแนวเส้น) ที่ 100 # และความยาวบรรทัดขั้นต่ำ 5 พิกเซลและช่องว่างสูงสุดระหว่างบรรทัด 10 พิกเซล เส้น = cv2 HoughLinesP (ขอบ 1, np.pi / 180,100,100,10) สำหรับ i ในช่วง (0, len (เส้น)): สำหรับ x1, y1, x2, y2 ในบรรทัด: cv2.line (รูปภาพ, (x1, y1), (x2, y2), (0,255,0), 3) cv2 imshow ('เส้น hough probalistic', รูปภาพ) cv2.waitKey (0) cv2.destroyAllWindows
8. การตรวจจับหยด
Blobs สามารถอธิบายได้ว่าเป็นกลุ่มของพิกเซลที่เชื่อมต่อซึ่งทั้งหมดใช้คุณสมบัติร่วมกัน วิธีการใช้ตัวตรวจจับหยด OpenCV อธิบายไว้ในผังงานนี้
สำหรับการวาดประเด็นสำคัญเราใช้ cv2.drawKeypoints ซึ่งรับอาร์กิวเมนต์ต่อไปนี้
cv2.drawKeypoints (ภาพอินพุต, จุดสำคัญ, blank_output_array, สี, ธง)
ในแฟล็กอาจอยู่ที่ไหน
cv2.DRAW_MATCHES_FLAGS_DEFAULT
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
และช่องว่างตรงนี้ไม่มีอะไรมากนอกจากเมทริกซ์ของศูนย์ทีละเมทริกซ์
ตอนนี้เรามาทำการตรวจจับหยดบนภาพของดอกทานตะวันโดยที่หยดจะเป็นส่วนกลางของดอกไม้เหมือนที่พบได้ทั่วไปในบรรดาดอกไม้ทั้งหมด
import cv2 import numpy เป็น np image = cv2.imread ('Sunflowers.jpg', cv2.IMREAD_GRAYSCALE)
ตั้งค่าตัวตรวจจับด้วยพารามิเตอร์เริ่มต้น
เครื่องตรวจจับ = cv2.SimpleBlobDetector_create ()
ตรวจจับ blobs
จุดสำคัญ = detector.detect (ภาพ)
วาด blobs ที่ตรวจพบเป็นวงกลมสีแดง
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ให้แน่ใจว่า #size ของวงกลมตรงกับขนาดของ blob blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (รูปภาพ, จุดสำคัญ, ว่าง, (0,255,255), cv2.DRAWDEF_MATCH_MATCH
แสดงประเด็นสำคัญ
cv2.imshow ('blobs', blobs) cv2.waitKey (0) cv2.destroyAllWindows ()
แม้ว่ารหัสจะใช้งานได้ดี แต่บางจุดก็พลาดไปเนื่องจากขนาดของดอกไม้ที่ไม่เท่ากันเนื่องจากดอกไม้ที่อยู่ด้านหน้ามีขนาดใหญ่เมื่อเทียบกับดอกไม้ที่อยู่ด้านท้าย
9. การกรอง Blobs - การนับวงกลมและวงรี
เราสามารถใช้พารามิเตอร์ในการกรอง blobs ตามรูปร่างขนาดและสี สำหรับการใช้พารามิเตอร์กับเครื่องตรวจจับหยดเราใช้ฟังก์ชันของ OpenCV
cv2.SimpleBlobDetector_Params ()
เราจะเห็นการกรอง blobs โดยส่วนใหญ่พารามิเตอร์ทั้งสี่นี้ตามรายการด้านล่าง:
พื้นที่
params.filterByArea = True / False params.minArea = พิกเซล params.maxArea = พิกเซล
ความเป็นวงกลม
params.filterByCircularity = True / False params.minCircularity = 1 กำลังสมบูรณ์ 0 อยู่ตรงข้าม
Convexity - พื้นที่ของหยด / พื้นที่ของตัวถังนูน
params.filterByConvexity = True / False params.minConvexity = พื้นที่
ความเฉื่อย
params.filterByInertia = True / False params.minInertiaRatio = 0.01
ตอนนี้เรามาลองกรอง blobs ตามพารามิเตอร์ที่กล่าวถึงข้างต้น
import cv2 import numpy เป็น np image = cv2.imread ('blobs.jpg') cv2.imshow ('original image', image) cv2.waitKey (0)
เริ่มต้นตัวตรวจจับโดยใช้พารามิเตอร์เริ่มต้น
เครื่องตรวจจับ = cv2.SimpleBlobDetector_create ()
ตรวจจับ blobs
จุดสำคัญ = detector.detect (ภาพ)
วาด blobs บนภาพของเราเป็นวงกลมสีแดง
blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (รูปภาพ, จุดสำคัญ, ว่าง, (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) number_of_blobs = len (จุดสำคัญ) text = "จำนวน blobs ทั้งหมด" + str (len (จุดสำคัญ)) cv2.putText (blobs, text, (20,550), cv2.FONT_HERSHEY_SIMPLEX, 1, (100,0,255), 2)
แสดงภาพด้วยจุดสำคัญหยด
cv2.imshow ('หยดโดยใช้พารามิเตอร์เริ่มต้น', blobs) cv2.waitKey (0)
ตั้งค่าพารามิเตอร์การกรองของเรา
#initialize การตั้งค่าพารามิเตอร์โดยใช้ cv2.SimpleBlobDetector params = cv2.SimpleBlobDetector_Params ()
ตั้งค่าพารามิเตอร์การกรองพื้นที่
params.filterByArea = True params.minArea = 100
ตั้งค่าพารามิเตอร์การกรองแบบวงกลม
params.filterByCircularity = True params.minCircularity = 0.9
ตั้งค่าพารามิเตอร์การกรองแบบนูน
params.filterByConvexity = พารามิเตอร์เท็จ minConvexity = 0.2
ตั้งค่าพารามิเตอร์การกรองความเฉื่อย
params.filterByInertia = True params.minInertiaRatio = 0.01
สร้างเครื่องตรวจจับด้วยพารามิเตอร์
เครื่องตรวจจับ = cv2.SimpleBlobDetector_create (params)
ตรวจจับ blobs
จุดสำคัญ = detector.detect (ภาพ)
วาดจุดบนภาพเป็นวงกลมสีแดง
blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (รูปภาพ, จุดสำคัญ, ว่าง, (0,255,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) number_of_blobs = len (จุดสำคัญ) ข้อความ = "จำนวนวงกลมทั้งหมด" + str (len (จุดสำคัญ)) cv2.putText (blobs, text, (20,550), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,100,255), 2)
แสดง blobs
cv2.imshow ('การกรอง blobs วงกลม', blobs) cv2.waitKey (0) cv2.destroyAllWindows ()
นี่คือวิธีการแบ่งส่วนภาพใน Python-OpenCV เพื่อให้เข้าใจถึงวิสัยทัศน์ของคอมพิวเตอร์และ OpenCV ได้ดีให้อ่านบทความก่อนหน้านี้ (เริ่มต้นใช้งาน Python OpenCV และ Image Manipulations ใน Python OpenCV และคุณจะสามารถสร้างสิ่งที่ยอดเยี่ยมด้วย Computer Vision