Thị giác máy tính với OpenCV-Python Bài 4, Phần 13: Biến đổi Hough
14:23 - 07/01/2022
Trong phần này chúng ta sẽ cùng tìm hiểu khái niệm về Biến đổi Hough và sử dụng nó để phát hiện các dòng kẻ trong một hình ảnh thông các hàm cv2.HoughLines() và cv2.HoughLinesP().
Thị giác máy tính với OpenCV-Python Bài 7 Phần 2: Phát hiện người đi bộ trong video
Thị giác máy tính với OpenCV-Python Bài 7 Phần 1: Phát hiện người đi bộ trong hình ảnh
Thị giác máy tính với OpenCV-Python Bài 6 Phần 2: Phép trừ nền
Thị giác máy tính với OpenCV-Python Bài 6 Phần 1: Bắt bám đối tượng với Meanshift và Camshift
Khái niệm
Biến đổi Hough (Hough Transform) là một kỹ thuật phổ biến để phát hiện bất kỳ hình dạng nào nếu có thể biểu diễn hình dạng đó dưới dạng toán học. Có thể phát hiện hình dạng ngay cả khi nó bị hỏng hoặc bị bóp méo một chút. Chúng ta sẽ xem nó hoạt động như thế nào đối với các đường kẻ.
Một đường kẻ có thể được biểu diễn dưới dạng y = mx + c hoặc ở dạng tham số, như ρ = xcosθ + ysinθ, trong đó ρ là khoảng cách vuông góc từ điểm gốc đến đường thẳng, và θ là góc tạo bởi đường vuông góc này và trục hoành (được đo ngược chiều kim đồng hồ trong OpenCV).
Bây giờ chúng ta hãy xem Biến đổi Hough hoạt động như thế nào đối với các đường kẻ. Bất kỳ đường thẳng nào cũng có thể được biểu diễn bởi hai tham số (ρ, θ). Trước tiên một mảng 2D được khởi tạo với giá trị 0 (để lưu các giá trị của hai tham số), trong đó, các hàng biểu thị ρ và các cột biểu thị θ. Kích thước của mảng phụ thuộc vào độ chính xác chúng ta cần. Giả sử bạn muốn độ chính xác của các góc là 1 độ, bạn sẽ cần 180 cột. Đối với ρ, khoảng cách tối đa có thể là chiều dài đường chéo của hình ảnh. Vì vậy, lấy độ chính xác một pixel, số hàng có thể là chiều dài đường chéo của hình ảnh. Những gì Hough Transform thực hiện là lần lượt thử các cặp (ρ, θ) để tìm ra đường thẳng trong hình ảnh.
Biến đổi Hough trong OpenCV
Mọi thứ giải thích ở trên được gói gọn trong hàm cv2. HoughLines(). Nó trả về một mảng các giá trị (ρ, θ), trong đó ρ được đo bằng pixel và θ được đo bằng radian. Với tham số đầu tiên, hình ảnh đầu vào phải là hình ảnh nhị phân, vì vậy cần áp dụng ngưỡng hoặc sử dụng tính năng phát hiện cạnh canny trước khi áp dụng biến đổi Hough. Tham số thứ hai và thứ ba là ρ và θ với độ chính xác tương ứng. Tham số thứ tư là ngưỡng tối thiểu mà nó phải nhận được để được coi là một đường, tham số này đại diện cho độ dài tối thiểu của đường cần tìm.
- import cv2
- import numpy as np
- img = cv2.imread('sudoku.jpg')
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- edges = cv2.Canny(gray, 50, 150, apertureSize = 3)
- lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
- for line in lines:
- rho, theta = line[0]
- 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(img, (x1,y1), (x2,y2), (0,0,255), 2)
- cv2.imshow('Bien doi Hough', img)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
Kiểm tra kết quả bên dưới:
Biến đổi Hough xác suất
Trong phép biến đổi hough, bạn có thể thấy rằng ngay cả đối với một đường có hai đối số cũng cần rất nhiều tính toán. Biến đổi Hough xác xuất là sự tối ưu hóa của Biến đổi Hough ở trên, không xem xét tất cả các điểm, mà thay vào đó chỉ lấy một tập hợp con ngẫu nhiên của các điểm đủ để phát hiện ra đường. Việc cần làm là giảm ngưỡng.
Trong OpenCV, việc phát hiện các đường kẻ bằng cách sử dụng phép biến đổi theo xác suất lũy tiến với hàm cv2.HoughLinesP() có thêm hai đối số mới:
- minLineLength: Độ dài tối thiểu của đường kẻ. Các đoạn thẳng ngắn hơn đoạn thẳng này bị bỏ qua.
- maxLineGap: Khoảng cách tối đa được phép giữa các đường kẻ để coi chúng là một đường riêng rẽ.
Kết quả trả về hai điểm cuối của đường kẻ giúp đơn giản hóa quá trình, trong ở Biến đổi Hough thông thường chỉ có các tham số của đường và chúng ta phải tìm tất cả các điểm:
- import cv2
- import numpy as np
- img = cv2.imread('sudoku.jpg')
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- edges = cv2.Canny(gray, 50, 150, apertureSize = 3)
- lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)
- for line in lines:
- x1,y1,x2,y2 = line[0]
- cv2.line(img, (x1,y1), (x2,y2), (0,255,0), 2)
- cv2.imshow('Hough xac xuat', img)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
Xem kết quả bên dưới:
Ở phần tiếp theo chúng ta sẽ cùng tìm hiểu cách áp dụng Biến đổi Hough để tìm đường tròn trong hình ảnh.
(Sưu tầm)
VIỆN IMC
Tòa nhà IMC Tower, Số 176 Trường Chinh, Phường Khương
Thượng, Quận Đống Đa, Thành phố Hà Nội, Việt Nam
Tel/Fax : (+84) 24 3566 6232 / 24 3566 6234
Email: contact@imc.org.vn Website: https://imc.org.vn