Trong bài viết này, chúng ta sẽ cùng nhau sử dụng những điểm cạnh phát hiện được để tìm ra đồng xu trong bức ảnh và đếm chúng. OpenCV cung cấp một phương thức để tìm các đường cong trong ảnh gọi là contours – đường viền. Một đường viền là đường cong các điểm không bao gồm khoảng trống. Các đường viền vô cùng hữu ích trong việc xác định hình dáng vật thể và phân tích ảnh.
Để có thể tìm đường các đường viền trong ảnh, bạn đọc cần nắm được các kỹ thuật xử lý ảnh cơ bản như tách cạnh hoặc áp dụng ngưỡng. Chúng ta sẽ bắt đầu ngay vào bài toán.
Trong 11 dòng đầu tiên, chúng ta thực hiện các thao tác quen thuộc: khai báo thư viện, định nghĩa tham số đầu vào và đọc ảnh.
Như đã trình bày trong bài học trước, để có thể tách cạnh, trước hết, ta chuyển đổi ảnh từ hệ màu RGB thành ảnh xám – dòng 13, sau đó áp dụng kỹ thuật làm mờ Gaussian để lọc nhiễu – dòng 14. Trong ví dụ này, ta sử dụng bộ lọc lớn hơn là 15×15. Tiếp đó, ta tách được cạnh bằng cách áp dụng Canny ở dòng 17.
Sau khi thu được các cạnh của đồng xu, ta thực hiện tìm đường viền qua hàm cv2.findContours – dòng 20. Hàm này trả về 2 giá trị ở phiên bản OpenCV 2.4.x gồm có các đường viền và thứ tự các đường viền trong khi ở phiên bản OpenCV 3.0, hàm này trả về 3 giá trị gồm có ảnh sau khi áp dụng phát hiện đường viền, đường viền và thứ tự của chúng. Quay lại với hàm cv2.findContours, tham số đầu tiên là ảnh được tách cạnh, tiếp đó là loại đường viền mà ta muốn thu về: cv2.RETR_EXTERNAL – thu về đường viền ngoài cùng. Ngoài ra, bạn đọc có thể thử nghiệm thêm một số cài đặt khác như cv2.RETR_COMP và cv2.RETR_TREE. Tham số cuối cùng là ước tính đường viền, trong đó cv2.CHAIN_APPROX_SIMPLE nén các phân đoạn ngang, dọc, chéo vào các điểm cuối. Điều này làm quá trình tính toán nhanh hơn và giảm khối lượng bộ nhớ phải sử dụng. Nếu muốn thu về toàn bộ các điểm tạo nên đường viền mà không nén, bạn đọc sử dụng cv2.CHAIN_APPROX_NONE để so sánh với cấu hình trên.
Như vậy, đường viền thu được nằm trong biến số cnts ở dạng list. Bạn đọc có thể đếm số đường viền thu được bằng hàm len() – 22. Sau khi thực thi đoạn mã, mình thu được kết quả đếm được 8 đồng xu xuất hiện trong ảnh.
Chúng ta thực hiện vẽ đường viền qua hàm cv2.drawContours. Tham số đầu tiên là bức ảnh ta muốn vẽ – dòng 25, tiếp đó là danh sách đường viền. Tham số thứ 3 là thứ tự đường viền, với giá trị là -1, ta thực hiện vẽ toàn bộ các đường viền có trong danh sách. Tuy nhiên, bạn đọc có thể thay đổi là giá trị này theo thứ tự đường viền bạn muốn vẽ thay vì tất cả. Cuối cùng là hai tham số về màu sắc sử dụng và độ dày của viền vẽ.
Vậy làm thế nào để chúng ta có thể trích xuất từng đồng xu trong bức ảnh kia?
Bằng cách xử lý từng phần tử trong danh sách đường viền thu được, chúng ta có thể trả lời câu hỏi trên. Dòng 28 bắt đầu vòng lặp vào danh sách đường viền. Hàm cv2.boundingRect để cắt tọa độ đồng xu xuất hiện trong ảnh và trả về tọa độ x,y bắt đầu đa giác, tiếp đó là chiều rộng và chiều cao đường viền. Các thao tác vẽ hình còn lại bạn đọc có thể tham khảo trong những bài hướng dẫn đầu tiên. Cuối cùng, chúng ta hiển thị được lần lượt các đồng xu xuất hiện trong hình
Như vậy, sau phần đầu tiên của “Thị giác máy tính toàn tập”, bạn đọc đã tìm hiểu rất nhiều phương pháp xử lý ảnh cơ bản như phép dịch, phép xoay, thay đổi kích thước hay cắt ảnh bằng cách lập trình trực tiếp với Python và OpenCV. Bên cạnh đó, chúng ta cũng cùng nhau đi qua các khái niệm và ứng dụng đồ thị phân bố điểm ảnh cũng như các phương pháp xét ngưỡng hay làm mờ ảnh. Cuối cùng, bạn đọc đã có thể áp dụng tất cả các kiến thức đó trong việc tìm xác định và tìm số đồng xu xuất hiện trong ảnh. Ở những khóa học tiếp theo, chúng ta sẽ tìm hiểu thêm về ứng dụng học sâu trong thị giác máy tính cùng một số dự án thú vị. Nếu bạn đọc muốn đi sâu hơn vào mảng này, chúng ta sẽ gặp lại nhau trong phần toán học thị giác máy tính.