- 1. Phân đoạn và đường viền
- 2. Chế độ phân cấp và truy xuất
- 3. Xấp xỉ các đường viền và tìm vỏ lồi của chúng
- 4. Lồi Hull
- 5. Khớp đường viền theo hình dạng
- 6. Nhận dạng Hình dạng (hình tròn, hình chữ nhật, hình tam giác, hình vuông, ngôi sao)
- 7. Phát hiện dòng
- 8. Phát hiện khối
- 9. Lọc các đốm màu - Đếm vòng tròn và hình elip
Trong các hướng dẫn trước, chúng tôi đã sử dụng OpenCV để xử lý hình ảnh cơ bản và thực hiện một số thao tác chỉnh sửa hình ảnh nâng cao. Như chúng ta đã biết, OpenCV là Thư viện nguồn mở Commuter Vision có giao diện C ++, Python và Java và hỗ trợ Windows, Linux, Mac OS, iOS và Android. Vì vậy, nó có thể dễ dàng cài đặt trong Raspberry Pi với môi trường Python và Linux. Và Raspberry Pi với OpenCV và camera kèm theo có thể được sử dụng để tạo nhiều ứng dụng xử lý hình ảnh thời gian thực như Nhận diện khuôn mặt, khóa khuôn mặt, theo dõi đối tượng, phát hiện biển số ô tô, Hệ thống an ninh gia đình, v.v. Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách làm phân đoạn hình ảnh bằng OpenCV. Các hoạt động chúng tôi sẽ thực hiện được liệt kê dưới đây:
- Phân đoạn và đường viền
- Hệ thống phân cấp và chế độ truy xuất
- Gần đúng các đường bao và tìm thân tàu lồi của chúng
- Conex Hull
- Phù hợp với đường viền
- Nhận dạng hình dạng (hình tròn, hình chữ nhật, hình tam giác, hình vuông, ngôi sao)
- Phát hiện dòng
- Phát hiện đốm màu
- Lọc các đốm màu - đếm vòng tròn và hình elip
1. Phân đoạn và đường viền
Phân đoạn ảnh là một quá trình chúng ta phân vùng ảnh thành các vùng khác nhau. Trong khi các đường bao là các đường hoặc đường cong liên tục ràng buộc hoặc bao phủ toàn bộ ranh giới của một đối tượng trong một hình ảnh. Và, ở đây chúng tôi sẽ sử dụng kỹ thuật phân đoạn hình ảnh được gọi là đường viền để trích xuất các phần của hình ảnh.
Ngoài ra, các đường viền cũng rất quan trọng trong
- Phát hiện đối tượng
- Phân tích hình dạng
Và chúng có rất nhiều lĩnh vực ứng dụng rộng rãi từ phân tích hình ảnh thế giới thực đến phân tích hình ảnh y tế như trong MRI
Hãy biết cách triển khai các đường bao trong opencv, bằng cách trích xuất các đường bao của hình vuông.
import cv2 import numpy as np
Hãy tải một hình ảnh đơn giản với 3 hình vuông màu đen
image = cv2.imread ('square.jpg') cv2.imshow ('input image', image) cv2.waitKey (0)
Thang độ xám
màu xám = cv2.cvtColor (hình ảnh, cv2.COLOR_BGR2GRAY)
Tìm các cạnh canny
edged = cv2.Canny (xám, 30.200) cv2.imshow ('canny edge', edged) cv2.waitKey (0)
Tìm đường viền
# sử dụng bản sao hình ảnh của bạn, ví dụ - edged.copy (), vì việc tìm kiếm các đường bao làm thay đổi hình ảnh # chúng ta phải thêm _, trước các đường viền dưới dạng đối số trống do nâng cấp phiên bản OpenCV _, contours, hierarchy = cv2.findContours (edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cv2.imshow ('canny edge after contouring', edged) cv2.waitKey (0)
In tệp đường bao để biết đường bao gồm những gì
print (contours) print ('Số đường viền được tìm thấy =' + str (len (contours)))
Vẽ tất cả các đường viền
#use -1 làm tham số thứ 3 để vẽ tất cả các đường bao cv2.drawContours (hình ảnh, đường viền, -1, (0,255,0), 3) cv2.imshow ('đường viền', hình ảnh) cv2.waitKey (0) cv2. killAllWindows ()
Đầu ra bảng điều khiển -],],], …,],],]], dtype = int32), mảng(],],
], …,
],],]], dtype = int32), array (],],], …,],],]], dtype = int32)]
Số đường viền tìm được = 3. Vì vậy, chúng tôi đã tìm thấy tổng cộng ba đường viền.
Bây giờ, trong đoạn mã trên, chúng tôi cũng đã in tệp đường bao bằng cách sử dụng , tệp này cho biết các đường bao này trông như thế nào, như được in trong đầu ra bảng điều khiển ở trên.
Trong đầu ra bảng điều khiển ở trên, chúng ta có một ma trận trông giống như tọa độ của các điểm x, y. OpenCV lưu trữ các đường bao trong một danh sách các danh sách. Chúng ta có thể hiển thị đầu ra bảng điều khiển ở trên như sau:
CONTOUR 1 CONTOUR 2 CONTOUR 3
], mảng (], mảng (],],],],],],],
…,…,…,],],],],],],]], dtype = int32),]], dtype = int32),]], dtype = int32)]
Bây giờ, khi chúng ta sử dụng hàm độ dài trên tệp đường viền, chúng ta nhận được độ dài bằng 3, nghĩa là có ba danh sách danh sách trong tệp đó, tức là ba đường viền.
Bây giờ, hãy tưởng tượng CONTOUR 1 là phần tử đầu tiên trong mảng đó và danh sách đó chứa danh sách tất cả các tọa độ và các tọa độ này là các điểm dọc theo các đường bao mà chúng ta vừa thấy, dưới dạng các hộp hình chữ nhật màu xanh lá cây.
Có nhiều phương pháp khác nhau để lưu trữ các tọa độ này và chúng được gọi là phương pháp xấp xỉ, về cơ bản phương pháp xấp xỉ có hai loại
- cv2.CHAIN_APPROX_NONE
- cv2.CHAIN_APPROX_SIMPLE
cv2.CHAIN_APPROX_NONE lưu trữ tất cả các điểm biên, nhưng chúng ta không nhất thiết phải cần tất cả các điểm biên, nếu điểm tạo thành một đường thẳng, chúng ta chỉ cần điểm bắt đầu và điểm kết thúc trên đường đó.
cv2.CHAIN_APPROX_SIMPLE thay vào đó chỉ cung cấp điểm bắt đầu và điểm cuối của các đường bao, kết quả là lưu trữ thông tin về đường bao hiệu quả hơn nhiều.
_, contours, hierarchy = cv2.findContours (edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
Trong đoạn mã trên, cv2.RETR_EXTERNAL là chế độ truy xuất trong khi cv2.CHAIN_APPROX_NONE là
phương pháp xấp xỉ.
Như vậy là chúng ta đã tìm hiểu về đường bao và phương pháp tính gần đúng, bây giờ chúng ta cùng khám phá hệ thống phân cấp và chế độ truy xuất.
2. Chế độ phân cấp và truy xuất
Chế độ truy xuất xác định hệ thống phân cấp trong các đường viền như đường bao phụ, đường viền bên ngoài hoặc tất cả các đường viền.
Bây giờ có bốn chế độ truy xuất được sắp xếp theo các kiểu phân cấp.
cv2.RETR_LIST - truy xuất tất cả các đường bao.
cv2.RETR_EXTERNAL - chỉ truy xuất các đường viền bên ngoài hoặc bên ngoài.
cv2.RETR_CCOMP - truy xuất tất cả trong hệ thống phân cấp 2 cấp.
cv2.RETR_TREE - truy xuất tất cả trong một hệ thống phân cấp đầy đủ.
Hệ thống phân cấp được lưu trữ ở định dạng sau
Bây giờ, hãy minh họa sự khác biệt giữa hai chế độ truy xuất đầu tiên, cv2.RETR_LIST và cv2.RETR_EXTERNAL.
import cv2 import numpy as np
Cho phép tải một hình ảnh đơn giản với 3 hình vuông màu đen
image = cv2.imread ('square donut.jpg') cv2.imshow ('input image', image) cv2.waitKey (0)
Thang độ xám
màu xám = cv2.cvtColor (hình ảnh, cv2.COLOR_BGR2GRAY)
Tìm Canny Edges
edged = cv2.Canny (xám, 30.200) cv2.imshow ('canny edge', edged) cv2.waitKey (0)
Tìm đường viền
# sử dụng bản sao hình ảnh của bạn, ví dụ - edged.copy (), vì việc tìm kiếm các đường bao làm thay đổi hình ảnh # chúng ta phải thêm _, trước đường viền làm đối số trống do nâng cấp phiên bản cv mở _, đường viền, hệ thống phân cấp = cv2.findContours (edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cv2.imshow ('canny edge after contouring', edged) cv2.waitKey (0)
In tệp đường bao để biết đường bao gồm những gì.
print (contours) print ('Số đường viền được tìm thấy =' + str (len (contours)))
Vẽ tất cả các đường viền
#use -1 làm tham số thứ 3 để vẽ tất cả các đường bao cv2.drawContours (hình ảnh, đường viền, -1, (0,255,0), 3) cv2.imshow ('đường viền', hình ảnh) cv2.waitKey (0) cv2. killAllWindows
import cv2 import numpy as np
Cho phép tải một hình ảnh đơn giản với 3 hình vuông màu đen
image = cv2.imread ('square donut.jpg') cv2.imshow ('input image', image) cv2.waitKey (0)
Thang độ xám
màu xám = cv2.cvtColor (hình ảnh, cv2.COLOR_BGR2GRAY)
Tìm các cạnh canny
edged = cv2.Canny (xám, 30.200) cv2.imshow ('canny edge', edged) cv2.waitKey (0)
Tìm đường viền
# sử dụng bản sao hình ảnh của bạn, ví dụ - edged.copy (), vì việc tìm kiếm các đường viền làm thay đổi hình ảnh # chúng ta phải thêm _, trước đường viền làm đối số trống do nâng cấp phiên bản cv mở _, đường viền, hệ thống phân cấp = cv2.findContours (edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) cv2.imshow ('canny edge after contouring', edged) cv2.waitKey (0)
In tệp đường bao để biết đường bao gồm những gì.
print (contours) print ('Số đường viền được tìm thấy =' + str (len (contours)))
Vẽ tất cả các đường viền
#use -1 làm tham số thứ 3 để vẽ tất cả các đường bao cv2.drawContours (hình ảnh, đường viền, -1, (0,255,0), 3) cv2.imshow ('đường viền', hình ảnh) cv2.waitKey (0) cv2. killAllWindows ()
Vì vậy, thông qua việc trình diễn các mã trên, chúng ta có thể thấy rõ ràng sự khác biệt giữa cv2.RETR_LIST và cv2.RETR_EXTERNNAL , trong cv2.RETR_EXTERNNAL chỉ các đường viền bên ngoài được tính đến trong khi các đường viền bên trong bị bỏ qua.
Trong khi trong cv2.RETR_LIST các đường viền bên trong cũng đang được tính đến.
3. Xấp xỉ các đường viền và tìm vỏ lồi của chúng
Trong các đường bao gần đúng, một hình dạng đường bao được xấp xỉ trên một hình dạng đường bao khác, hình dạng này có thể không giống lắm với hình dạng đường bao đầu tiên.
Đối với xấp xỉ chúng tôi sử dụng approxPolyDP chức năng của OpenCV được giải thích dưới đây
cv2.approxPolyDP (đường bao, độ chính xác xấp xỉ, đã đóng)
Thông số:
- Đường bao - là đường bao riêng lẻ mà chúng tôi muốn tính gần đúng.
- Độ chính xác xấp xỉ - thông số quan trọng trong việc xác định độ chính xác của phép gần đúng, giá trị nhỏ cho phép xấp xỉ chính xác, giá trị lớn cho nhiều thông tin chung chung. Quy tắc ngón tay cái tốt là nhỏ hơn 5% chu vi đường viền.
- Đã đóng - một giá trị Boolean cho biết liệu đường bao gần đúng có thể mở hay đóng.
Hãy thử tính gần đúng một hình đơn giản của một ngôi nhà
import numpy as np import cv2
Tải hình ảnh và giữ một bản sao
image = cv2.imread ('house.jpg') orig_image = image.copy () cv2.imshow ('ảnh gốc', orig_image) cv2.waitKey (0)
Thang độ xám và mã hóa hình ảnh
grey = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold (xám, 127,255, cv2.THRESH_BINARY_INV)
Tìm đường viền
_, contours, hierarchy = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
Lặp lại từng đường viền và tính toán hình chữ nhật giới hạn của chúng
cho c trong đường viền: x, y, w, h = cv2.bidingRect (c) cv2.rectangle (orig_image, (x, y), (x + w, y + h), (0,0,255), 2) cv2.imshow ('Ranh giới trực tràng', orig_image) cv2.waitKey (0)
Lặp lại từng đường viền và tính toán đường bao
cho c trong đường viền:
# tính toán độ chính xác theo phần trăm độ chính xác của chu vi đường viền = 0,03 * cv2.arcLength (c, True) xấp xỉ = cv2.approxPolyDP (c, độ chính xác, True) cv2.drawContours (hình ảnh, 0, (0,255,0), 2) cv2.imshow ('Khoảng polyDP', hình ảnh) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Lồi Hull
Thân tàu lồi về cơ bản là các cạnh bên ngoài, được biểu diễn bằng các đường vẽ trên một hình nhất định.
Nó có thể là hình đa giác nhỏ nhất có thể vừa với vật thể đó.
import cv2 import numpy as np image = cv2.imread ('star.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) cv2.imshow ('original image', image) cv2.waitKey (0)
Ngưỡng hình ảnh
ret, thresh = cv2.threshold (xám, 176,255,0)
Tìm đường viền
_, contours, hierarchy = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
Sắp xếp các đường viền theo khu vực và sau đó loại bỏ đường viền khung lớn nhất
n = len (contours) -1 contours = đã sắp xếp (contours, key = cv2.contourArea, reverse = False)
Lặp lại thông qua các đường viền và vẽ thân tàu lồi
cho c trong đường viền:
hull = cv2.convexHull (c) cv2.drawContours (image,, 0, (0,255,0), 2) cv2.imshow ('lồi hull', image) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Khớp đường viền theo hình dạng
cv2.matchShapes (mẫu đường bao, phương thức đường bao, tham số phương thức)
Đầu ra - giá trị khớp (giá trị thấp hơn có nghĩa là khớp gần hơn)
mẫu đường viền - Đây là đường viền tham chiếu của chúng tôi mà chúng tôi đang cố gắng tìm trong một hình ảnh mới.
đường viền - Đường viền riêng lẻ mà chúng tôi đang kiểm tra.
Phương pháp - Kiểu ăn khớp đường bao (1,2,3).
tham số phương thức - để nguyên là 0.0 (không được sử dụng trong python opencv)
import cv2 import numpy as np
Tải mẫu hình dạng hoặc hình ảnh tham chiếu
template = cv2.imread ('star.jpg', 0) cv2.imshow ('template', template) cv2.waitKey (0)
Tải hình ảnh mục tiêu với các hình dạng mà chúng tôi đang cố gắng khớp
target = cv2.imread ('shapestomatch.jpg') gray = cv2.cvtColor (target, cv2.COLOR_BGR2GRAY)
Đặt ngưỡng cả hai hình ảnh trước khi sử dụng cv2.findContours
ret, thresh1 = cv2.threshold (mẫu, 127,255,0) ret, thresh2 = cv2.threshold (xám, 127,255,0)
Tìm đường viền trong mẫu
_, contours, hierarhy = cv2.findContours (thresh1, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) # chúng ta cần sắp xếp các đường bao theo khu vực để chúng ta có thể loại bỏ đường bao lớn nhất là
Phác thảo hình ảnh
sorted_contours = sorted (contours, key = cv2.contourArea, reverse = True) # chúng tôi trích xuất đường bao lớn thứ hai sẽ là đường bao mẫu của chúng ta tempelate_contour = contours # cắt các đường viền từ hình ảnh đích thứ hai _, contours, hierarchy = cv2.findContours (thresh2, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) cho c trong contours: #iterate qua từng đường viền trong hình ảnh đích và sử dụng cv2.matchShape để so sánh hình dạng đường bao đối sánh = cv2.matchShapes (tempelate_contour, c, 1,0.0) print ("match") # nếu giá trị so khớp nhỏ hơn 0,15 nếu khớp <0,16: near_contour = c else: near_contour = cv2.drawContours (target,, - 1, (0,255,0), 3) cv2.imshow ('output',Mục tiêu) cv2.waitKey (0) cv2.destroyAllWindows ()
Đầu ra bảng điều khiển -
0,16818605122199104
0,19946910256158912
0,18949760627309664
0,11101058276281539
Có ba phương pháp khác nhau với các hàm toán học khác nhau, chúng ta có thể thử nghiệm với từng phương pháp bằng cách thay thế các giá trị phương pháp cv2.matchShapes (tempelate_contour, c, 1, 0.0) thay đổi từ 1,2 và 3, với mỗi giá trị, bạn sẽ nhận được kết quả phù hợp khác nhau giá trị trong đầu ra bảng điều khiển.
6. Nhận dạng Hình dạng (hình tròn, hình chữ nhật, hình tam giác, hình vuông, ngôi sao)
OpenCV cũng có thể được sử dụng để phát hiện các loại hình dạng khác nhau tự động từ hình ảnh. Bằng cách sử dụng mã dưới đây, chúng tôi sẽ có thể phát hiện hình tròn, hình chữ nhật, hình tam giác, hình vuông và các ngôi sao từ hình ảnh.
import cv2 import numpy as np
Tải và sau đó tải hình ảnh tỷ lệ xám
image = cv2.imread ('shape.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) cv2.imshow ('nhận dạng hình dạng', image) cv2.waitKey (0) ret, thresh = cv2.threshold (xám, 127,255,1)
Trích xuất đường viền
_, contours, hierarchy = cv2.findContours (thresh.copy (), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
Đối với cnt trong đường viền:
Nhận đa giác gần đúng xấp xỉ = cv2.approxPolyDP (cnt, 0,01 * cv2.arcLength (cnt, True), True) nếu len (khoảng) == 3: shape_name = "Triangle" cv2.drawContours (image,, 0, (0,255, 0), - 1)
tìm trung tâm đường viền để đặt văn bản ở trung tâm
M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (image, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0, 0), 1) elif len (xấp xỉ) == 4: x, y, w, h = cv2.bidingRect (cnt) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M)
Kiểm tra xem đa giác bốn cạnh đó là hình vuông hay hình chữ nhật
# cv2.bidingRect trả về chiều rộng và chiều cao bên trái tính bằng pixel, bắt đầu từ góc trên cùng #left, đối với hình vuông, nó sẽ gần giống nếu abs (wh) <= 3: shape_name = "square" #find contour center để đặt văn bản tại center cv2.drawContours (image,, 0, (0,125,255), - 1) cv2.putText (image, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) khác: shape_name = "Reactangle" # tìm tâm đường viền để đặt văn bản ở tâm cv2.drawContours (image,, 0, (0,0,255), - 1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (image, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) elif len (khoảng) == 10: shape_name = 'ngôi sao' cv2.drawContours (image,, 0, (255,255,0), - 1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (image, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) elif len (khoảng)> = 15: shape_name = 'circle' cv2.drawContours (image,, 0, (0,255,255), -1) M = cv2.moments (cnt) cx = int (M / M) cy = int (M / M) cv2.putText (image, shape_name, (cx-50, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1) cv2.imshow ('xác định hình dạng', hình ảnh) cv2.waitKey (0) cv2.destroyAllWindows ()
7. Phát hiện dòng
Phát hiện dòng là một khái niệm rất quan trọng trong OpenCV và có một ứng dụng đầy hứa hẹn trong thế giới thực. Xe ô tô tự lái sử dụng các thuật toán phát hiện đường để phát hiện làn đường và đường.
Trong phát hiện dòng, chúng tôi sẽ xử lý hai thuật toán,
- Thuật toán dòng Hough
- Thuật toán dòng Probalistic Hough.
Bạn có thể đã nhớ biểu diễn của đường trong toán học trung học với phương trình, y = mx + c.
Tuy nhiên, trong OpenCV dòng được biểu diễn bằng một cách khác
Phương trình trên ρ = xcosӨ + ysincosӨ là biểu diễn OpenCV của đường, trong đó ρ là khoảng cách vuông góc của đường từ điểm gốc và Ө là góc tạo bởi pháp tuyến của đường này tới điểm gốc (đo bằng radian, trong đó 1pi radian / 180 = 1 độ).
Hàm OpenCV để phát hiện dòng được cung cấp như
cv2.HoughLines (hình ảnh nhị phân, độ chính xác ρ, độ chính xác Ө, ngưỡng), trong đó ngưỡng là phiếu bầu tối thiểu để nó được coi là một đường.
Bây giờ chúng ta hãy phát hiện các đường cho một hình hộp với sự trợ giúp của hàm Hough line của opencv.
import cv2 import numpy as np image = cv2.imread ('box.jpg')
Đã trích xuất thang độ xám và các cạnh màu xám
grey = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) edge = cv2.Canny (xám, 100,170, khẩu độSize = 3)
Chạy các đường Hough sử dụng độ chính xác rho là 1 pixel
#theta độ chính xác của (np.pi / 180) là 1 độ # ngưỡng dòng được đặt thành 240 (số điểm trên dòng) lines = cv2.HoughLines (edge, 1, np.pi / 180, 240) #we lặp qua từng dòng và chuyển thành định dạng # được yêu cầu bởi cv2.lines (tức là yêu cầu điểm cuối) cho i trong phạm vi (0, len (lines)): cho rho, theta trong các dòng: 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 (image, (x1, y1), (x2, y2), (0,255,0), 2) cv2.imshow ('hough lines', image) cv2.waitKey (0) cv2.destroyAllWindows ()
Bây giờ chúng ta hãy lặp lại việc phát hiện dòng ở trên với thuật toán khác của dòng Hough theo xác suất.
Ý tưởng đằng sau đường Hough xác suất là lấy một tập hợp con ngẫu nhiên của các điểm đủ để phát hiện đường.
Hàm OpenCV cho đường Hough theo xác suất được biểu diễn dưới dạng cv2.HoughLinesP (hình ảnh được nhị phân hóa, độ chính xác ρ, độ chính xác Ө, ngưỡng, độ dài dòng tối thiểu, khoảng cách dòng tối đa)
Bây giờ chúng ta hãy phát hiện các đường hộp với sự trợ giúp của các đường Hough xác suất.
import cv2 import numpy as np
Thang màu xám và các cạnh màu xám được trích xuất
image = cv2.imread ('box.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) edge = cv2.Canny (gray, 50,150,pertureSize = 3) #again chúng tôi sử dụng cùng một độ chính xác rho và theta #however, chúng tôi chỉ định một phiếu bầu tối thiểu (pts dọc theo dòng) là 100 # và độ dài dòng tối thiểu là 5 pixel và khoảng cách tối đa giữa các dòng là 10 pixel lines = cv2.HoughLinesP (edge, 1, np.pi / 180,100,100,10) for i trong phạm vi (0, len (dòng)): cho x1, y1, x2, y2 trong các dòng: cv2.line (hình ảnh, (x1, y1), (x2, y2), (0,255,0), 3) cv2. imshow ('probalistic hough lines', image) cv2.waitKey (0) cv2.destroyAllWindows
8. Phát hiện khối
Các khối màu có thể được mô tả như một nhóm các pixel được kết nối mà tất cả đều có chung một thuộc tính. Phương pháp sử dụng bộ dò đốm màu OpenCV được mô tả thông qua biểu đồ này.
Để vẽ các điểm chính, chúng tôi sử dụng cv2.drawKeypoints lấy các đối số sau.
cv2.drawKeypoints (hình ảnh đầu vào, keypoints, blank_output_array, màu sắc, cờ)
nơi trong những lá cờ có thể được
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
và khoảng trống ở đây không có gì khác ngoài từng ma trận số không
Bây giờ chúng ta hãy thực hiện phát hiện đốm màu trên hình ảnh hoa hướng dương, trong đó các đốm màu sẽ là phần trung tâm của bông hoa vì chúng là điểm chung của tất cả các bông hoa.
import cv2 import numpy as np image = cv2.imread ('Sunflowers.jpg', cv2.IMREAD_GRAYSCALE)
Thiết lập bộ dò với các thông số mặc định
detector = cv2.SimpleBlobDetector_create ()
Phát hiện đốm màu
keypoints = detector.detect (hình ảnh)
Vẽ các đốm màu được phát hiện dưới dạng vòng tròn màu đỏ
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS đảm bảo # kích thước của hình tròn tương ứng với kích thước của blob blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (hình ảnh, keypoints, blank, (0,255,255), cv2.DRAW_MATCHES_)AGS_DEFAULTFLAW_MATCHES_)
Hiển thị các điểm chính
cv2.imshow ('blobs', đốm màu) cv2.waitKey (0) cv2.destroyAllWindows ()
Mặc dù mã hoạt động tốt nhưng một số đốm màu bị thiếu do kích thước của hoa không đồng đều như hoa ở phía trước to hơn so với hoa ở cuối.
9. Lọc các đốm màu - Đếm vòng tròn và hình elip
Chúng ta có thể sử dụng các thông số để lọc các đốm màu theo hình dạng, kích thước và màu sắc của chúng. Để sử dụng các tham số với trình dò đốm màu, chúng tôi sử dụng chức năng của OpenCV
cv2.SimpleBlobDetector_Params ()
Chúng ta sẽ thấy việc lọc các đốm màu chủ yếu theo bốn tham số được liệt kê bên dưới:
Khu vực
params.filterByArea = True / False params.minArea = pixel params.maxArea = pixel
Tính tuần hoàn
params.filterByCircularity = True / False params.minCircularity = 1 là hoàn hảo, 0 là ngược lại
Độ lồi - Diện tích đốm màu / diện tích vỏ lồi
params.filterByConvexity = True / False params.minConvexity = Diện tích
Quán tính
params.filterByInertia = True / False params.minInertiaRatio = 0,01
Bây giờ chúng ta hãy thử lọc các đốm màu theo các thông số đã đề cập ở trên
import cv2 import numpy as np image = cv2.imread ('blobs.jpg') cv2.imshow ('original image', image) cv2.waitKey (0)
Khởi tạo bộ dò bằng các tham số mặc định
detector = cv2.SimpleBlobDetector_create ()
Phát hiện đốm màu
keypoints = detector.detect (hình ảnh)
Vẽ các đốm màu trên hình ảnh của chúng tôi dưới dạng vòng tròn màu đỏ
blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (image, keypoints, blank, (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) number_of_blobs = len (keypoints) text = "total no of blobs" + str (len (keypoints)) cv2.putText (blobs, text, (20,550), cv2.FONT_HERSHEY_SIMPLEX, 1, (100,0,255), 2)
Hiển thị hình ảnh với các điểm chính blob
cv2.imshow ('blob sử dụng tham số mặc định', blob) cv2.waitKey (0)
Đặt các thông số lọc của chúng tôi
#initialize cài đặt thông số bằng cách sử dụng cv2.SimpleBlobDetector params = cv2.SimpleBlobDetector_Params ()
Đặt thông số lọc khu vực
params.filterByArea = True params.minArea = 100
Đặt thông số lọc tuần hoàn
params.filterByCircularity = True params.minCircularity = 0.9
Đặt thông số lọc độ lồi
params.filterByConvexity = Sai params.minConvexity = 0,2
Đặt thông số lọc quán tính
params.filterByInertia = True params.minInertiaRatio = 0,01
Tạo máy dò với tham số
detector = cv2.SimpleBlobDetector_create (params)
Phát hiện đốm màu
keypoints = detector.detect (hình ảnh)
Vẽ các đốm màu trên hình ảnh dưới dạng vòng tròn màu đỏ
blank = np.zeros ((1,1)) blobs = cv2.drawKeypoints (image, keypoints, blank, (0,255,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) number_of_blobs = len (keypoints) text = "tổng số không có đốm tròn" + str (len (keypoints)) cv2.putText (blobs, text, (20,550), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,100,255), 2)
Hiển thị các đốm màu
cv2.imshow ('lọc đốm màu tròn', đốm màu) cv2.waitKey (0) cv2.destroyAllWindows ()
Vì vậy, đây là cách phân đoạn hình ảnh có thể được thực hiện trong Python-OpenCV. Để hiểu rõ hơn về tầm nhìn máy tính và OpenCV, hãy xem qua các bài viết trước (Bắt đầu với Python OpenCV và Thao tác hình ảnh trong Python OpenCV và bạn sẽ có thể tạo ra điều gì đó thú vị với Computer Vision.