sourceextensions/image/demos/photo-lab.xtl

1⍝# The photo lab: a photo is an array. Buzz Aldrin on the Moon (Apollo 2⍝# 11, NASA, public domain: demos/data/PROVENANCE.txt) read as numbers; 3⍝# filters and edges by rotating the array (the Life idiom), a color 4⍝# toning by an inner product, and the SVD compressing it at several 5⍝# ranks -- the native code reads, writes and decomposes, X_eTaL does 6⍝# the rest. Pictures go to work/photo-lab/. 7⍝# Run: just demo image photo-lab 8 9ⁱᵐ⁼u̲se< "Image" 10ˡᵃ⁼u̲se< "Linalg" 11 12src ← "demos/data/aldrin.jpg" 13out ← "work/photo-lab/" 14ᵘr̲ound ← { v → (f̲loat f̲loor 0.5 + 1000.0 × v) ÷ 1000.0 } 15ᵘm̲ean ← { v → ('+ r̲/ f̲loat r̲avel v) ÷ f̲loat t̲ally r̲avel v } 16 17⍝## 1. the photo as numbers: 240 by 246, gray from 0 (black) to 1 18 19"the photo (height, width), and the working size:" 20ⁱᵐs̲ize src 21p ← 240 246 ⁱᵐr̲esize ⁱᵐg̲ray src 22s̲hape p 23"mean brightness, darkest, brightest:" 24ᵘr̲ound (ᵘm̲ean p) c̲at ('m̲in r̲/ r̲avel p) c̲at 'm̲ax r̲/ r̲avel p 25 26⍝## 2. filters by rotation: each pixel and its 8 neighbors, as Life 27 28⍝# counts neighbors (the edges wrap around, as rotations do) 29box ← ('+ r̲/₁₂ -1 0 1 o̲-₁₂ p) ÷ 9.0 30sharp ← 0.0 m̲ax 1.0 m̲in p + 1.5 × p − box 31⍝# edges: Sobel, horizontal and vertical differences of the blurred rows 32⍝# and columns, and their length 33sx ← ((-1 o̲-₂ p) − 1 o̲-₂ p) 34sy ← ((-1 o̲-₁ p) − 1 o̲-₁ p) 35gx ← sx + (1 o̲-₁ sx) + -1 o̲-₁ sx 36gy ← sy + (1 o̲-₂ sy) + -1 o̲-₂ sy 37edge ← 1.0 m̲in 0.5 × ((gx ^ 2.0) + gy ^ 2.0) ^ 0.5 38"edge strength: mean, share of pixels on a strong edge (over 0.5):" 39ᵘr̲ound (ᵘm̲ean edge) c̲at ᵘm̲ean edge > 0.5 40n ← (out c̲at "filters.png") ⁱᵐw̲rite! p c̲at₂ box c̲at₂ sharp c̲at₂ edge 41 42⍝## 3. color: a sepia toning, every pixel's red, green and blue times 43 44⍝# one 3 by 3 matrix (an inner product over the last axis) 45c ← 240 246 ⁱᵐr̲esize ⁱᵐr̲ead src 46sepia ← 3 3 r̲eshape 0.393 0.349 0.272 0.769 0.686 0.534 0.189 0.168 0.131 47toned ← 1.0 m̲in c '+ '× i̲nner sepia 48n ← (out c̲at "sepia.png") ⁱᵐw̲rite! c c̲at₂ toned 49 50⍝## 4. the SVD: the photo as a sum of rank-1 pictures, largest first; 51 52⍝# keeping k of 240 stores k times (240 + 246 + 1) numbers 53u ← ˡᵃs̲vdU p 54s ← ˡᵃs̲vdS p 55v ← ˡᵃs̲vdV p 56"the five largest singular values, and the share of the energy in the first 5, 20, 50:" 57ᵘr̲ound 5 t̲ake s 58e ← '+ s̲\ s ^ 2.0 59ᵘr̲ound (5 20 50 s̲elect e) ÷ f̲irst -1 t̲ake e 60ᵘr̲ank ← { k → ((k t̲ake₂ u) × (s̲hape k t̲ake₂ u) r̲eshape k t̲ake s) '+ '× i̲nner 2 1 t̲ranspose k t̲ake₂ v } 61r5 ← ᵘr̲ank 5 62r20 ← ᵘr̲ank 20 63r50 ← ᵘr̲ank 50 64"rank, storage (share of the photo's numbers), error (root mean square):" 65ᵘe̲rr ← { r → (ᵘm̲ean (r − p) ^ 2.0) ^ 0.5 } 66ᵘr̲ound 3 3 r̲eshape (f̲loat 5 20 50) c̲at ((f̲loat 5 20 50 × 487) ÷ 59040.0) c̲at (ᵘe̲rr r5) c̲at (ᵘe̲rr r20) c̲at ᵘe̲rr r50 67n ← (out c̲at "svd.png") ⁱᵐw̲rite! p c̲at₂ r50 c̲at₂ r20 c̲at₂ r5 68"written: work/photo-lab/filters.png, sepia.png, svd.png"