c070f40
961c25c
c070f40
| 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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MCMC Animation Generator (Stable Diffusion)</title>
<style>
body { background: #1e1e2e; color: white; font-family: sans-serif; }
canvas { background: black; display: block; margin: 10px auto; border: 2px solid #4ecdc4; }
.log { max-height: 200px; overflow-y: auto; font-family: monospace; font-size: 12px; background: #111; padding: 10px; border-radius: 10px; margin: 10px; }
</style>
</head>
<body>
<h1 style="text-align:center">MCMC Animation Generator (Stable Diffusion)</h1>
<div style="text-align:center">
<input type="text" id="prompt" placeholder="Prompt" value="A surreal dreamscape" />
<input type="number" id="seed" value="42" />
<button onclick="generateInitialImage()">Generate Image</button>
<button onclick="startAnimation()">Start Animation</button>
</div>
<canvas id="canvas" width="512" height="512"></canvas>
<div class="log" id="log"></div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const logEl = document.getElementById('log');
let state = {
currentPosition: Array.from({ length: 100 }, () => Math.random() * 2 - 1),
currentVelocity: Array(100).fill(0),
currentEnergy: 0,
baseImage: null, // This will now store a canvas element
seed: 42,
};
function log(msg) {
logEl.innerHTML += `[${new Date().toLocaleTimeString()}] ${msg}<br>`;
logEl.scrollTop = logEl.scrollHeight;
}
// This function is no longer needed as we're fetching from Stable Diffusion
// function generateMockImage(seed) { ... }
async function generateInitialImage() {
const prompt = document.getElementById('prompt').value;
const seed = parseInt(document.getElementById('seed').value);
state.seed = seed;
log('Generating image with Stable Diffusion...');
try {
const response = await fetch('
https://devinendorphin-mcmc-generator.hf.space/run/predict', { // REPLACE THIS URL
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: [prompt, seed] }),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
}
const result = await response.json();
// Assuming the image is returned as a base64 data URL (e.g., "data:image/png;base64,...")
const imageDataUrl = result.data[0];
const img = new Image();
img.src = imageDataUrl;
// Wait for the image to load before drawing
await new Promise((resolve) => { img.onload = resolve; });
// Clear the main canvas and draw the new image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, 512, 512);
// Create a new canvas to store the base image for MCMC operations
state.baseImage = document.createElement('canvas');
state.baseImage.width = 512;
state.baseImage.height = 512;
const baseCtx = state.baseImage.getContext('2d');
baseCtx.drawImage(img, 0, 0, 512, 512);
const imageData = ctx.getImageData(0, 0, 512, 512);
state.currentEnergy = calculateEnergy(imageData);
log('Stable Diffusion image loaded and energy calculated.');
} catch (e) {
log('Error using Hugging Face Space: ' + e.message);
}
}
function calculateEnergy(imageData) {
let energy = 0;
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const intensity = (data[i] + data[i + 1] + data[i + 2]) / 3;
energy += Math.pow(intensity - 128, 2) * 0.00001;
}
return energy;
}
function generateImageVariation(base, params) {
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext('2d');
ctx.drawImage(base, 0, 0); // 'base' is now a canvas element
const imgData = ctx.getImageData(0, 0, 512, 512);
const data = imgData.data;
for (let i = 0; i < data.length; i += 4) {
const p = params[Math.floor((i / 4) % 100)];
data[i] += p * 10;
data[i + 1] += p * 5;
data[i + 2] += p * 15;
}
ctx.putImageData(imgData, 0, 0);
return canvas;
}
function calculateGradient(position, baseImage) {
const epsilon = 0.01;
const grad = new Array(position.length).fill(0);
for (let i = 0; i < position.length; i++) {
const posPlus = [...position];
const posMinus = [...position];
posPlus[i] += epsilon;
posMinus[i] -= epsilon;
const imgPlus = generateImageVariation(baseImage, posPlus);
const imgMinus = generateImageVariation(baseImage, posMinus);
const energyPlus = calculateEnergy(imgPlus.getContext('2d').getImageData(0, 0, 512, 512));
const energyMinus = calculateEnergy(imgMinus.getContext('2d').getImageData(0, 0, 512, 512));
grad[i] = (energyPlus - energyMinus) / (2 * epsilon);
}
return grad;
}
async function startAnimation() {
if (!state.baseImage) return log('No base image loaded. Please generate an image first.');
log('Starting animation...');
const T = 1.0, stepSize = 0.01, damping = 0.5;
for (let frame = 0; frame < 30; frame++) {
const grad = calculateGradient(state.currentPosition, state.baseImage);
const newVelocity = state.currentVelocity.map((v, i) => v - stepSize * (grad[i] + damping * v) + (Math.random() * 2 - 1) * Math.sqrt(2 * damping * T * stepSize));
const newPosition = state.currentPosition.map((x, i) => x + stepSize * newVelocity[i]);
const proposedImage = generateImageVariation(state.baseImage, newPosition);
const proposedEnergy = calculateEnergy(proposedImage.getContext('2d').getImageData(0, 0, 512, 512));
let accept = false;
if (proposedEnergy <= state.currentEnergy) accept = true;
else if (Math.random() < Math.exp(-(proposedEnergy - state.currentEnergy) / T)) accept = true;
if (accept) {
state.currentPosition = newPosition;
state.currentVelocity = newVelocity;
state.currentEnergy = proposedEnergy;
ctx.drawImage(proposedImage, 0, 0);
log(`Frame ${frame + 1}: Accepted, Energy: ${proposedEnergy.toFixed(4)}`);
} else {
log(`Frame ${frame + 1}: Rejected`);
}
await new Promise(res => setTimeout(res, 50));
}
log('Animation complete.');
}
</script>
</body>
</html> |