Tìm đường thẳng bằng hàm Houghlines

Bài viết này chia sẻ cách tìm đường thẳng trong ảnh bằng hàm HoughLines. Công dụng là tìm đường thẳng trong ảnh mặc dù có thể bị đứt đoạn.

Trong hình học thì đường thẳng có phương trình:
y = m.x + c
hoặc là
ρ = x.cosθ + y.sinθ (ρ đọc là ro, còn đọc θ là theta nhé)
Với ρ là khoảng cách từ đường thẳng tới gốc tọa độ, còn θ là góc giữa trục hoành và đoạn thẳng ngắn nhất nối tới gốc tọa độ (đơn vị là radian).

Hình minh họa trong hệ tọa độ Đề Cát, trong máy tính thì khác 1 chút vì trục tung từ trên xuống.
Hình minh họa trong hệ tọa độ Đề Cát


Hình minh họa sử dụng trong OpenCV
Lưu ý: Hệ tọa độ trên máy tính có gốc tọa độ ở góc trên bên trái

Có 2 cách để xác định 1 đường thẳng, người ta chọn cách thứ 2 vì chỉ cần 2 tham số (ρ, θ) tiện cho tính toán hơn. Vì θ được tính bằng radian nên có giá trị trong khoảng [0;π] (hay là [0;3.14]). Khi θ bằng 0 hoặc bằng 3.14 thì đường thẳng dựng đứng, còn θ bằng 1.57 (π/2) là nằm ngang.

MÔ TẢ CÁCH HOẠT ĐỘNG CỦA THUẬT TOÁN

Vì mỗi đường thẳng được xác dịnh bởi 2 giá trị (ρ, θ) nên thuật toán tạo 1 mảng 2 chiều. Dòng ứng với ρ và cột ứng với θ, kích thước của mảng phụ thuộc vào bạn chọn, và tất nhiên là mảng càng lớn thì càng chính xác và tính toán càng lâu, còn mảng nhỏ thì nhanh hơn nhưng không chính xác bằng.

Khi sử dụng người dùng sẽ truyền giá trị ρ và θ họ mong muốn. Thuật toán sẽ vẽ ρ x θ đường thẳng trên ảnh, với mỗi đường thẳng thuật toán đếm số pixel nằm trên đường thẳng đó, cứ mỗi pixel tìm thấy thì cộng thêm giá trị vào ô ứng với (ρ, θ).


Trong ảnh trên: bên trái là các điểm trong ảnh, bên phải là mảng 2 chiều

Sau quá trình tính toán thì mỗi ô sẽ có giá trị là số pixel nằm trên đường thẳng đó.

SỬ DỤNG HÀM HOUGHLINES TRONG OPENCV

Hàm houghlines() sử dụng ảnh nhị phân để xử lý, bạn cần phân ngưỡng trước khi gọi hàm.

  • image – ảnh input nhị phân (ảnh có thể bị thay đổi khi tính toán)
  • lines – Output là vector chứa các đường thẳng. Mỗi đường thẳng chứa 2 giá trị (ρ, θ)
  • rho – Khoảng cách của các đường thẳng tính bằng pixels
  • theta – Khoảng cách góc của các đường thẳng tính bằng radians
  • threshold – Số lần được tìm thấy phải vượt qua ngưỡng mới lấy
  • srn – Dùng cho multi-scale
  • stn – Cũng dùng cho multi-scale


Ảnh gốc

Biến đổi ảnh bằng hàm Canny

Sau đó tìm đường thẳng và vẽ

Thông thường người ta sẽ truyền rho = 1px, theta = 3.14/180 (rad).

Hàm PROBABILISTIC HOUGH

Hàm HoughLines() phải tính toán quá nhiều để tìm đường thẳng, còn Probabilistic Hough ít tính toán hơn. Nó không kiểm tra tất cả các pixel mà chỉ lấy 1 số cụm pixel vừa đủ để tìm ra đường thẳng.

Nhược điểm thứ 2 là HoughLines() không xác định được điểm đầu và điểm cuối của đoạn thẳng. Do đó chúng ta dùng HoughLinesP() để khắc phục nhược điểm

Thuật toán này có thêm 2 tham số nữa:

  • minLineLength – Độ dài tối thiểu của đường thẳng
  • maxLineGap – Nếu 2 đường thẳng có khoảng đứt gãy ở giữa ngắn hơn maxLineGap thì được xem là 1 đường thẳng

Source code

Các bạn clone source về (nhớ checkout sub modules OpenCV). Sau đó chạy LineFinder.sln vì trong source code có nhiều example khác

https://github.com/thigiacmaytinh/TGMTcpp

Nguồn

Leave a Reply