mirror of
https://github.com/ychalier/datamoshing.git
synced 2026-06-16 12:31:19 +02:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Optical Flow Transfer from the Webcam</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.css" />
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/ychalier/pifekit/pifekit.min.js"></script>
|
||||
<script src="opencv.js"></script>
|
||||
<script src="master.js"></script>
|
||||
<style>
|
||||
* {
|
||||
font-family: "Fira Code", monospace !important;
|
||||
color: white;
|
||||
--color-accent-0: hsl(192, 63%, 59%);
|
||||
--color-accent-1: hsl(192, 64%, 61%);
|
||||
--color-accent-2: hsl(192, 63%, 62%);
|
||||
--color-accent-3: hsl(192, 63%, 64%);
|
||||
--color-accent-4: hsl(192, 63%, 66%);
|
||||
--color-accent-5: hsl(192, 63%, 69%);
|
||||
--color-accent-6: hsla(192, 63%, 69%, 0.2);
|
||||
--color-accent-7: hsla(192, 63%, 69%, 0.95);
|
||||
--color-accent-8: hsl(192, 64%, 74%);
|
||||
--color-accent-9: hsl(192, 63%, 79%);
|
||||
--color-accent-a: hsl(192, 62%, 99%);
|
||||
--color-accent-b: hsl(192, 63%, 100%);
|
||||
--color-accent-c: hsl(192, 65%, 13%);
|
||||
--color-accent-d: hsl(192, 67%, 89%);
|
||||
--color-accent-e: hsl(192, 100%, 90%);
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 100vh;
|
||||
background: black;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: var(--color-accent-5);
|
||||
}
|
||||
|
||||
table {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: left;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
canvas {
|
||||
width: 512px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container text-center">
|
||||
<h1>Optical Flow Transfer from the Webcam</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
You:<br>
|
||||
<video id="video"></video>
|
||||
</td>
|
||||
<td>
|
||||
Transfer:<br>
|
||||
<canvas id="canvas"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<footer class="text-center">
|
||||
<p>
|
||||
More details on my <a href="https://chalier.fr/blog/datamoshing">blog</a> · Images from <a href="https://picsum.photos/">Lorem Picsum</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
navigator.getMedia = (navigator.getUserMedia ||
|
||||
navigator.webkitGetUserMedia ||
|
||||
navigator.mozGetUserMedia ||
|
||||
navigator.msGetUserMedia);
|
||||
|
||||
async function start_optical_flow_effect() {
|
||||
|
||||
var streaming = false;
|
||||
const width = 256;
|
||||
var height;
|
||||
const video = document.getElementById("video");
|
||||
const canvas = document.getElementById("canvas");
|
||||
const context_image = canvas.getContext("2d");
|
||||
var cap;
|
||||
|
||||
async function load_webcam() {
|
||||
navigator.getMedia({ video: true, audio: false }, (stream) => {
|
||||
if (navigator.mozGetUserMedia) {
|
||||
video.srcObject = stream;
|
||||
} else {
|
||||
video.src = vendorURL.createObjectURL(stream);
|
||||
}
|
||||
video.play();
|
||||
}, (err) => {
|
||||
console.log("An error occured! " + err);
|
||||
});
|
||||
|
||||
video.addEventListener("canplay", function(ev) {
|
||||
if (!streaming) {
|
||||
height = video.videoHeight / (video.videoWidth / width);
|
||||
video.setAttribute('width', width);
|
||||
video.setAttribute('height', height);
|
||||
streaming = true;
|
||||
cap = new cv.VideoCapture(video);
|
||||
}
|
||||
}, false);
|
||||
|
||||
while (!streaming) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
}
|
||||
}
|
||||
|
||||
async function load_image() {
|
||||
canvas.style.imageRendering = "crisp-edges";
|
||||
const image = new Image();
|
||||
image.crossOrigin = "anonymous";
|
||||
image.src = `https://picsum.photos/${ width }/${ height }`;
|
||||
await image.decode();
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
context_image.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);
|
||||
}
|
||||
|
||||
await load_webcam();
|
||||
await load_image();
|
||||
// await Promise.all([load_webcam(), load_image()]);
|
||||
|
||||
function takepicture() {
|
||||
let frame = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
let frame_gray = new cv.Mat();
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, frame_gray, cv.COLOR_RGBA2GRAY);
|
||||
return frame_gray;
|
||||
}
|
||||
|
||||
let reference = takepicture();
|
||||
var image_data = context_image.getImageData(0, 0, width, height);
|
||||
while (true) {
|
||||
let current = takepicture();
|
||||
let flow = new cv.Mat();
|
||||
cv.calcOpticalFlowFarneback(reference, current, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
|
||||
let image_data_copy = [...image_data.data];
|
||||
for (let i = 0; i < height; i++) {
|
||||
for (let j = 0; j < width; j++) {
|
||||
let k = (i * width + j);
|
||||
let ii = i + Math.round(flow.data32F[k * 2]);
|
||||
let jj = j + Math.round(flow.data32F[k * 2 + 1]);
|
||||
image_data.data[(ii * width + jj) * 4] = image_data_copy[(i * width + j) * 4];
|
||||
image_data.data[(ii * width + jj) * 4 + 1] = image_data_copy[(i * width + j) * 4 + 1];
|
||||
image_data.data[(ii * width + jj) * 4 + 2] = image_data_copy[(i * width + j) * 4 + 2];
|
||||
image_data.data[(ii * width + jj) * 4 + 3] = image_data_copy[(i * width + j) * 4 + 3];
|
||||
}
|
||||
}
|
||||
context_image.putImageData(image_data, 0, 0);
|
||||
await new Promise(x => requestAnimationFrame(x));
|
||||
current.copyTo(reference);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener("load", start_optical_flow_effect);
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user