Các thuật toán để thực hiện khảm hình ảnh - có cách nào nhanh hơn thế này không?


9

Tôi đã chơi với việc tạo hình ảnh khảm. Kịch bản của tôi lấy một số lượng lớn hình ảnh, thu nhỏ chúng xuống kích thước hình thu nhỏ và sau đó sử dụng chúng làm hình xếp để xấp xỉ hình ảnh mục tiêu.

Cách tiếp cận thực sự khá dễ chịu:

Tôi tính sai số bình phương trung bình cho mỗi ngón tay cái ở mọi vị trí ô.

Lúc đầu, tôi chỉ sử dụng một vị trí tham lam: đặt ngón tay cái với ít lỗi nhất vào ô mà nó phù hợp nhất, và sau đó tiếp theo và cứ thế.

Vấn đề với sự tham lam là nó cuối cùng khiến bạn đặt những ngón tay cái khác nhau nhất trên các gạch ít phổ biến nhất, cho dù chúng có khớp với nhau hay không. Tôi hiển thị các ví dụ ở đây: http://williamedwardscoder.tumblr.com/post/84505278488/making-image-mosaics

Vì vậy, sau đó tôi thực hiện hoán đổi ngẫu nhiên cho đến khi kịch bản bị gián đoạn. Kết quả khá OK.

Việc hoán đổi ngẫu nhiên hai gạch không phải lúc nào cũng là một sự cải tiến, nhưng đôi khi việc xoay vòng ba hoặc nhiều gạch dẫn đến cải thiện toàn cầu tức là A <-> Bcó thể không cải thiện, nhưng A -> B -> C -> A1có thể ..

Vì lý do này, sau khi chọn hai gạch ngẫu nhiên và phát hiện ra chúng không cải thiện, tôi chọn một bó gạch để đánh giá xem chúng có thể là gạch thứ ba trong một vòng quay như vậy không. Tôi không khám phá nếu bất kỳ bộ bốn gạch có thể được quay có lợi nhuận, và như vậy; đó sẽ là siêu đắt thực sự sớm.

Nhưng điều này cần có thời gian .. Rất nhiều thời gian!

Có một cách tiếp cận tốt hơn và nhanh hơn?


Cập nhật tiền thưởng

Tôi đã thử nghiệm các triển khai và ràng buộc Python khác nhau của Phương pháp Hungary .

Cho đến nay, nhanh nhất là Python thuần https://github.com/xtof-durr/makeSimple/blob/master/Munkres/kuhnMunkres.py

Linh cảm của tôi là điều này gần đúng câu trả lời tối ưu; Khi chạy trên một hình ảnh thử nghiệm, tất cả các thư viện khác đều đồng ý về kết quả, nhưng kuhnMunkres.py này, trong khi có các đơn đặt hàng có cường độ nhanh hơn, chỉ rất gần với điểm số mà các triển khai khác đã đồng ý.

Tốc độ rất phụ thuộc vào dữ liệu; Mona Lisa vội vã chạy qua kuhnMunkres.py sau 13 phút, nhưng Parakeet Scarlet Chested mất 16 phút.

Kết quả tương tự như các giao dịch hoán đổi và xoay ngẫu nhiên cho Parakeet:

nhập mô tả hình ảnh ở đâynhập mô tả hình ảnh ở đây

(kuhnMunkres.py ở bên trái, hoán đổi ngẫu nhiên ở bên phải; ảnh gốc để so sánh )

Tuy nhiên, đối với hình ảnh Mona Lisa mà tôi đã thử nghiệm, kết quả đã được cải thiện rõ rệt và cô ấy thực sự có 'nụ cười' được định nghĩa tỏa sáng:

nhập mô tả hình ảnh ở đâynhập mô tả hình ảnh ở đây

(kuhnMunkres.py ở bên trái, hoán đổi ngẫu nhiên ở bên phải)


1
Liên quan ... ish. Trên Codegolf chuyển đổi vòm miệng có vấn đề tương tự.

1
Và một bộ hình ảnh liên quan khác là allRGB trong đó mỗi hình ảnh (mặc dù điều đó không cung cấp cho bạn quá nhiều gợi ý về cách thực hiện ... chỉ là có một lĩnh vực khác mà vấn đề này đã được tiếp cận).

1
Tôi gặp vấn đề này với một nhà sản xuất khảm cách đây vài năm. Dòng lý luận của tôi lúc đó và bây giờ là vấn đề không phải là quá nhiều với thuật toán của bạn (phần MSE) mà là với kích thước giới hạn của bảng màu hình ảnh đầu vào của bạn. Không có một tỷ hình ảnh để làm việc, tôi đã làm giả nó bằng cách cho phép một hình ảnh được sử dụng lại sau một khoảng thời gian. Tuy nhiên, nếu bạn muốn theo cách tiếp cận của mình, có thể tốt để thực hiện lần đầu tiên cho phù hợp "tốt" và sau đó coi phần còn lại của hình ảnh là ngẫu nhiên (hoặc ngẫu nhiên-ish) - với bộ đầu vào hạn chế bạn chỉ có quá nhiều lựa chọn.
J Trana

@MichaelT cảm ơn vì liên kết tuyệt vời đó :) Đặc biệt codegolf rất hấp dẫn. Tôi thấy các giải pháp tốt nhất được bình chọn đang sử dụng các giao dịch hoán đổi ngẫu nhiên (không phải xoay ngẫu nhiên) và có lẽ đang chạy trong một thời gian dài ...
Will

1
Đến với điều này sau khi bạn đã chọn một câu trả lời và trao tiền thưởng. Một cách tiếp cận khác sẽ được coi là vấn đề mô phỏng luyện kim . Bạn có thể sử dụng SA là một trong những giai đoạn của đường ống giải pháp của bạn.
andy256

Câu trả lời:


3

Vâng, có hai cách tiếp cận tốt hơn và nhanh hơn.

  • Vấn đề đơn giản hơn: đối với mỗi ô, chọn ngón tay cái tốt nhất (có thể nhân đôi). Ok, đó là gian lận, nhưng chỉ có thể dẫn đến kết quả hình ảnh tốt hơn.
  • Việc thực hiện của bạn thú vị hơn về mặt thuật toán và hiểu rõ "vấn đề gán tuyến tính", giả sử bạn lấy MSE làm chi phí khớp mà tổng của nó phải là tối thiểu. Vấn đề như vậy có thể được giải quyết trong thời gian đa thức, thông qua "Phương pháp Hungary"

Sau đó, bạn có thể điều chỉnh chi phí của mình bằng cách thay thế MSE bằng khoảng cách trực quan chính xác hơn mà không thay đổi thuật toán cơ bản.


Cám ơn! Phương pháp LAP và Hungary là những hướng dẫn tôi cần! Cập nhật với kết quả trong câu hỏi.
Sẽ

3

Tôi chắc chắn rằng đó là một vấn đề NP-hard. Để tìm một giải pháp 'hoàn hảo', bạn phải thử mọi khả năng một cách triệt để, và đó là theo cấp số nhân.

Một cách tiếp cận sẽ là sử dụng sự phù hợp tham lam và sau đó cố gắng cải thiện nó. Điều đó có thể bằng cách lấy một hình ảnh được đặt kém (một trong những hình cuối cùng) và tìm một nơi khác để đặt nó, sau đó lấy hình ảnh đó và di chuyển nó và vân vân. Bạn đã hoàn thành khi bạn (a) hết thời gian (b) sự phù hợp là "đủ tốt".

Nếu bạn giới thiệu một yếu tố xác suất, nó có thể mang lại một phương pháp ủ mô phỏng hoặc thuật toán di truyền. Có lẽ tất cả những gì bạn đang cố gắng đạt được là trải đều các lỗi. Tôi nghi ngờ điều này đang tiến gần đến những gì bạn đang làm nên câu trả lời là: với thuật toán phù hợp, bạn có thể nhận được kết quả tốt hơn nhanh hơn nhưng không có lối tắt kỳ diệu nào đến Nirvana.


Vâng, điều này tương tự như những gì bạn đã làm. Vấn đề là quên một câu trả lời kỳ diệu và suy nghĩ theo 2 thuật toán: điền trước, sau đó tối ưu hóa.

Sự lấp đầy có thể là: ngẫu nhiên, tốt nhất có sẵn, tốt nhất đầu tiên, đủ tốt, một số điểm nóng.

Việc tối ưu hóa có thể là ngẫu nhiên, khắc phục điều tồi tệ nhất hoặc (như tôi đề xuất) mô phỏng thuật toán ủ hoặc thuật toán di truyền.

Bạn cần một số liệu về 'lòng tốt' và một lượng thời gian bạn chuẩn bị dành cho nó và chỉ cần thử nghiệm. Hoặc tìm một người đã thực sự làm điều đó.


Bạn mô tả chính xác cách tiếp cận được mô tả trong câu hỏi ...?
Sẽ

1

Nếu gạch cuối cùng là vấn đề của bạn, bạn nên cố gắng đặt chúng sớm, bằng cách nào đó;)

Một cách tiếp cận là nhìn vào ô xếp xa nhất so với x% trên cùng của trận đấu (theo trực giác tôi sẽ đi với 33%) và đặt nó vào trận đấu tốt nhất. Đó là trận đấu hay nhất mà nó có thể nhận được.

Hơn nữa, bạn có thể chọn không sử dụng kết quả phù hợp nhất cho ô xấu nhất, nhưng trường hợp giới thiệu ít lỗi nhất so với kết quả phù hợp nhất cho vị trí đó, để bạn không hoàn toàn loại bỏ các kết quả phù hợp nhất của mình vì lợi ích của " mất kiểm soát".

Một điều nữa để tâm trí là cuối cùng bạn đang tạo ra một hình ảnh được xử lý bằng mắt. Vì vậy, những gì bạn thực sự muốn là sử dụng một số phát hiện cạnh để xác định vị trí nào trên hình ảnh của bạn là quan trọng nhất. Tương tự, những gì xảy ra ở ngoại vi của hình ảnh rất ít có giá trị đối với chất lượng của hiệu ứng. Đặt hai trọng số này và đưa chúng vào tính toán khoảng cách của bạn. Do đó, bất kỳ jitter nào bạn nhận được sẽ bị hút về phía biên giới và cách xa các cạnh, do đó làm phiền ít hơn rất nhiều.

Ngoài ra với tính năng phát hiện cạnh, bạn có thể muốn đặt y% đầu tiên một cách tham lam (có thể cho đến khi bạn giảm xuống dưới một ngưỡng "độ sắc nét" nhất định trong các ô bên trái), để các "điểm nóng" được xử lý thực sự độc đáo, và sau đó chuyển sang "kiểm soát thiệt hại" cho phần còn lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.