1
+ function parallaxPlot(img1 , img2 )
2
+ % PARAKKAXPLOT(IMG1, IMG2) - Plot scatter points that shows the black
3
+ % and white IMG1 with IMG2 hidden behind IMG1 pixels.
4
+ % Rotating the axes around Z will reveal IMG2, and hide IMG1 behind IMG2.
5
+
6
+ arguments
7
+ img1 (: ,: ) double
8
+ img2 (: ,: ) double
9
+ end
10
+
11
+ [ verts1(: ,2 ), verts1(: ,1 ) ] = find(img1 );
12
+ [ verts2(: ,2 ), verts2(: ,1 ) ] = find(img2 );
13
+
14
+ verts3 = parallax(verts1 , verts2 );
15
+
16
+ scatter3(verts3(: ,1 ), verts3(: ,3 ), verts3(: ,2 ), 20 , ' w' , ' Marker' ,' .' );
17
+
18
+ view([ 0 0 ]);
19
+
20
+ axis vis3d padded on
21
+ box on
22
+ daspect([1 1 1 ]);
23
+ xticks([]);
24
+ yticks([]);
25
+ zticks([]);
26
+ set(gca ,' ZDir' ,' reverse' ,...
27
+ ' Color' ,' none' ,...
28
+ ' BoxStyle' ,' full' ,...
29
+ ' XColor' ,[.5 .5 .5 ],...
30
+ ' YColor' ,[.5 .5 .5 ],...
31
+ ' ZColor' ,[.5 .5 .5 ]);
32
+ set(gcf ,' Color' ,' black' );
33
+ end
34
+
35
+ function verts3 = parallax(v1 , v2 )
36
+ % Convert img1 and img2 into a single set of vertices
37
+ % which represent BOTH images, where 1 image is hidden behind
38
+ % the other, but revealed with a view change.
39
+
40
+ verts3 = v1 ;
41
+ verts3(: ,3 ) = - 1 ; % Starts with img1, add Z values. -1 means not used
42
+
43
+ % Basic idea: V1 is the image we first show, this is the reference image.
44
+ % For each vertex in V2, find an unused vertrc in V1 at the same Y and set Z to the X.
45
+ % If NO MATCH, we need to add a new vertex
46
+
47
+ for idx = 1 : height(v2 )
48
+ % First find points that haven't been used yet.
49
+ match = find_matching_index(verts3 , v2 , idx , ' unused' );
50
+
51
+ if match
52
+ % We have a match, set Z of a random pt in img1 to x of img2.
53
+ verts3(match ,3 ) = v2(idx ,1 );
54
+ else
55
+ % We have no matches. Look for existing matches of the Y coord, and hide
56
+ % our new point behind that.
57
+ match = find_matching_index(verts3 , v2 , idx , ' any' );
58
+ if match
59
+ % We found at least one, so hide this new pixel behind one of them
60
+ verts3(end + 1 ,: ) = [ verts3(match ,1 ) v2(idx ,2 ) v2(idx ,1 ) ]; % #ok
61
+ else
62
+ % No match - hide this in the margins
63
+ verts3(end + 1 ,: ) = [ - 1 v2(idx ,2 ) v2(idx ,1 ) ]; % #ok
64
+ end
65
+ end
66
+ end
67
+
68
+ % Lastly, find points from the first image (V1) that don't already
69
+ % have a corresponding point from the second image (V2), and move
70
+ % them behind other points in V2.
71
+ % Note: All points from V2 are now in our destination image VERTS3.
72
+ lost = find(verts3(: ,3 )==-1 );
73
+ for lidx = 1 : numel(lost )
74
+ idx = lost(lidx );
75
+ % Only find used points since we are finding homes for unused points.
76
+ match = find_matching_index(verts3 , verts3 , idx , ' used' );
77
+ if match
78
+ verts3(idx ,3 ) = verts3(match ,3 );
79
+ else
80
+ % Just ignore it.
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ function match = find_matching_index(dest , src , idx , flag )
87
+ % For the DEST image, find a random vertex in DEST that matches the
88
+ % SRC image point at IDX.
89
+ % If UNUSED is true, make sure the found vertex has not be used already.
90
+ mask = dest(: ,2 )==src(idx ,2 );
91
+ switch flag
92
+ case ' unused'
93
+ % Only match vertices not yet used.
94
+ mask = mask & dest(: ,3 )==-1 ;
95
+ case ' used'
96
+ % Only match vertices that have been used.
97
+ mask = mask & dest(: ,3 )~=-1 ;
98
+ end
99
+ % Get the indices to the found points
100
+ match_indices = find(mask );
101
+ if isempty(match_indices )
102
+ match = 0 ;
103
+ else
104
+ % Of the found points, find a random vertex from that list.
105
+ match = match_indices(randi(numel(match_indices )));
106
+ end
107
+ end
0 commit comments