summaryrefslogtreecommitdiff
path: root/tools/cnn_v2_test/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cnn_v2_test/index.html')
-rw-r--r--tools/cnn_v2_test/index.html72
1 files changed, 65 insertions, 7 deletions
diff --git a/tools/cnn_v2_test/index.html b/tools/cnn_v2_test/index.html
index ca89fb4..2ec934d 100644
--- a/tools/cnn_v2_test/index.html
+++ b/tools/cnn_v2_test/index.html
@@ -543,12 +543,10 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
}
}
- if (is_output) {
- output[c] = clamp(sum, 0.0, 1.0);
- } else if (params.is_layer_0 != 0u) {
- output[c] = clamp(sum, 0.0, 1.0); // Layer 0: clamp [0,1]
+ if (is_output || params.is_layer_0 != 0u) {
+ output[c] = 1.0 / (1.0 + exp(-sum)); // Sigmoid [0,1]
} else {
- output[c] = max(0.0, sum); // Middle layers: ReLU
+ output[c] = max(0.0, sum); // ReLU
}
}
@@ -1395,6 +1393,7 @@ class CNNTester {
const label = `Layer ${i - 1}`;
html += `<button onclick="tester.visualizeLayer(${i})" id="layerBtn${i}">${label}</button>`;
}
+ html += `<button onclick="tester.saveCompositedLayer()" style="margin-left: 20px; background: #28a745;">Save Composited</button>`;
html += '</div>';
html += '<div class="layer-grid" id="layerGrid"></div>';
@@ -1526,7 +1525,7 @@ class CNNTester {
continue;
}
- const vizScale = layerIdx === 0 ? 1.0 : 0.5; // Static: 1.0, CNN layers: 0.5 (4 channels [0,1])
+ const vizScale = 1.0; // Always 1.0, shader clamps to [0,1]
const paramsBuffer = this.device.createBuffer({
size: 8,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
@@ -1618,7 +1617,8 @@ class CNNTester {
const layerTex = this.layerOutputs[layerIdx];
if (!layerTex) return;
- const vizScale = layerIdx === 0 ? 1.0 : 0.5;
+ // Always 1.0, shader clamps to [0,1] - show exact layer values
+ const vizScale = 1.0;
const actualChannel = channelOffset + this.selectedChannel;
const paramsBuffer = this.device.createBuffer({
@@ -1836,6 +1836,64 @@ class CNNTester {
this.setStatus(`Save failed: ${err.message}`, true);
}
}
+
+ async saveCompositedLayer() {
+ if (!this.currentLayerIdx) {
+ this.log('No layer selected for compositing', 'error');
+ return;
+ }
+
+ try {
+ const canvases = [];
+ for (let i = 0; i < 4; i++) {
+ const canvas = document.getElementById(`layerCanvas${i}`);
+ if (!canvas) {
+ this.log(`Canvas layerCanvas${i} not found`, 'error');
+ return;
+ }
+ canvases.push(canvas);
+ }
+
+ const width = canvases[0].width;
+ const height = canvases[0].height;
+ const compositedWidth = width * 4;
+
+ // Create composited canvas
+ const compositedCanvas = document.createElement('canvas');
+ compositedCanvas.width = compositedWidth;
+ compositedCanvas.height = height;
+ const ctx = compositedCanvas.getContext('2d');
+
+ // Composite horizontally
+ for (let i = 0; i < 4; i++) {
+ ctx.drawImage(canvases[i], i * width, 0);
+ }
+
+ // Convert to grayscale
+ const imageData = ctx.getImageData(0, 0, compositedWidth, height);
+ const pixels = imageData.data;
+ for (let i = 0; i < pixels.length; i += 4) {
+ const gray = 0.299 * pixels[i] + 0.587 * pixels[i + 1] + 0.114 * pixels[i + 2];
+ pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
+ }
+ ctx.putImageData(imageData, 0, 0);
+
+ // Save as PNG
+ const blob = await new Promise(resolve => compositedCanvas.toBlob(resolve, 'image/png'));
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `composited_layer${this.currentLayerIdx - 1}_${compositedWidth}x${height}.png`;
+ a.click();
+ URL.revokeObjectURL(url);
+
+ this.log(`Saved composited layer: ${a.download}`);
+ this.setStatus(`Saved: ${a.download}`);
+ } catch (err) {
+ this.log(`Failed to save composited layer: ${err.message}`, 'error');
+ this.setStatus(`Compositing failed: ${err.message}`, true);
+ }
+ }
}
const tester = new CNNTester();