2012-07-04 4 views
11

Tôi cần thuật toán băm hình ảnh (tốt và đơn giản). Giá trị băm được sử dụng trong bảng tra cứu, không phải cho mật mã.Thuật toán băm hình ảnh nhanh và đơn giản

Một số hình ảnh là "đồ họa máy tính" - nghĩa là các bản màu được tô màu, văn bản được tô màu và v.v ... trong khi đó cũng có những hình ảnh "nhiếp ảnh" - chứa phổ màu phong phú, chủ yếu là trơn tru.

Tôi cũng muốn thuật toán băm có thể được áp dụng cho các phần hình ảnh cụ thể. Ý tôi là, hình ảnh có thể được chia thành một ô lưới và hàm băm của mỗi ô chỉ phụ thuộc vào nội dung của ô này. Vì vậy, người ta có thể phát hiện một cách nhanh chóng nếu hai hình ảnh có các khu vực chung (trong trường hợp chúng được căn chỉnh phù hợp).

Lưu ý: Tôi chỉ cần biết hai hình ảnh (hoặc các bộ phận của chúng) là giống hệt nhau. Đó là, tôi không cần phải phù hợp với hình ảnh tương tự, không cần phải nhận diện tính năng, tương quan và các kỹ thuật DSP khác.

Tôi tự hỏi thuật toán băm ưa thích là gì.

Đối với hình ảnh "chụp ảnh" chỉ XOR-ing tất cả các pixel trong ô lưới là ok nhiều hơn hoặc ít hơn. Xác suất của cùng một giá trị băm cho các hình ảnh khác nhau là khá thấp, đặc biệt là do sự hiện diện của nhiễu (gần như trắng) phá vỡ tất cả các đối xứng tiềm năng. Cộng với quang phổ của hàm băm như vậy có vẻ tốt (bất kỳ giá trị nào có thể với gần như cùng xác suất).

Nhưng một thuật toán ngây thơ như vậy có thể không được sử dụng với đồ họa "nhân tạo". Các pixel giống hệt nhau, các mẫu lặp lại, tính bất biến bù hình học là rất phổ biến đối với các hình ảnh như vậy. XOR-ing tất cả các điểm ảnh sẽ cho 0 cho bất kỳ hình ảnh nào với số lượng pixel giống hệt nhau.

Sử dụng một cái gì đó như CRT-32 có vẻ hơi hứa hẹn, nhưng tôi muốn tìm ra điều gì đó nhanh hơn. Tôi nghĩ về công thức lặp đi lặp lại, mỗi điểm ảnh mới đột biến giá trị hash hiện tại, như thế này:

hashValue = (hashValue * /*something*/ | newPixelValue) % /* huge prime */ 

Làm số nguyên tố modulo lẽ nên đưa ra một sự phân tán tốt, vì vậy mà tôi đang nghiêng về phía tùy chọn này. Nhưng tôi muốn biết nếu có varians tốt hơn.

Xin cảm ơn trước.

+0

tại sao bạn không sử dụng một số thuật toán băm đơn giản như md5? –

+0

@Karoly Horvath: Câu hỏi hay. Thật vậy đây là những gì tôi cần nhiều hơn hoặc ít hơn. Tuy nhiên MD5 là (có lẽ) CPU đói, nó được thiết kế để có một hàm băm một chiều. OTOH Tôi cần một cái gì đó đơn giản hơn nhiều, vì tôi không có cân nhắc bảo mật. Tôi mặc dù về CRC-32. Nhưng tôi muốn tìm ra một cái gì đó thậm chí đơn giản hơn – valdo

+0

Nếu bạn làm điều này trên rất nhiều hình ảnh, nút cổ chai sẽ là tốc độ đĩa của bạn .. –

Trả lời

7

Nếu bạn muốn làm cho nó rất nhanh, bạn nên xem xét lấy một tập hợp con ngẫu nhiên của các điểm ảnh để tránh đọc toàn bộ hình ảnh. Tiếp theo, tính toán hàm băm trên chuỗi giá trị tại các pixel đó. Tập hợp con ngẫu nhiên nên được chọn bởi trình tạo số giả ngẫu nhiên xác định với hạt giống cố định để hình ảnh giống hệt nhau tạo ra các tập con giống hệt nhau và do đó các giá trị băm giống hệt nhau.

Điều này sẽ hoạt động tốt ngay cả đối với hình ảnh nhân tạo. Tuy nhiên, nếu bạn có các hình ảnh khác nhau với một số lượng nhỏ pixel, điều này sẽ cho ra các xung đột băm. Lặp lại nhiều hơn cho độ tin cậy tốt hơn. Nếu đó là trường hợp, ví dụ, nếu hình ảnh của bạn thiết lập có khả năng có cặp với một điểm ảnh khác nhau, bạn phải đọc mỗi điểm ảnh để tính toán giá trị băm. Việc kết hợp tuyến tính đơn giản với các hệ số giả ngẫu nhiên sẽ đủ tốt ngay cả đối với hình ảnh nhân tạo.

pseudo-code của một thuật toán đơn giản

Random generator = new generator(2847) // Initialized with fixed seed 
int num_iterations = 100 

int hash(Image image) { 
    generator.reset() //To ensure consistency on each evaluation 
    int value = 0 
    for num_iteration steps { 
     int nextValue = image.getPixel(generator.nextInt()%image.getSize()).getValue() 
     value = value + nextValue*generator.nextInt() 
    } 
    return value 
} 
+0

Cảm ơn câu trả lời. Tôi không có vấn đề gì khi đọc toàn bộ ô lưới. Các ô lưới của tôi khá nhỏ (8x8 hoặc 16x16). Hơn nữa, khi giá trị băm của hai hình ảnh bằng nhau - tôi đảm bảo rằng các hình ảnh đều bằng nhau. Tham số duy nhất bị thiếu là hàm băm. Nó nên là gì? – valdo

+2

Nếu bạn không yêu cầu bảo mật mật mã và chỉ lo lắng về hình ảnh nhân tạo, thì kết hợp tuyến tính đơn giản của các giá trị pixel với các hệ số ngẫu nhiên là đủ, như tôi đã mô tả. Vấn đề tương tự với việc tìm kiếm giá trị băm của một mảng nguyên như v1 = [34,2,4,92,3], v2 = [10,3,5,20,3]. Mục tiêu của bạn là tìm băm của chúng để xem cái nào là bằng nhau. Chọn một vector cố định được chọn ngẫu nhiên m = [72,37,1,4,34] ban đầu. Đối với mỗi vectơ đầu vào, giá trị băm của v1 là v1 * m = 34 * 72 + 2 * 37 + 4 * 1 + 92 * 4 + 3 * 34. Bạn có thể tính toán số này modulo bất kỳ số nguyên quá, nếu bạn muốn. – akashnil

5

Hãy nhìn vào hướng dẫn này trên các thuật toán phash http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html được sử dụng để tìm phù hợp chặt chẽ hình ảnh.

+0

Cảm ơn sự quan tâm của bạn, nhưng đây không phải là những gì tôi muốn IMHO. Thuật toán mô tả là tốt cho việc tìm kiếm hình ảnh "tương tự", nó cũng là quy mô bất biến. Vấn đề của tôi đơn giản hơn rất nhiều và tôi muốn một giải pháp hiệu quả hơn nhiều – valdo

+0

@valdo: Tôi đã thêm một số thông tin khác. – Bytemain