Bài đăng này là điểm khởi đầu của giải pháp của tôi, rất nhiều ý tưởng hay ở đây vì vậy tôi mặc dù tôi sẽ chia sẻ kết quả của mình. Cái nhìn sâu sắc chính là tôi đã tìm ra cách khắc phục sự chậm chạp của việc khớp hình ảnh dựa trên điểm chính bằng cách khai thác tốc độ của phash.
Đối với giải pháp chung, tốt nhất là sử dụng một số chiến lược. Mỗi thuật toán phù hợp nhất cho các loại biến đổi hình ảnh nhất định và bạn có thể tận dụng lợi thế đó.
Ở đầu, các thuật toán nhanh nhất; ở phía dưới chậm nhất (mặc dù chính xác hơn). Bạn có thể bỏ qua những cái chậm nếu một trận đấu hay được tìm thấy ở cấp độ nhanh hơn.
- dựa trên tệp băm (md5, sha1, v.v.) để sao chép chính xác
- băm nhận thức (phash) cho hình ảnh thay đổi kích thước
- dựa trên tính năng (SIFT) cho hình ảnh được sửa đổi
Tôi đang có kết quả rất tốt với phash. Độ chính xác là tốt cho hình ảnh thay đổi kích thước. Nó không tốt cho (nhận thức) hình ảnh được sửa đổi (cắt, xoay, nhân đôi, v.v.). Để đối phó với tốc độ băm, chúng ta phải sử dụng bộ đệm / cơ sở dữ liệu đĩa để duy trì băm cho haystack.
Điều thực sự thú vị về phash là một khi bạn xây dựng cơ sở dữ liệu băm của mình (với tôi là khoảng 1000 hình ảnh / giây), các tìm kiếm có thể rất, rất nhanh, đặc biệt là khi bạn có thể giữ toàn bộ cơ sở dữ liệu băm trong bộ nhớ. Điều này khá thực tế vì một hàm băm chỉ có 8 byte.
Ví dụ: nếu bạn có 1 triệu hình ảnh, nó sẽ yêu cầu một mảng gồm 1 triệu giá trị băm 64 bit (8 MB). Trên một số CPU, điều này phù hợp với bộ đệm L2 / L3! Trong sử dụng thực tế tôi đã thấy một corei7 so sánh ở mức hơn 1 Giga-hamm / giây, đó chỉ là một câu hỏi về băng thông bộ nhớ cho CPU. Cơ sở dữ liệu hình ảnh 1 tỷ là thực tế trên CPU 64 bit (cần RAM 8GB) và các tìm kiếm sẽ không vượt quá 1 giây!
Đối với các hình ảnh được sửa đổi / cắt xén, có vẻ như một tính năng phát hiện điểm / biến đổi điểm bất biến như SIFT là hướng đi. SIFT sẽ tạo ra các điểm chính tốt sẽ phát hiện cắt / xoay / gương, v.v. Tuy nhiên, so sánh mô tả rất chậm so với khoảng cách hãm được sử dụng bởi phash. Đây là một hạn chế lớn. Có rất nhiều so sánh để làm, vì có mô tả IxJxK tối đa so sánh để tra cứu một hình ảnh (I = num haystack hình ảnh, J = điểm chính trên mỗi hình ảnh haystack, K = điểm chính trên mỗi hình ảnh kim).
Để giải quyết vấn đề tốc độ, tôi đã thử sử dụng phash xung quanh từng điểm chính được tìm thấy, sử dụng kích thước / bán kính tính năng để xác định hình chữ nhật phụ. Mẹo để làm cho điều này hoạt động tốt, là tăng / thu nhỏ bán kính để tạo các mức độ trực tràng khác nhau (trên hình ảnh kim). Thông thường, cấp độ đầu tiên (không được tính) sẽ phù hợp tuy nhiên thường phải mất thêm một vài lần nữa. Tôi không chắc chắn 100% lý do tại sao điều này hoạt động, nhưng tôi có thể tưởng tượng nó cho phép các tính năng quá nhỏ để phash hoạt động (phash chia tỷ lệ hình ảnh xuống còn 32x32).
Một vấn đề khác là SIFT sẽ không phân phối các điểm chính một cách tối ưu. Nếu có một phần của hình ảnh có nhiều cạnh, các điểm chính sẽ co cụm ở đó và bạn sẽ không nhận được bất kỳ phần nào trong khu vực khác. Tôi đang sử dụng GridAdaptedFeatureDetector trong OpenCV để cải thiện việc phân phối. Không chắc chắn kích thước lưới nào là tốt nhất, tôi đang sử dụng một lưới nhỏ (1x3 hoặc 3x1 tùy theo hướng hình ảnh).
Bạn có thể muốn chia tỷ lệ tất cả các hình ảnh haystack (và kim) thành kích thước nhỏ hơn trước khi phát hiện tính năng (Tôi sử dụng 210px dọc theo kích thước tối đa). Điều này sẽ làm giảm nhiễu trong hình ảnh (luôn là vấn đề đối với thuật toán thị giác máy tính), cũng sẽ tập trung máy dò vào các tính năng nổi bật hơn.
Đối với hình ảnh của mọi người, bạn có thể thử phát hiện khuôn mặt và sử dụng nó để xác định kích thước hình ảnh theo tỷ lệ và kích thước lưới (ví dụ: khuôn mặt lớn nhất được chia tỷ lệ là 100px). Trình phát hiện tính năng chiếm nhiều cấp độ tỷ lệ (sử dụng kim tự tháp) nhưng có giới hạn đối với số lượng cấp độ sẽ sử dụng (tất nhiên điều này có thể điều chỉnh được).
Trình phát hiện keypoint có thể hoạt động tốt nhất khi nó trả về ít hơn số lượng tính năng bạn muốn. Ví dụ: nếu bạn yêu cầu 400 và nhận lại 300, điều đó thật tốt. Nếu bạn nhận được 400 trở lại mỗi lần, có lẽ một số tính năng tốt đã bị bỏ qua.
Hình ảnh kim có thể có ít điểm chính hơn hình ảnh haystack và vẫn nhận được kết quả tốt. Thêm nhiều hơn không nhất thiết giúp bạn có được lợi nhuận khổng lồ, ví dụ với J = 400 và K = 40 tỷ lệ trúng của tôi là khoảng 92%. Với J = 400 và K = 400, tỷ lệ trúng chỉ tăng lên 96%.
Chúng ta có thể tận dụng tốc độ cực cao của chức năng hamming để giải quyết tỷ lệ, xoay, phản chiếu, v.v ... Có thể sử dụng kỹ thuật nhiều đường chuyền. Trên mỗi lần lặp, chuyển đổi các hình chữ nhật phụ, băm lại và chạy lại chức năng tìm kiếm.