multiarray 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
6
6
  require 'rbconfig'
7
7
 
8
8
  PKG_NAME = 'multiarray'
9
- PKG_VERSION = '0.18.1'
9
+ PKG_VERSION = '0.19.0'
10
10
  RB_FILES = FileList[ 'lib/**/*.rb' ]
11
11
  TC_FILES = FileList[ 'test/tc_*.rb' ]
12
12
  TS_FILES = FileList[ 'test/ts_*.rb' ]
data/lib/multiarray.rb CHANGED
@@ -585,6 +585,72 @@ end
585
585
  # The +Array+ class is extended with a few methods
586
586
  class Array
587
587
 
588
+ class << self
589
+
590
+ # Compute Gauss blur filter
591
+ #
592
+ # Compute a filter for approximating a Gaussian blur. The size of the
593
+ # filter is determined by the given error bound.
594
+ #
595
+ # @param [Float] sigma Spread of blur filter.
596
+ # @param [Float] max_error Upper bound for filter error.
597
+ #
598
+ # @return [Array] An array with the filter elements.
599
+ def gauss_blur_filter( sigma, max_error = 1.0 / 0x100 )
600
+ def erf( x, sigma )
601
+ 0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
602
+ end
603
+ raise 'Sigma must be greater than zero.' if sigma <= 0
604
+ # Integral of Gauss-bell from -0.5 to +0.5.
605
+ integral = erf( +0.5, sigma ) - erf( -0.5, sigma )
606
+ retVal = [ integral ]
607
+ while 1.0 - integral > max_error
608
+ # Integral of Gauss-bell from -size2 to +size2.
609
+ size2 = 0.5 * ( retVal.size + 2 )
610
+ nIntegral = erf( +size2, sigma ) - erf( -size2, sigma )
611
+ value = 0.5 * ( nIntegral - integral )
612
+ retVal.unshift( value )
613
+ retVal.push( value )
614
+ integral = nIntegral
615
+ end
616
+ # Normalise result.
617
+ retVal.collect { |element| element / integral }
618
+ end
619
+
620
+ # Compute Gauss gradient filter
621
+ #
622
+ # Compute a filter for approximating a Gaussian gradient. The size of the
623
+ # filter is determined by the given error bound.
624
+ #
625
+ # @param [Float] sigma Spread of blur filter.
626
+ # @param [Float] max_error Upper bound for filter error.
627
+ #
628
+ # @return [Array] An array with the filter elements.
629
+ def gauss_gradient_filter( sigma, max_error = 1.0 / 0x100 )
630
+ def gauss( x, sigma )
631
+ 1.0 / ( Math.sqrt( 2.0 * Math::PI ) * sigma.abs ) *
632
+ Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
633
+ end
634
+ raise 'Sigma must be greater than zero.' if sigma <= 0
635
+ # Integral of Gauss-gradient from -0.5 to +0.5.
636
+ retVal = [ gauss( +0.5, sigma ) - gauss( -0.5, sigma ) ]
637
+ # Absolute integral of Gauss-gradient from 0.5 to infinity.
638
+ integral = gauss( 0.5, sigma )
639
+ sumX = 0
640
+ while 2.0 * integral > max_error
641
+ size2 = 0.5 * ( retVal.size + 2 )
642
+ nIntegral = gauss( size2, sigma )
643
+ value = integral - nIntegral
644
+ retVal.unshift( -value )
645
+ retVal.push( +value )
646
+ sumX += value * ( retVal.size - 1 )
647
+ integral = nIntegral
648
+ end
649
+ retVal.collect { |element| element / sumX }
650
+ end
651
+
652
+ end
653
+
588
654
  # Element-wise operation based on element and its index
589
655
  #
590
656
  # Same as +Array#collect+ but with index.
@@ -74,7 +74,7 @@ module Hornetseye
74
74
  # shape of the array is determined. Finally the elements are coopied to the
75
75
  # resulting array.
76
76
  #
77
- # @param [Array<Object>] *args
77
+ # @param [Array<Object>] *args The array elements.
78
78
  #
79
79
  # @return [Node] Uniform multi-dimensional array.
80
80
  def []( *args )
@@ -82,6 +82,38 @@ module Hornetseye
82
82
  target[ *args ]
83
83
  end
84
84
 
85
+ # Compute Laplacian of Gaussian filter
86
+ #
87
+ # @param [Float] sigma Spread of filter.
88
+ # @param [Integer] size Size of filter (*e.g.* 9 for 9x9 filter)
89
+ #
90
+ # @return[Node] The filter.
91
+ def laplacian_of_gaussian( sigma = 1.4, size = 9 )
92
+ def erf( x, sigma )
93
+ 0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
94
+ end
95
+ def gauss_gradient( x, sigma )
96
+ -x / ( Math.sqrt( 2.0 * Math::PI * sigma.abs**5 ) ) *
97
+ Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
98
+ end
99
+ retval = new DFLOAT, size, size
100
+ sum = 0
101
+ for y in 0 .. size - 1
102
+ y0 = y - 0.5 * size
103
+ y1 = y0 + 1
104
+ y_grad_diff = gauss_gradient( y1, sigma ) - gauss_gradient( y0, sigma )
105
+ y_erf_diff = erf( y1, sigma ) - erf( y0, sigma )
106
+ for x in 0..size-1
107
+ x0 = x - 0.5 * size
108
+ x1 = x0 + 1
109
+ x_grad_diff = gauss_gradient( x1, sigma ) - gauss_gradient( x0, sigma )
110
+ x_erf_diff = erf( x1, sigma ) - erf( x0, sigma )
111
+ retval[ y, x ] = y_grad_diff * x_erf_diff + y_erf_diff * x_grad_diff
112
+ end
113
+ end
114
+ retval
115
+ end
116
+
85
117
  end
86
118
 
87
119
  end
@@ -329,6 +329,14 @@ module Hornetseye
329
329
  end
330
330
  end
331
331
 
332
+ def each( &action )
333
+ if dimension > 0
334
+ shape.last.times { |i| element( INT.new( i ) ).each &action }
335
+ else
336
+ action.call demand.get
337
+ end
338
+ end
339
+
332
340
  # Equality operator
333
341
  #
334
342
  # @return [Boolean] Returns result of comparison.
@@ -402,7 +410,7 @@ module Hornetseye
402
410
  if current.last != current.first
403
411
  factor =
404
412
  ( range.last - range.first ).to_f / ( current.last - current.first )
405
- self * factor + ( range.first - current.first * factor )
413
+ collect { |x| x * factor + ( range.first - current.first * factor ) }
406
414
  else
407
415
  self + ( range.first - current.first )
408
416
  end
@@ -418,7 +426,7 @@ module Hornetseye
418
426
  raise "Clipping does not support ranges with end value " +
419
427
  "excluded (such as #{range})"
420
428
  end
421
- major( range.begin ).minor range.end
429
+ collect { |x| x.major( range.begin ).minor range.end }
422
430
  end
423
431
 
424
432
  # Fill array with a value
@@ -511,6 +519,48 @@ module Hornetseye
511
519
  array.product( filter ).diagonal { |s,x| s + x }
512
520
  end
513
521
 
522
+ # Create spread array similar to product array
523
+ #
524
+ # Used internally to implement erosion and dilation.
525
+ #
526
+ # @param [Integer] n Size of spread.
527
+ #
528
+ # @return [Node] Result of operation.
529
+ #
530
+ # @see #erode
531
+ # @see #dilate
532
+ #
533
+ # @private
534
+ def spread( n = 3 )
535
+ if dimension > 0
536
+ Hornetseye::lazy( n, shape.last ) { |i,j| self[j].spread n }
537
+ else
538
+ self
539
+ end
540
+ end
541
+
542
+ # Erosion
543
+ #
544
+ # The erosion operation works on boolean as well as scalar values.
545
+ #
546
+ # @param [Integer] n Size of erosion operator.
547
+ #
548
+ # @return [Node] Result of operation.
549
+ def erode( n = 3 )
550
+ spread( n ).diagonal { |m,x| m.minor x }
551
+ end
552
+
553
+ # Dilation
554
+ #
555
+ # The dilation operation works on boolean as well as scalar values.
556
+ #
557
+ # @param [Integer] n Size of dilation operator.
558
+ #
559
+ # @return [Node] Result of operation.
560
+ def dilate( n = 3 )
561
+ spread( n ).diagonal { |m,x| m.major x }
562
+ end
563
+
514
564
  # Sobel operator
515
565
  #
516
566
  # @param [Integer] direction Orientation of Sobel filter.
@@ -524,6 +574,42 @@ module Hornetseye
524
574
  end.force
525
575
  end
526
576
 
577
+ # Gaussian blur
578
+ #
579
+ # @param [Float] sigma Spread of Gauss bell.
580
+ # @param [Float] max_error Error of approximated filter.
581
+ #
582
+ # @return [Node] Result of filter operation.
583
+ def gauss_blur( sigma, max_error = 1.0 / 0x100 )
584
+ filter_type = DFLOAT.align typecode
585
+ filter = Sequence[ *Array.gauss_blur_filter( sigma, max_error / dimension ) ].
586
+ to_type filter_type
587
+ ( dimension - 1 ).downto( 0 ).inject self do |retval,i|
588
+ retval.convolve filter
589
+ end
590
+ end
591
+
592
+ # Gauss gradient
593
+ #
594
+ # @param [Float] sigma Spread of Gauss gradient.
595
+ # @param [Integer] direction Orientation of Gauss gradient.
596
+ # @param [Float] max_error Error of approximated filter.
597
+ #
598
+ # @return [Node] Result of filter operation.
599
+ def gauss_gradient( sigma, direction, max_error = 1.0 / 0x100 )
600
+ filter_type = DFLOAT.align typecode
601
+ gradient =
602
+ Sequence[ *Array.gauss_gradient_filter( sigma, max_error / dimension ) ].
603
+ to_type filter_type
604
+ blur =
605
+ Sequence[ *Array.gauss_blur_filter( sigma, max_error / dimension ) ].
606
+ to_type filter_type
607
+ ( dimension - 1 ).downto( 0 ).inject self do |retval,i|
608
+ filter = i == direction ? gradient : blur
609
+ retval.convolve filter
610
+ end.force
611
+ end
612
+
527
613
  # Compute histogram of this array
528
614
  #
529
615
  # @overload histogram( *ret_shape, options = {} )
@@ -586,7 +672,7 @@ module Hornetseye
586
672
  inject { |a,b| a.and b }
587
673
  end.conditional Lut.new( *( field + [ self ] ) ), options[ :default ]
588
674
  else
589
- field.lut self
675
+ field.lut self, :safe => false
590
676
  end
591
677
  end
592
678
 
@@ -371,6 +371,12 @@ class TC_MultiArray < Test::Unit::TestCase
371
371
  assert_equal M[ [ 6 ] ], M[ [ C( 1, 2, 3 ) ] ].collect { |x| x.r + x.g + x.b }
372
372
  end
373
373
 
374
+ def test_each
375
+ a = []
376
+ M[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].each { |x| a << x }
377
+ assert_equal [ 1, 2, 3, 4, 5, 6 ], a
378
+ end
379
+
374
380
  def test_sum
375
381
  m = M[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
376
382
  assert_equal 21, sum { |i,j| m[ i, j ] }
@@ -432,6 +438,16 @@ class TC_MultiArray < Test::Unit::TestCase
432
438
  assert_raise( RuntimeError ) { S[ 1, 2, 3 ].convolve f }
433
439
  end
434
440
 
441
+ def test_erode
442
+ assert_equal [ [ 0, 0, 0 ], [ 0, -1, -1 ], [ 0, -1, -1 ] ],
443
+ M[ [ 1, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, -1 ] ].erode.to_a
444
+ end
445
+
446
+ def test_dilate
447
+ assert_equal [ [ 1, 1, 0 ], [ 1, 1, 0 ], [ 0, 0, 0 ] ],
448
+ M[ [ 1, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, -1 ] ].dilate.to_a
449
+ end
450
+
435
451
  def test_sobel
436
452
  m = M[ [ 0, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 0 ] ]
437
453
  assert_equal [ [ -1, 0, 1, 0 ], [ -2, 0, 2, 0 ], [ -1, 0, 1, 0 ] ],
data/test/tc_sequence.rb CHANGED
@@ -300,6 +300,12 @@ class TC_Sequence < Test::Unit::TestCase
300
300
  assert_equal S[ 6 ], S[ C( 1, 2, 3 ) ].collect { |x| x.r + x.g + x.b }
301
301
  end
302
302
 
303
+ def test_each
304
+ a = []
305
+ S[ 1, 2, 3 ].each { |x| a << x }
306
+ assert_equal [ 1, 2, 3 ], a
307
+ end
308
+
303
309
  def test_sum
304
310
  [ S( O, 3 ), S( I, 3 ) ].each do |t|
305
311
  assert_equal 6, t[ 1, 2, 3 ].sum
@@ -366,6 +372,22 @@ class TC_Sequence < Test::Unit::TestCase
366
372
  convolve( S[ C( 1, 0, 0 ), C( 0, 1, 0 ), C( 0, 0, 1 ) ] )
367
373
  end
368
374
 
375
+ def test_erode
376
+ [ O, I ].each do |t|
377
+ assert_equal [ 1, 1, 1, 2, 2, 2 ], S( t, 6 )[ 1, 1, 2, 3, 2, 2 ].erode.to_a
378
+ end
379
+ assert_equal S[ false, false, true, false, false ],
380
+ S[ false, true, true, true, false ].erode
381
+ end
382
+
383
+ def test_dilate
384
+ [ O, I ].each do |t|
385
+ assert_equal [ 1, 2, 3, 3, 3, 2 ], S( t, 6 )[ 1, 1, 2, 3, 2, 2 ].dilate.to_a
386
+ end
387
+ assert_equal S[ false, true, true, true, false ],
388
+ S[ false, false, true, false, false ].dilate
389
+ end
390
+
369
391
  def test_sobel
370
392
  assert_equal [ 0, -1, 0, 1, 0 ], S[ 0, 0, 1, 0, 0 ].sobel( 0 ).to_a
371
393
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 18
8
- - 1
9
- version: 0.18.1
7
+ - 19
8
+ - 0
9
+ version: 0.19.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jan Wedekind
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-12 00:00:00 +00:00
17
+ date: 2011-01-25 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -57,52 +57,52 @@ files:
57
57
  - README.md
58
58
  - COPYING
59
59
  - .document
60
- - lib/multiarray/object.rb
61
- - lib/multiarray/operations.rb
62
- - lib/multiarray/variable.rb
63
- - lib/multiarray/gcctype.rb
64
60
  - lib/multiarray/bool.rb
65
- - lib/multiarray/element.rb
66
- - lib/multiarray/gcccache.rb
67
- - lib/multiarray/int.rb
68
- - lib/multiarray/gccfunction.rb
69
- - lib/multiarray/shortcuts.rb
70
- - lib/multiarray/float.rb
71
- - lib/multiarray/diagonal.rb
72
- - lib/multiarray/inject.rb
73
- - lib/multiarray/list.rb
74
- - lib/multiarray/pointer.rb
75
- - lib/multiarray/lambda.rb
76
- - lib/multiarray/sequence.rb
77
- - lib/multiarray/methods.rb
78
- - lib/multiarray/integral.rb
79
61
  - lib/multiarray/multiarray.rb
80
- - lib/multiarray/unmask.rb
81
62
  - lib/multiarray/node.rb
82
- - lib/multiarray/histogram.rb
83
- - lib/multiarray/mask.rb
84
- - lib/multiarray/malloc.rb
85
- - lib/multiarray/index.rb
63
+ - lib/multiarray/gccvalue.rb
86
64
  - lib/multiarray/rgb.rb
65
+ - lib/multiarray/object.rb
87
66
  - lib/multiarray/gcccontext.rb
88
- - lib/multiarray/composite.rb
89
- - lib/multiarray/store.rb
67
+ - lib/multiarray/unmask.rb
90
68
  - lib/multiarray/elementwise.rb
69
+ - lib/multiarray/diagonal.rb
70
+ - lib/multiarray/index.rb
71
+ - lib/multiarray/variable.rb
72
+ - lib/multiarray/lambda.rb
73
+ - lib/multiarray/integral.rb
74
+ - lib/multiarray/pointer.rb
75
+ - lib/multiarray/element.rb
76
+ - lib/multiarray/composite.rb
91
77
  - lib/multiarray/lookup.rb
92
- - lib/multiarray/gccvalue.rb
78
+ - lib/multiarray/sequence.rb
79
+ - lib/multiarray/gcctype.rb
80
+ - lib/multiarray/shortcuts.rb
93
81
  - lib/multiarray/complex.rb
94
- - lib/multiarray/random.rb
82
+ - lib/multiarray/mask.rb
83
+ - lib/multiarray/malloc.rb
95
84
  - lib/multiarray/lut.rb
85
+ - lib/multiarray/int.rb
86
+ - lib/multiarray/gcccache.rb
87
+ - lib/multiarray/inject.rb
88
+ - lib/multiarray/list.rb
89
+ - lib/multiarray/gccfunction.rb
90
+ - lib/multiarray/histogram.rb
91
+ - lib/multiarray/float.rb
92
+ - lib/multiarray/random.rb
93
+ - lib/multiarray/operations.rb
94
+ - lib/multiarray/store.rb
95
+ - lib/multiarray/methods.rb
96
96
  - lib/multiarray.rb
97
97
  - test/ts_multiarray.rb
98
+ - test/tc_int.rb
99
+ - test/tc_object.rb
98
100
  - test/tc_float.rb
99
- - test/tc_sequence.rb
100
- - test/tc_rgb.rb
101
+ - test/tc_lazy.rb
101
102
  - test/tc_multiarray.rb
102
103
  - test/tc_bool.rb
103
- - test/tc_object.rb
104
- - test/tc_int.rb
105
- - test/tc_lazy.rb
104
+ - test/tc_rgb.rb
105
+ - test/tc_sequence.rb
106
106
  has_rdoc: yard
107
107
  homepage: http://wedesoft.github.com/multiarray/
108
108
  licenses: []
@@ -136,11 +136,11 @@ signing_key:
136
136
  specification_version: 3
137
137
  summary: Multi-dimensional and uniform Ruby arrays
138
138
  test_files:
139
+ - test/tc_int.rb
140
+ - test/tc_object.rb
139
141
  - test/tc_float.rb
140
- - test/tc_sequence.rb
141
- - test/tc_rgb.rb
142
+ - test/tc_lazy.rb
142
143
  - test/tc_multiarray.rb
143
144
  - test/tc_bool.rb
144
- - test/tc_object.rb
145
- - test/tc_int.rb
146
- - test/tc_lazy.rb
145
+ - test/tc_rgb.rb
146
+ - test/tc_sequence.rb