xxxxxxxxxx
99
/* * * * * * * * * * * * * * * * * * *
* Image Stitching (scale & translate)
*
* Keith O'Hara <kohara2@swarthmore.edu>
* revised for p5 & mljs (Feb 2024)
*/
let cap; // webcam capture
let p1 = []; // clicked points
let p2 = []; // window corners
let homography = ML.Matrix.eye(3, 3);
function setup() {
createCanvas(640, 480);
cap = createCapture(VIDEO);
cap.size(width, height);
cap.hide();
p2.push(new p5.Vector(0, 0, 1));
//p2.push(new p5.Vector(cap.width, 0, 1));
p2.push(new p5.Vector(cap.width, cap.height, 1));
//p2.push(new p5.Vector(0, cap.height, 1));
pixelDensity(1);
print(homography);
}
function estimate(p1, p2) {
let H = ML.Matrix.eye(3, 3);
if (p1.length == p2.length) {
let as = [];
let bs = [];
// Creates the estimation matrix
for (let i =0; i < p1.length; i++) {
as.push([p2[i].x, 1, 0]);
as.push([p2[i].y, 0, 1]);
bs.push([p1[i].x]);
bs.push([p1[i].y]);
}
let mls_a = new ML.Matrix(as);
let mls_b = new ML.Matrix(bs);
let mls_x = ML.MatrixLib.solve(mls_a, mls_b);
let s = mls_x.data[0][0];
let t_x = mls_x.data[1][0];
let t_y = mls_x.data[2][0];
H.data[0][0] = s;
H.data[1][1] = s;
H.data[0][2] = t_x;
H.data[1][2] = t_y;
}
print(H.data);
return H;
}
function mousePressed() {
if (p1.length >= p2.length) p1 = [];
let v = new p5.Vector(mouseX, mouseY, 1);
p1.push(v);
if (p1.length == p2.length) {
homography = estimate(p1, p2);
}
}
function draw() {
background(0);
cap.loadPixels();
loadPixels();
// perform forward warping
for (let x = 0; x < cap.width; x++) {
for (let y = 0; y < cap.height; y++) {
let idx = (y * cap.width + x) * 4;
let v = new ML.Matrix([[x], [y], [1]]);
let tv = homography.mmul(v);
let x1 = Math.round(tv.get(0, 0) / tv.get(2, 0));
let y1 = Math.round(tv.get(1, 0) / tv.get(2, 0));
if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height) {
let idx1 = (y1 * width + x1) * 4;
pixels[idx1] = cap.pixels[idx];
pixels[idx1 + 1] = cap.pixels[idx + 1];
pixels[idx1 + 2] = cap.pixels[idx + 2];
pixels[idx1 + 3] = cap.pixels[idx + 3];
}
}
}
updatePixels();
fill(255, 255, 0);
// draw the selected points
for (let i = 0; i < p1.length; i++) {
ellipse(p1[i].x, p1[i].y, 2, 2);
text(str(i), p1[i].x, p1[i].y);
}
}