5.31. Khớp độ dịch chuyển

Khớp mẫu trả lời câu hỏi vùng ảnh này nằm ở đâu trong khung hình; đánh giá độ tương đồng trả lời hai ảnh này giống nhau đến mức nào tổng thể. Một câu hỏi khác nằm ở giữa chúng: hai khung hình hiển thị cùng một cảnh, nhưng camera (hoặc cảnh) đã di chuyển giữa chúng -- bao nhiêu? Đó là bài toán độ dịch chuyển, và module image giải quyết nó bằng một phương thức tương quan pha duy nhất.

5.31.1. Độ dịch chuyển bằng tương quan pha

find_displacement() ước tính sự căn chỉnh cứng giữa hai ảnh cùng kích thước bằng tương quan pha -- một phương thức trong miền tần số chạy biến đổi Fourier nhanh (FFT) trên mỗi ảnh, tương quan chéo các pha của chúng và xác định đỉnh trong kết quả. Vị trí đỉnh là phép tịnh tiến căn chỉnh hai ảnh:

d = img.find_displacement(template)

print("shift:", d.x_translation, d.y_translation,
      " response:", d.response)

Đối tượng Displacement trả về chứa x_translationy_translation -- độ dịch chuyển điểm ảnh theo mỗi trục -- cùng với response, điểm độ tin cậy từ 0.0 đến 1.0 trong đó 1.0 là đỉnh hoàn hảo. Lọc ra các phát hiện dưới ngưỡng response > 0.3 loại bỏ các kết quả nhiễu khi tương quan pha không tìm thấy đỉnh rõ ràng.

Cả rotationscale đều lần lượt là 0.0 và 1.0 trong chế độ mặc định; chúng nhận giá trị thực chỉ khi logpolar=True (xem bên dưới).

Phương thức có hai ràng buộc thực tế. Ràng buộc đầu tiên là kích thước lũy thừa của hai: FFT ở trung tâm của tương quan pha nhanh nhất -- và trên camera, chỉ được hỗ trợ đầy đủ -- ở các kích thước như 32x32, 64x64 và 128x128. Cách thiết lập gọn nhất là chụp trực tiếp ở một trong các kích thước đó, bằng cách truyền độ phân giải cho framesize() dưới dạng tuple:

csi0.framesize((64, 64))

Ứng dụng cần độ dịch chuyển từ khung hình lớn hơn thay vào đó cắt xén một vùng ảnh lũy thừa của hai từ vùng quan tâm và chạy bộ khớp trên đó.

Ràng buộc thứ hai là đầu vào cùng kích thước: roitemplate_roi phải chọn chiều rộng và chiều cao giống hệt nhau, nếu không bộ khớp sẽ từ chối lệnh gọi. Hai ảnh chụp từ cùng một camera ở cùng cấu hình sẽ tự động thỏa mãn điều này; một khung hình được chụp so sánh với một tham chiếu đã tải cần cả hai được cắt thành các vùng ảnh lũy thừa của hai khớp nhau trước.

5.31.2. Xoay và tỷ lệ qua log-polar

Chế độ mặc định chỉ tìm tịnh tiến. Khi hai khung hình cũng khác nhau về xoay quanh một tâm đã chọn hoặc tỷ lệ quanh cùng tâm đó, việc chạy tương quan pha trên phép chiếu log-polar của mỗi ảnh chuyển đổi các tham số đó thành tịnh tiến trong hệ tọa độ log-polar -- mà cùng bộ khớp tương quan pha có thể phục hồi:

d = img.find_displacement(template, logpolar=True)

print("rotation rad:", d.rotation,
      " scale:", d.scale,
      " response:", d.response)

Với logpolar=True, phương thức chạy cùng quy trình khớp trên các ảnh được chiếu log-polar thay vì ảnh gốc. Các trường rotationscale của kết quả được điền đầy đủ: rotation là góc tính bằng radian giữa hai khung hình, scale là hệ số tỷ lệ giữa chúng. x_translationy_translation trở nên vô nghĩa trong chế độ này (tịnh tiến dọc theo các trục log-polar không tương ứng với tịnh tiến tuyến tính trong nguồn).

Từ khóa fix_rotation_scale=True xử lý trường hợp trung gian: hai ảnh khác nhau về cả tịnh tiến và xoay/tỷ lệ, và ứng dụng chỉ cần tịnh tiến sau khi đã hiệu chỉnh xoay và tỷ lệ. Bộ khớp chạy lần log-polar trước để phục hồi xoay và tỷ lệ, áp dụng nghịch đảo cho một trong các ảnh, rồi chạy lần tịnh tiến để phục hồi độ dịch chuyển còn lại. Cờ này chỉ có ý nghĩa khi logpolar=False -- nó yêu cầu bộ khớp chế độ tịnh tiến loại bỏ xoay/tỷ lệ trước.

Mẫu từ biến đổi Polar -- Descartes → cực → khớp -- là những gì find_displacement() với logpolar=True thực hiện trong một lệnh gọi. Ứng dụng lưu trữ một vùng ảnh log-polar tham chiếu khi khởi động, chụp và biến đổi log-polar mỗi khung hình trực tiếp, và phương thức phục hồi sự khác biệt xoay-và-tỷ lệ giữa chúng. Đối với các ứng dụng cần một bộ theo dõi bất biến với xoay và tỷ lệ -- robot cập bến có camera nghiêng và thu phóng khi tiếp cận mục tiêu, gimbal ổn định cần biết ảnh đang xoay như thế nào so với tham chiếu -- đây là cấu trúc tiêu chuẩn.

5.31.3. Cách dùng cổ điển

Cách dùng phổ biến nhất của find_displacement()ước tính chuyển động giữa các khung hình trong một pipeline xử lý camera đang di chuyển. Camera chụp một vùng ảnh lũy thừa-của-2 nhỏ ở khung hình N, chụp vùng ảnh cùng kích thước ở khung hình N+1, chạy find_displacement() trên cả hai, và đọc ra độ dịch chuyển điểm ảnh giữa chúng. Độ dịch chuyển là chuyển động ước tính của camera (hoặc của cảnh, tùy thuộc vào hệ quy chiếu nào quan trọng hơn) giữa hai lần chụp, hữu ích cho:

  • Cảm biến kiểu optical-flow -- một drone bay lơ lửng với camera hướng xuống dưới dùng độ dịch chuyển mỗi khung hình để ước tính chuyển động ngang và đưa vào bộ điều khiển bay.

  • Ổn định ảnh -- độ dịch chuyển giữa các khung hình liên tiếp được trừ đi khỏi ảnh chụp trước khi ghi hoặc truyền, tạo ra luồng video mượt mà hơn.

  • Căn chỉnh kiểm tra -- một camera quét di chuyển dọc theo băng tải dùng độ dịch chuyển mỗi khung hình để căn chỉnh từng khung hình với khung tiếp theo và xây dựng khung nhìn ghép của toàn bộ chi tiết.

Mỗi ứng dụng đó có cùng dạng: chụp, tính độ dịch chuyển, tích lũy vào ước tính đang chạy, chụp lại.