-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathWeSaid.pde
182 lines (158 loc) · 5.67 KB
/
WeSaid.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* ,--. ,--. ,---. ,--. ,--.
* | | | | ,---. ' .-' ,--,--.`--' ,-| |
* | |.'.| || .-. :`. `-. ' ,-. |,--.' .-. |
* | ,'. |\ --..-' |\ '-' || |\ `-' |
* '--' '--' `----'`-----' `--`--'`--' `---'
* Copyright (c) David Elliott and Yuxin Tseng
*/
import java.util.List;
// Global vars
List<PImage> images = new ArrayList<PImage>();
PImage screenImage;
int HEADER_HEIGHT;
PrintWriter writer;
int currentDisplayY;
// Phone constants
final double IOS_HEADER_RATIO = 0.100;
final double AND_HEADER_RATIO = 0.135;
// Adjustable parameters per image
final boolean IS_IOS = false;
final int ALLOWABLE_PIXEL_COLOR_DIFFERENCE = 5;
final double MINIMUM_OVERLAP_PERCENTAGE = 12.0;
void setup() {
size(1080, 3500);
//fullScreen();
background(0);
noStroke();
fill(0);
//for (int i=1; i<=6; i++) {
// images.add(loadImage("screens/and-i" + i + ".png"));
//}
//for (int i=1; i<=5; i++) {
// images.add(loadImage("screens/ios-i" + i + ".PNG"));
//}
//for (int i=1; i<=3; i++) {
// images.add(loadImage("screens/ell" + i + ".png"));
//}
for (int i=1; i<=5; i++) {
images.add(loadImage("screens/and-groupme-" + i + ".png"));
}
HEADER_HEIGHT = (int) (((double) images.get(0).height) * (IS_IOS ? IOS_HEADER_RATIO : AND_HEADER_RATIO));
println((double) images.get(0).height);
println(HEADER_HEIGHT);
PImage img1 = null, img2;
for (int i=0; i<images.size() - 1; i++) {
if (img1 == null) {
img1 = images.get(i);
img1.loadPixels();
}
img2 = images.get(i+1);
img2.loadPixels();
int idealOverlapWindowHeight = calculateOverlap(img1, img2, i);
PImage newImage = createNewImage(img1, img2, idealOverlapWindowHeight);
img1 = newImage;
}
screenImage = img1;
image(img1, (displayWidth - img1.width) / 2, currentDisplayY, img1.width, img1.height);
img1.save("stitch.png");
println("Display Height: " + displayHeight);
println("Image Height: " + img1.height);
}
void draw() {
}
void mouseDragged() {
int yDiff = mouseY - pmouseY;
println(currentDisplayY);
currentDisplayY += yDiff;
if (currentDisplayY > 0) {
currentDisplayY = 0;
}
if (currentDisplayY < -(screenImage.height - displayHeight)) {
currentDisplayY = -(screenImage.height - displayHeight);
}
background(255);
image(screenImage, (displayWidth - screenImage.width) / 2, currentDisplayY, screenImage.width, screenImage.height);
}
int calculateOverlap(PImage img1, PImage img2, int iter) {
writer = createWriter("debug/PercentEquality" + iter + ".csv");
// Compare top window of img2 with bottom window of img1
int idealOverlapWindowHeight = 0;
double maxPercentEquality = 0;
int leftMax = img1.height;
int rightMax = img2.height - HEADER_HEIGHT;
for (int i=1; i < leftMax && i < rightMax; i++) {
// Caculate similarity
double percentEquality = percentageEquality(img1, img2, i);
if (percentEquality > maxPercentEquality) {
maxPercentEquality = percentEquality;
idealOverlapWindowHeight = i;
}
//println("Window size of " + i + " is: " + percentEquality);
writer.println(i + "," + percentEquality);
writer.flush();
}
// Threshold of non-overlap
if(maxPercentEquality < MINIMUM_OVERLAP_PERCENTAGE) {
idealOverlapWindowHeight = HEADER_HEIGHT;
}
println("Proposed window height for optimal overlap: " + idealOverlapWindowHeight);
println("Percent equality is now : "+ maxPercentEquality);
writer.flush();
writer.close();
return idealOverlapWindowHeight;
}
PImage createNewImage(PImage img1, PImage img2, int idealOverlapWindowHeight) {
// THE MOST AMAZING ALGORITHM IN THE WORLD:
// 1. Insert pixels from the left image in range [0, left.height - windowSize]
// 2. Find header size
// 3. Insert pixels from the right image in range [headerSize, right.height]
PImage newOutput;
int totalImageHeight = (img1.height - idealOverlapWindowHeight) + (img2.height - HEADER_HEIGHT);
newOutput = createImage(img1.width, totalImageHeight, RGB);
newOutput.loadPixels();
int img1CutOff = img1.height - idealOverlapWindowHeight;
for (int i = 0; i<img1CutOff; i++){
for(int j = 0; j<img1.width; j++){
newOutput.pixels[i * img1.width + j]= img1.pixels[i * img1.width + j];
}
}
// Second part of the image
for (int i = HEADER_HEIGHT; i<img2.height; i++){
for(int j = 0; j<img2.width; j++){
newOutput.pixels[(img1CutOff - HEADER_HEIGHT + i) * img1.width + j]= img2.pixels[i * img2.width + j];
}
}
newOutput.updatePixels();
return newOutput;
}
double percentageEquality(PImage left, PImage right, int totalWindowSize) {
int totalEqual = 0;
// Gradually perform comparisons on the bottom of the left image and the top of the right image
// with increasing window size.
for (int i=0; i < totalWindowSize; i++) {
int leftRowNumber = left.height - totalWindowSize + i;
int rightRowNumber = i + HEADER_HEIGHT;
// We have the row number for the left (offset from bottom) and right (from top).
// Now compare pixels row by row.
for (int x=0; x < left.width; x++) {
if (isCloseEnough(left.pixels[left.width * leftRowNumber + x],
right.pixels[right.width * rightRowNumber + x])) {
totalEqual++;
}
}
}
double percentEqual = ((double) totalEqual) / ((double) left.width * totalWindowSize) * 100.0;
return percentEqual;
}
boolean isCloseEnough(color a, color b) {
float ra = a >> 16 & 0xFF;
float ga = a >> 8 & 0xFF;
float ba = a & 0xFF;
float rb = b >> 16 & 0xFF;
float gb = b >> 8 & 0xFF;
float bb = b & 0xFF;
return abs(ra - rb) < ALLOWABLE_PIXEL_COLOR_DIFFERENCE &&
abs(ga - gb) < ALLOWABLE_PIXEL_COLOR_DIFFERENCE &&
abs(ba - bb) < ALLOWABLE_PIXEL_COLOR_DIFFERENCE;
}