/fast_jigsaw_puzzle_solver

fragments image and re-assemble them back to original image. #Prim's MST algorithm

Primary LanguagePython

Fast Jigsaw Puzzle Solver with unknown orientation

  • Breaks down an original image into N (row x col) anonymized rectangular pieces of random orientations.
  • Reconstructs N puzzle pieces back to original image in O(N2) runtime.
    demo_anim
    Disclaimer: orientation of the reconstructed image is random. Successful reconstruction is not always guaranteed.

Features

  • Prim's Minimum Spanning Tree algorithm with Linked-Hashmap implementation of the Priority Queue
  • Parallel 3D distance matrix (img x img x orientation) computation
  • Euclidean distance metric for image boundary matching

Dependencies

python 3.7+
numpy 1.16+
opencv-python 4.1.2+

Execution guide

Quick demo with animation

pip install -r requirements.txt
bash demo.sh

create_jigsaw_pieces.py: read and slice image into rectangular jigsaw pieces and apply random set of transformations

create_jigsaw_pieces.py [OPTION] ${image_filename} ${x_slice} ${y_slice} ${keystring}

-v: increase verbosity

solve_puzzle.py: reconstruct original image by putting puzzle pieces together

solve_puzzle.py [OPTION] ${keystring}

-v: increase verbosity
-a: show animation
-t: show minimum spanning tree on top

image reconstruction algorithm

I[i,t]: all puzzle pieces (image, transformation)
S[i,j,t]: all-pairs puzzle piece similarity-matrix
G[y,x]: puzzle block
Q: priority queue

1 initialize S with similarity metric
2 set all nodes in G as inactive
3 root <- (im: I[0,0], pos: (0,0))
4 Q.enqueue(root)
5 while Q is not empty do
6     v <- Q.dequeue()
7     G[v.pos].activate(v)
8     for all w, dir in G.inactiveNeighbors(v) do
9         w.im <- arg_max(S[v.im,j,k] for all j and k)
10        w.pos <- (v.pos+dir)
11        Q.enqueue(w)
12    Q.removeAllDuplicates(v.im)

Time complexity analysis

N: number of images (puzzle pieces)
C: total cache miss (total number of duplicate puzzle pieces to be removed from the queue)
in all cases, C = O(N)

Operations \ Algorithms brute-force


brute-force
index mapping
hashmap
Prim's MST
max-heap

Prim's MST
linked-hashmap
matrix symmetry
similarity matrix O(256N2) O(32N2) O(32N2) O(16N2)
traverse all puzzle pieces O(N) O(N) O(N) O(N)
traverse all positions O(4N) O(4N) - -
argmax(img at pos(x,y)) O(256N) O(32N) O(32N) O(32N)
validate puzzle-block shape O(4N) O(1) O(1) O(1)
(PQueue) remove by ID - O(C) O(ClogN) O(C)
(PQueue) extract_min() - - O(1) O(1)
(PQueue) enqueue - - O(logN) O(N)
Total time complexity O(256N2)
+O(4096N4)
O(32N2)
+O(32(C+N2))
+O(128N3)
O(32N2)
+O(32(C+N2))
+O(3CNlog(N))
O(16N2)
+O(32(C+N2))
+O(N(C+N))
= O(N4) O(N3) O(N2log(N)) O(N2)

references

http://chenlab.ece.cornell.edu/people/Andy/publications/Andy_files/Gallagher_cvpr2012_puzzleAssembly.pdf
http://www.bmva.org/bmvc/2016/papers/paper139/paper139.pdf
https://en.wikipedia.org/wiki/Prim%27s_algorithm
https://en.wikipedia.org/wiki/Priority_queue
https://github.com/python/cpython/blob/master/Lib/heapq.py