summaryrefslogtreecommitdiff
path: root/tools/cnn_v2_test/index.html
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-13 23:32:32 +0100
committerskal <pascal.massimino@gmail.com>2026-02-13 23:32:32 +0100
commit87a27bf022d7fba68e3a945ee29c854c6e1ae2d7 (patch)
tree412cff8626ee5d10ed241f0828db0eac5ad4762d /tools/cnn_v2_test/index.html
parent25f3c735e304a9af7c0bf8f7d62228907d03e5c5 (diff)
CNN v2: Add debugging tools for mismatch investigation
Add identity weight generator and composited layer save for debugging HTML/C++ output differences. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'tools/cnn_v2_test/index.html')
-rw-r--r--tools/cnn_v2_test/index.html59
1 files changed, 59 insertions, 0 deletions
diff --git a/tools/cnn_v2_test/index.html b/tools/cnn_v2_test/index.html
index ca89fb4..3977d9f 100644
--- a/tools/cnn_v2_test/index.html
+++ b/tools/cnn_v2_test/index.html
@@ -1395,6 +1395,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>';
@@ -1836,6 +1837,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}_${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();