Như đã đề xuất ở trên, bộ phát hiện cạnh Matlab Canny tính toán độ dốc bằng cách sử dụng "đạo hàm của bộ lọc Gaussian" (như đã nêu trong tài liệu). Nói cách khác, Matlab thực hiện làm mờ hình ảnh Gaussian và sau đó tìm thấy độ dốc của hình ảnh được làm mịn đó ... tất cả chỉ sử dụng một bộ lọc ưa thích. [Nếu bạn muốn biết chi tiết, chỉ cần nhập vào edit edge
như gợi ý của Andrey, sau đó cuộn xuống smoothGradient()
chức năng.]
Hoạt động làm mờ làm giảm đáng kể lượng nhiễu có trong hình ảnh, loại bỏ nhiều cạnh giả và để lại những thứ tốt.
Thật không may, hàm Canny OpenCV không cho phép bạn thay đổi nhân bộ lọc mà nó sử dụng thông qua các tham số chức năng. Tuy nhiên. Bạn có thể tạo kết quả tương tự bằng cách trước tiên làm mờ hình ảnh đầu vào, sau đó chuyển hình ảnh mờ này vào chức năng Canny.
Điều này làm sạch đáng kể các bản đồ cạnh kết quả. Để làm mờ hình ảnh đầu vào, cá nhân tôi sử dụng GaussianBlur()
chức năng của OpenCV với sigmaX=2
. Điều này bắt chước sigma mặc định trong Matlab. Kích thước kernel làm mờ tốt nhất có thể khác nhau tùy theo từng trường hợp, nhưng trong Matlab, nó được tính bằng cách sử dụng filterLength = 8*ceil(sigma);
, vì vậy đối với sigma là 2 có nghĩa là kích thước kernel là(16,16)
Do cả hai bộ lọc Gaussian Blur và Sobel đều tuyến tính, việc chuyển một hình ảnh đầu vào mờ sang Canny()
hàm OpenCV tương đương về mặt toán học với những gì Matlab làm vì nguyên tắc chồng chất, như được minh họa trong mã giả này (lưu ý: *
là toán tử tích chập):
// The Matlab method: the sobel and blur operations are combined into
// a single filter, and that filter is then convolved with the image
matlabFancyFilter = (sobel * blur);
gradient = matlabFancyFilter * image;
// Equivalent method: image is first convolved with the blur filter, and
// then convolved with the sobel filter.
gradient = sobel * (blur * image); // image is filtered twice
Có một hướng dẫn Canny OpenCV ở đây chỉ ra cách thực hiện điều này bằng C ++. Tôi là một con trăn, vì vậy đây là những gì tôi làm:
smoothedInput = cv2.GaussianBlur(image, (7,7), 2);
edges = cv2.Canny(smoothedInput, 25, 50);