code wiki / (root) / nx_scale_test.nx

nx_scale_test.nx source

↩ module page · 108 lines · 3926 B

1// nx_scale_test.nx -- smoke for V6 scale pyramid primitives. 2 3import "syscalls.nx" 4import "nx_image.nx" 5import "nx_scale.nx" 6 7func main() -> i64 { 8 // === Test 1: Gaussian blur preserves uniform field === 9 // All pixels 100. After blur all pixels should still be 100 10 // (binomial sums to 16, /16 = 1). Border pixels lose energy 11 // due to zero-padded out-of-bounds reads -- but the interior 12 // should be exactly 100. 13 let img1: *Image = nx_image_alloc(16, 16, 1) 14 var y: i64 = 0 15 while y < 16 { 16 var x: i64 = 0 17 while x < 16 { 18 nx_image_set(img1, x, y, 0, 100) 19 x = x + 1 20 } 21 y = y + 1 22 } 23 let b1: *Image = nx_scale_gauss_blur(img1) 24 // Interior pixel (8, 8) should be exactly 100. 25 if nx_image_get(b1, 8, 8, 0) != 100 { return 1 } 26 27 // === Test 2: downsample 2x dimensions === 28 let d1: *Image = nx_scale_downsample_2x(img1) 29 if d1.width != 8 { return 10 } 30 if d1.height != 8 { return 11 } 31 // Interior value preserved 32 if nx_image_get(d1, 4, 4, 0) != 100 { return 12 } 33 34 // === Test 3: full Gaussian pyramid === 35 let py: *GaussPyramid = nx_scale_gauss_pyramid(img1, 4) 36 if py.n_levels != 4 { return 20 } 37 let l0: *Image = nx_scale_pyramid_get(py, 0) 38 let l1: *Image = nx_scale_pyramid_get(py, 1) 39 let l2: *Image = nx_scale_pyramid_get(py, 2) 40 let l3: *Image = nx_scale_pyramid_get(py, 3) 41 if l0.width != 16 { return 21 } 42 if l1.width != 8 { return 22 } 43 if l2.width != 4 { return 23 } 44 if l3.width != 2 { return 24 } 45 46 // === Test 4: DoG on uniform image is zero === 47 let dog1: *ImageS64 = nx_scale_dog(img1) 48 if nx_image_s64_get(dog1, 8, 8) != 0 { return 30 } 49 50 // === Test 5: DoG on a single bright spot === 51 // Build 32x32 image with bright square at center. 52 let img2: *Image = nx_image_alloc(32, 32, 1) 53 // Background 50 54 var y2: i64 = 0 55 while y2 < 32 { 56 var x2: i64 = 0 57 while x2 < 32 { 58 nx_image_set(img2, x2, y2, 0, 50) 59 x2 = x2 + 1 60 } 61 y2 = y2 + 1 62 } 63 // Bright 6x6 blob at center 64 var yb: i64 = 13 65 while yb < 19 { 66 var xb: i64 = 13 67 while xb < 19 { 68 nx_image_set(img2, xb, yb, 0, 200) 69 xb = xb + 1 70 } 71 yb = yb + 1 72 } 73 let dog2: *ImageS64 = nx_scale_dog(img2) 74 // Detect extrema. 75 let bx: *i64 = (sys_mmap(50 * 8)) as *i64 76 let by: *i64 = (sys_mmap(50 * 8)) as *i64 77 let bs: *i64 = (sys_mmap(50 * 8)) as *i64 78 let n_blobs: i64 = nx_scale_dog_extrema(dog2, 2, 50, bx, by, bs) 79 if n_blobs == 0 { return 40 } 80 // At least one extremum should be near the blob center (16, 16). 81 var found_blob: i64 = 0 82 var bi: i64 = 0 83 while bi < n_blobs { 84 let dx: i64 = bx[bi] - 16 85 let dy: i64 = by[bi] - 16 86 let d2: i64 = dx * dx + dy * dy 87 if d2 <= 25 { found_blob = 1 } // within 5px 88 bi = bi + 1 89 } 90 if found_blob != 1 { return 41 } 91 92 // === Test 6: pyramid preserves bright-blob center across scales === 93 let py2: *GaussPyramid = nx_scale_gauss_pyramid(img2, 3) 94 let l0p: *Image = nx_scale_pyramid_get(py2, 0) 95 let l1p: *Image = nx_scale_pyramid_get(py2, 1) 96 let l2p: *Image = nx_scale_pyramid_get(py2, 2) 97 // Level 1 is 16x16. Blob originally at (13..18, 13..18) maps to (6.5..9, 6.5..9). 98 // Pixel (8, 8) at level 1 should be much brighter than (1, 1). 99 let v1_center: i64 = nx_image_get(l1p, 8, 8, 0) 100 let v1_corner: i64 = nx_image_get(l1p, 1, 1, 0) 101 if v1_center <= v1_corner { return 50 } 102 // Level 2 is 8x8. Blob center maps to (4, 4). 103 let v2_center: i64 = nx_image_get(l2p, 4, 4, 0) 104 let v2_corner: i64 = nx_image_get(l2p, 0, 0, 0) 105 if v2_center <= v2_corner { return 51 } 106 107 return 0 108}