multiarray 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
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