5.13. Bộ lọc tuyến tính và lân cận¶
Các phép toán pixel trước đó trong chương này kết hợp hai ảnh từng điểm ảnh một. Bộ lọc thực hiện công việc tương tự theo cách khác: chúng tính giá trị của mỗi điểm ảnh đầu ra từ một vùng lân cận nhỏ các điểm ảnh đầu vào xung quanh vị trí tương ứng. Đầu ra tại (x, y) là một thống kê nào đó -- giá trị trung bình, trung vị, giá trị phổ biến nhất -- của các điểm ảnh đầu vào trong một ô nhỏ có tâm tại (x, y).
Sự thay đổi nhỏ trong cách nhìn nhận -- từ xử lý từng điểm ảnh một sang xử lý cả một cửa sổ điểm ảnh -- chính là điều làm cho cả một họ các phép toán hữu ích hoạt động được. Giá trị trung bình đơn giản trên một cửa sổ nhỏ sẽ làm mịn nhiễu cảm biến. Giá trị trung vị trên cùng cửa sổ đó sẽ loại bỏ nhiễu đốm điểm ảnh đơn mà không làm mờ cạnh nhiều như vậy. Bộ lọc trung bình hai chiều từ chối làm mịn qua các ranh giới tương phản mạnh, bảo toàn các cạnh của đối tượng trong khi làm sạch kết cấu bên trong chúng. Vùng lân cận là đơn vị công việc; lựa chọn thống kê quyết định bộ lọc làm gì.
5.13.1. Kích thước kernel¶
Mọi bộ lọc lân cận đều nhận tham số size để đặt bán kính của cửa sổ theo điểm ảnh. Bản thân cửa sổ là hình vuông và bao phủ (2 * size + 1) điểm ảnh mỗi chiều -- vì vậy size=1 có nghĩa là vùng lân cận 3x3, size=2 có nghĩa là 5x5, size=3 có nghĩa là 7x7, và cứ thế tiếp tục.
Vùng lân cận trượt qua ảnh từng điểm ảnh một, từ trên-trái đến dưới-phải. Mỗi điểm ảnh đầu ra là kết quả áp dụng thống kê của bộ lọc lên vùng lân cận đầu vào có tâm tại nó.¶
Kích thước lớn hơn đồng nghĩa với vùng lân cận lớn hơn, tức là lọc mịn hơn (hoặc mạnh hơn). Chi phí tăng theo diện tích của cửa sổ, vì vậy bộ lọc size=3 thực hiện khoảng chín lần công việc trên mỗi điểm ảnh so với bộ lọc size=1. Giá trị mặc định thực tế cho hầu hết công việc làm sạch là size=1 hoặc size=2; chỉ dùng kích thước lớn hơn khi các vùng lân cận nhỏ không đủ để loại bỏ đặc trưng mà ứng dụng cần triệt tiêu.
5.13.2. Bộ lọc trung bình cộng¶
mean() thay thế mỗi điểm ảnh bằng giá trị trung bình cộng của vùng lân cận của nó. Kết quả làm mịn biến động điểm ảnh theo kích thước cửa sổ, khiến đây là cách rẻ nhất để loại bỏ nhiễu đốm cảm biến: biến động tần số cao được lấy trung bình, nội dung tần số thấp tồn tại.
Đánh đổi ở chỗ các cạnh và các đặc trưng sắc nét khác cũng bị lấy trung bình. Một cạnh sáng trước đây rộng một điểm ảnh sẽ rộng hai hoặc ba điểm ảnh sau bộ lọc trung bình size=1, với độ sáng giảm dần ở hai bên. Đối với việc giảm nhiễu thuần túy trên ảnh nghèo kết cấu (tường sạch, bên trong một dấu màu) thì đây là đánh đổi chấp nhận được. Đối với cảnh bận rộn nơi các cạnh quan trọng, một trong những bộ lọc sau đây thường phù hợp hơn.
img.mean(1) # 3x3 box average -- fast, gentle smoothing
img.mean(2) # 5x5 box average -- stronger, slower
5.13.3. Trung vị, mode, trung điểm¶
Ba bộ lọc lân cận thống kê còn lại thay thế giá trị trung bình cộng đơn giản bằng thứ gì đó mạnh mẽ hơn trước các giá trị ngoại lai.
median() trả về trung vị của vùng lân cận -- giá trị kết thúc ở giữa danh sách đã sắp xếp các điểm ảnh trong cửa sổ. Một điểm ảnh rất sáng hoặc rất tối đơn lẻ trong cửa sổ không kéo giá trị trung vị; nó chỉ trở thành một trong những giá trị cực bị loại bỏ. Hiệu ứng thực tế là lọc trung vị loại bỏ nhiễu đốm điểm ảnh đơn và nhiễu muối-tiêu mà không làm mờ cạnh như mean làm. Chi phí là nhiều tính toán hơn trên mỗi điểm ảnh -- sắp xếp một cửa sổ chậm hơn lấy trung bình nó -- và kết quả không hoàn toàn là một giá trị trung bình, điều này đôi khi quan trọng cho các phép toán tiếp theo.
Tham số percentile (mặc định 0.5) di chuyển giá trị được chọn ra khỏi trung vị nghiêm ngặt. percentile=0.0 trả về giá trị nhỏ nhất của vùng lân cận, percentile=1.0 là giá trị lớn nhất; các giá trị trung gian chọn tỷ lệ giữa chúng trong cửa sổ đã sắp xếp. Điều đó cho median khả năng nhấn mạnh các phần tối hoặc sáng của vùng lân cận mà không mất tính mạnh mẽ trước ngoại lai của thống kê thứ tự.
mode() trả về giá trị phổ biến nhất trong vùng lân cận. Hữu ích khi mô hình nhiễu là "hầu hết các điểm ảnh đúng, một số đã bị hỏng ở các mức độ khác nhau," nơi câu trả lời đúng là giá trị xuất hiện thường xuyên nhất -- điều mà trung vị có thể bỏ lỡ khi các giá trị bị hỏng tích tụ ở một phía của cửa sổ đã sắp xếp.
midpoint() trả về tổ hợp có trọng số của giá trị nhỏ nhất và lớn nhất của vùng lân cận -- bias=0.5 cho trung điểm giữa chúng, bias=0.0 cho giá trị nhỏ nhất, bias=1.0 cho giá trị lớn nhất. Ít được dùng hơn các bộ lọc khác nhưng đáng biết khi mục tiêu là trích xuất đặc trưng tối hoặc sáng.
5.13.4. Bộ lọc hai chiều, phiên bản bảo toàn cạnh¶
bilateral() là bộ lọc lân cận đáng hiểu kỹ nhất. Nó tạo ra hiệu ứng làm mịn của mean(), nhưng với một ràng buộc thêm: càng có nhiều điểm ảnh lân cận khác biệt so với điểm ảnh trung tâm, thì nó càng ít đóng góp vào giá trị trung bình. Kết quả là làm mịn bên trong mỗi vùng đồng nhất mà không lan qua các cạnh phân tách chúng, đây chính xác là điều hầu hết các ứng dụng thực sự muốn.
Hai tham số kiểm soát mức độ bộ lọc loại bỏ các điểm ảnh:
color_sigmaquyết định độ chênh lệch màu sắc ảnh hưởng đến trọng số như thế nào. Giá trị nhỏ hơn có nghĩa là bộ lọc nghiêm ngặt hơn trong việc loại bỏ các điểm ảnh khác biệt so với điểm trung tâm.space_sigmaquyết định khoảng cách không gian ảnh hưởng đến trọng số như thế nào. Giá trị nhỏ hơn cho trọng số lớn hơn cho các điểm ảnh gần trung tâm.
Các giá trị mặc định (color_sigma=0.1, space_sigma=1.0) là điểm khởi đầu hợp lý; việc tinh chỉnh chúng thường là chạy bộ lọc trên một khung hình mẫu và điều chỉnh cho đến khi các cạnh sắc nét và bên trong sạch.
Bộ lọc hai chiều đắt hơn median() và đắt hơn đáng kể so với mean(), vì vậy chỉ đáng dùng khi hành vi bảo toàn cạnh là thứ ứng dụng cần.
5.13.5. Ngưỡng hóa thích ứng¶
Các bộ lọc trung bình, trung vị, mode và trung điểm đều mang cùng một cặp đối số từ khóa để chuyển đầu ra của chúng thành một ngưỡng nhị phân:
threshold=Truechuyển bộ lọc sang chế độ ngưỡng hóa.offset=Ndịch chuyển ngưỡng cắt cục bộ điNđơn vị trước khi so sánh.
Cơ chế này xây dựng trực tiếp trên hành vi thông thường của bộ lọc. Không có threshold=True, bộ lọc tính thống kê của nó trên vùng lân cận và ghi thống kê đó vào điểm ảnh đầu ra. Với threshold=True, bộ lọc tính cùng thống kê đó, sau đó so sánh điểm ảnh nguồn tại cùng vị trí với thống kê cộng với offset, và ghi giá trị tối đa của định dạng nếu nguồn lớn hơn, ngược lại là không.
Kết quả là một ảnh nhị phân có ngưỡng cắt di chuyển theo độ sáng cục bộ trên toàn bộ khung hình. Các vùng sáng nhận ngưỡng cắt cao, các vùng tối nhận ngưỡng cắt thấp, và một điểm ảnh tiền cảnh sáng hơn cục bộ so với các điểm lân cận của nó sẽ khớp dù nó nằm trong vùng sáng hay tối -- đây chính xác là hành vi mà một ngưỡng toàn cục duy nhất không thể tạo ra trên ảnh được chiếu sáng không đều.
img.mean(3, threshold=True, offset=5)
Tham số offset là nơi ứng dụng kiểm soát mức độ nghiêm ngặt của phép kiểm tra. Một offset dương nhỏ đòi hỏi điểm ảnh nguồn sáng hơn đáng kể so với các điểm lân cận trước khi tính là khớp, điều này loại bỏ các kết quả dương tính giả do nhiễu cảm biến với chi phí là bỏ qua tiền cảnh mờ. Một offset âm nhỏ bắt được tiền cảnh mờ với chi phí để lọt qua một số nhiễu. Lựa chọn phụ thuộc vào những gì phần còn lại của pipeline sẽ làm với đầu ra nhị phân.
Với chiếu sáng không đều, một ngưỡng toàn cục duy nhất không thể mô tả tiền cảnh ở mỗi vị trí. Một bộ lọc lân cận chạy với threshold=True tạo ra ngưỡng cắt di chuyển theo độ sáng cục bộ và phân loại tiền cảnh đúng trên toàn bộ khung hình.¶
Họ bộ lọc chạy ngưỡng hóa thích ứng, vì vậy việc chọn đúng bộ lọc quan trọng: mean() cho ngưỡng hóa thích ứng rẻ nhất, median() khi đầu vào có nhiễu muối-tiêu mà bộ lọc nên loại bỏ trước khi tính ngưỡng cắt cục bộ.