Array convolutions

One-dimensional convolutions

One dimensional signals such as audio samples can be filtered using a 1D convolution. Convolution can also be performed using composite values such as complex numbers.

(use-modules (aiscm sequence) (aiscm convolution) (aiscm complex))
(convolve (seq 0 0 2 2 2 2 0 0) (seq 1 0 -1))
;#<sequence<int<16,signed>>>:
;(0 2 2 0 0 -2 -2 0)
(convolve (seq 0 0 1 0 0 0 0 0 2 0) (seq +1 +i -1 -i))
;#<sequence<complex<int<16,signed>>>>:
;(1 0.0+1.0i -1 0.0-1.0i 0 0 2 0.0+2.0i -2 0.0-2.0i)

Two-dimensional convolutions

Convolution can also be performed on 2D data.

(use-modules (aiscm sequence) (aiscm convolution))
(convolve (arr (0 0 0 0 0) (0 0 1 0 0) (0 0 0 0 0)) (arr (-1 0 1) (-2 0 2) (-1 0 1)))
;#<sequence<sequence<int<16,signed>>>>:
;((0 -1 0 1 0)
; (0 -2 0 2 0)
; (0 -1 0 1 0))

Image processing

Here is the test input image for comparison.

star-ferry.jpg

star-ferry.jpg

Box filter

A simple filter for blurring an image is the box filter. Note that convolution is performed on a colour image.

(use-modules (aiscm magick) (aiscm convolution) (aiscm sequence) (aiscm element) (aiscm rgb) (aiscm int) (aiscm jit))
(define (box-filter img) (/ (convolve img (fill <sint> '(5 5) 1)) 25))
(write-image (to-type <ubytergb> (box-filter (read-image "star-ferry.jpg"))) "box-filter.jpg")
box-filter.jpg

box-filter.jpg

Sharpen

Image sharpening increases the difference between neighbouring pixels.

(use-modules (aiscm magick) (aiscm convolution) (aiscm tensor) (aiscm sequence) (aiscm element) (aiscm rgb) (aiscm int) (aiscm jit))
(define (sharpen img) (tensor (max 0 (min 255 (convolve img (arr (0 -1 0) (-1 5 -1) (0 -1 0)))))))
(write-image (to-type <ubytergb> (sharpen (read-image "star-ferry.jpg"))) "sharpen.jpg")
sharpen.jpg

sharpen.jpg

Edge detection

Convolutions can be used for edge detection.

Here is an implementation of the Roberts cross edge detector.

(use-modules (aiscm magick) (aiscm convolution) (aiscm tensor) (aiscm sequence) (aiscm image) (aiscm element) (aiscm int))
(define (to-gray img) (to-array (convert-image (to-image img) 'GRAY)))
(define (norm x y) (tensor (/ (+ (abs x) (abs y)) 2)))
(define (roberts-cross img) (/ (norm (convolve img (arr (+1 0) ( 0 -1))) (convolve img (arr ( 0 +1) (-1 0)))) 2))
(write-image (to-type <ubyte> (roberts-cross (to-gray (read-image "star-ferry.jpg")))) "roberts-cross.jpg")
roberts-cross.jpg

roberts-cross.jpg

Another popular edge detector is the Sobel operator.

(use-modules (aiscm magick) (aiscm convolution) (aiscm tensor) (aiscm sequence) (aiscm image) (aiscm element) (aiscm int))
(define (to-gray img) (to-array (convert-image (to-image img) 'GRAY)))
(define (norm x y) (tensor (/ (+ (abs x) (abs y)) 8)))
(define (sobel img) (norm (convolve img (arr (1 0 -1) (2 0 -2) ( 1 0 -1))) (convolve img (arr (1 2 1) (0 0 0) (-1 -2 -1)))))
(write-image (to-type <ubyte> (sobel (to-gray (read-image "star-ferry.jpg")))) "sobel.jpg")
sobel.jpg

sobel.jpg

Conway's Game of Life

Finally here is an implementation of Conway's Game of Life.

(use-modules (aiscm xorg) (aiscm convolution) (aiscm tensor) (aiscm bool) (aiscm int) (aiscm jit)
             (aiscm sequence) (aiscm operation) (aiscm element))
(define img (fill <bool> '(100 60) #f))
(set img 0 0 #f) (set img 1 0 #t) (set img 2 0 #f)
(set img 0 1 #f) (set img 1 1 #f) (set img 2 1 #t)
(set img 0 2 #t) (set img 1 2 #t) (set img 2 2 #t)
(set img 4 50 #t) (set img 5 50 #t) (set img 6 50 #t)
(set img 4 51 #f) (set img 5 51 #f) (set img 6 51 #t)
(set img 4 52 #f) (set img 5 52 #t) (set img 6 52 #f)
(set img 27 25 #t) (set img 28 25 #t) (set img 29 25 #t)
(show
  (lambda (dsp)
    (let [(neighbours (convolve (to-type <ubyte> img) (arr (1 1 1) (1 0 1) (1 1 1))))]
      (set! img (tensor (&& (ge neighbours (where img 2 3)) (le neighbours 3))) )
      (where img 255 0))))

Generated by Pandoc - 2017-07-01