Đếm các đồng xu nằm chồng bằng OpenCV

Bài này hướng dẫn các đếm các đồng xu nằm chồng bằng OpenCV. Sử dụng 2 thuật toán chính là WatershedDistanceTransform.

Đếm đối tượng có hình dạng đơn giản và không dính nhau khá là dễ. Chỉ cần lấy biên từ ảnh nhị phân thì chúng ta có thể biết được số lượng đường biên. Nhưng nếu đối tượng dính nhau hoặc đè chồng, thì khó hơn 1 chút.

Với những lá bài đè chồng lên nhau như hình dưới thì khi nhị phân hóa sẽ thành 1 blob duy nhất. Trong thực tế các dây chuyền sản xuất cũng có những sản phẩm nằm chồng lên nhau đôi chút.

2_play_card 2_play_card_binary


Thuật toán Watershed

Watershed là thuật toán xử lý hình ảnh nhằm tách đối tượng khỏi background. Thuật toán có input là ảnh xám và 1 ảnh gọi là ảnh marker. Ảnh marker là ảnh mà bạn cho thuật toán Watershed biết đâu là đối tượng foreground và background. Ảnh market là ảnh nhị phân tương tự như mask và có cùng size với ảnh xám.

Hình dưới ảnh xám được đánh dấu thủ công để tách con đường ra khỏi cảnh. Đưa ảnh nguồn và ảnh đánh dấu vào thì thuật toán sẽ thực hiện việc phân đoạn con đường như hình 2b.

marker_image_manual road_watershed

Hình 2 (a) Ảnh gốc với marker (b) Con đường đã được phân đoạn với thuật toán Watershed

Thuật toán Watershed được giải thích trong tài liệu của OpenCV:

Xem file ví dụ watershed.cpp trong thư viện openCV để biết cách dùng Watershed. Chú ý rằng trong bài này tôi tạo ảnh đánh maker tự động


Distance transform

Distance transform sử dụng ảnh nhị phân, với mỗi pixel được thay thế bằng khoảng cách của nó tới pixel background gần nhất. Xem ví dụ:
hand hand_distance_transform

Hình 3 (a) Ảnh gốc (b) Ảnh sau khi áp dụng Distance transform

Ví dụ khác về ảnh distance transform
horse_distance_transform

Trong OpenCV, distance transform thực hiện bằng hàm:

Thuật toán này dùng để tạo ảnh maker cho thuật toán Watershed được mô tả bên dưới.


Tiến hành viết code

Thực hành đếm và tách những đồng xu trong hình dưới

5_coin_overlap

Load ảnh và chuyển sang ảnh nhị phân
5_coin_overlap_threeshold

Thực hiện phép distance transform và chuẩn hóa kết quả về khoảng [0,1] nên chúng ta có thể nhìn trực quan và phân ngưỡng nó.

5_coin_overlap_distance_transform

Sau đó chúng ta phân ngưỡng để lấy các giá trị từ 0.5 -> 1.0
5_coin_segmented

Tìm biên
Sử dụng hàm findContours() để tìm số countour có trong ảnh. Sau đó vẽ contour để tạo ảnh marker cho thuật toán Watershed. Chúng ta cũng cần vẽ background marker, đó chính là điểm tròn góc trên bên trái. Vẽ background marker sao cho không chồng lên các contour khác là được.
marker

Áp dụng thuật toán Watershed được kết quả
5_coin_segment


Source đầy đủ ở dưới

Nguồn http://opencv-code.com/tutorials/count-and-segment-overlapping-objects-with-watershed-and-distance-transform/

22 thoughts on “Đếm các đồng xu nằm chồng bằng OpenCV

  1. Bạn ơi code này chỉ đếm được duy nhất trên ảnh đồng xu này thôi ạ?B có code nào đếm được số lượng vật thể ở ảnh tùy chọn của mình k?

  2. Ad ơi cho mình hỏi nếu mình thay bằng ảnh đồng xu khác thì cần chỉnh sửa gì thì mới đếm chính xác được v ạ?

    1. Bạn cần đưa hình ảnh lên mới biết được là cần chỉnh sửa gì nhé

    1. bạn copy code lại rồi save thành file watershed.py là chạy được rồi nhé

Leave a Reply