Class: Hornetseye::Components

Inherits:
Node show all
Defined in:
lib/multiarray/components.rb

Overview

Class for representing connected component analysis

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

#+@, #<=>, ===, #[], #[]=, #allocate, #b=, #b_with_decompose, basetype, #basetype, #between?, bool, byte, #check_shape, #clip, #coerce, coercion_bool, coercion_byte, coercion_maxint, #collect, compilable?, #components, cond, #conditional, #convolve, #decompose, define_binary_op, define_unary_op, descriptor, #diagonal, #dilate, dimension, #dimension, #downsample, #dup, #each, #empty?, #eq_with_multiarray, #erode, #fill!, #finalised?, #flip, float, float_scalar, floating, #fmod_with_float, #force, #g=, #g_with_decompose, #gauss_blur, #gauss_gradient, #get, #height, #histogram, #histogram_with_rgb, identity, #if, #if_else, #imag=, #imag_with_decompose, indgen, #inject, #inspect, #integral, #lut, #lut_with_rgb, #malloc, #mask, match, #matched?, #max, maxint, #memorise, #memory, #min, #normalise, #r=, #r_with_decompose, #range, #real=, #real_with_decompose, #reshape, #rgb?, rgb?, #roll, scalar, shape, #shift, #simplify, #size, #sobel, #stride, #strides, strip, subst, #sum, #swap_rgb_with_scalar, #table, #to_a, #to_s, to_s, #to_type, to_type, #to_type_with_identity, #to_type_with_rgb, #transpose, typecode, typecodes, #unmask, #unroll, variables, #warp, #width

Methods included from Field_::Match

#align, #fit

Methods included from FLOAT_::Match

#align, #fit

Methods included from OBJECT::Match

#align, #fit

Methods included from Hornetseye::COMPLEX_::Match

#align, #fit

Methods included from BOOL::Match

#fit

Methods included from RGB_::Match

#align, #fit

Methods included from INT_::Match

#fit

Constructor Details

#initialize(dest, source, default, zero, labels, rank, n) ⇒ Components

Constructor

Parameters:

  • dest (Node)

    Target array to write component labels to.

  • source (Node)

    Array to extract components from.

  • default (Node)

    Value of background pixel.

  • zero (Node)

    Zero is used to aid compilation.

  • labels (Node)

    Array to store label correspondences.

  • rank (Node)

    Array to store number of indirections for each label.

  • n (Node)

    Pointer to return number of components.



45
46
47
48
# File 'lib/multiarray/components.rb', line 45

def initialize( dest, source, default, zero, labels, rank, n )
  @dest, @source, @default, @zero, @labels, @rank, @n =
    dest, source, default, zero, labels, rank, n
end

Class Method Details

.finalised?Boolean

Check whether objects of this class are finalised computations

Returns:

  • (Boolean)

    Returns false.



30
31
32
# File 'lib/multiarray/components.rb', line 30

def finalised?
  false
end

Instance Method Details

#compilable?Set

Get variables contained in this term

Returns:

  • (Set)

    Returns list of variables.



228
229
230
231
232
# File 'lib/multiarray/components.rb', line 228

def compilable?
  [ @dest, @source, @default, @zero, @labels, @rank, @n ].all? do |value|
    value.compilable?
  end
end

#demandNode, Object

Reevaluate computation

Returns:

See Also:



83
84
85
86
# File 'lib/multiarray/components.rb', line 83

def demand
  knot [], []
  @dest
end

#descriptor(hash) ⇒ String

Get unique descriptor of this object

Parameters:

  • hash (Hash)

    Labels for any variables.

Returns:

  • (String)

    Descriptor of this object,



61
62
63
64
65
66
# File 'lib/multiarray/components.rb', line 61

def descriptor( hash )
  "Components(#{@dest.descriptor( hash )},#{@source.descriptor( hash )}," +
    "#{@default.descriptor( hash )},#{@zero.descriptor( hash )}," +
    "#{@labels.descriptor( hash )},#{@rank.descriptor( hash )}," +
    "#{@n.descriptor( hash )})"
end

#knot(args, comp) ⇒ Object

Recursive function to perform connected component labeling

Parameters:

  • args (Array<Proc>)

    Array with functions for locating neighbouring elements.

  • comp (Array<Proc>)

    Array with functions for locating neighbouring labels.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/multiarray/components.rb', line 94

def knot( args, comp )
  n = @n.simplify
  if dimension > 0
    subargs1, subargs2, subargs3 = [], [], []
    subcomp1, subcomp2, subcomp3 = [], [], []
    args.each do |arg|
      subargs1.push proc { |i| arg.element( i - 1 ).demand }
      subargs2.push proc { |i| arg.element( i     ).demand }
      subargs3.push proc { |i| arg.element( i + 1 ).demand }
    end
    comp.each do |c|
      subcomp1.push proc { |i| c.element( i - 1 ) }
      subcomp2.push proc { |i| c.element( i     ) }
      subcomp3.push proc { |i| c.element( i + 1 ) }
    end
    self.class.new( @dest.element( INT.new( 0 ) ),
                    @source.element( INT.new( 0 ) ).demand, @default, @zero,
                    @labels, @rank, n ).
      knot( ( subargs2 + subargs3 ).collect { |p| p.call INT.new( 0 ) },
            ( subcomp2 + subcomp3 ).collect { |p| p.call INT.new( 0 ) } )
    INT.new( 1 ).upto INT.new( @source.shape.last ) - 2 do |i|
      self.class.new( @dest.element( INT.new( i ) ),
                      @source.element( INT.new( i ) ).demand, @default, @zero,
                      @labels, @rank, n ).
        knot( ( subargs1 + subargs2 + subargs3 ).collect { |p| p.call INT.new( i ) } +
              [ @source.element( INT.new( i ) - 1 ) ],
              ( subcomp1 + subcomp2 + subcomp3 ).collect { |p| p.call INT.new( i ) } +
              [ @dest.element( INT.new( i ) - 1 ) ] )
    end
    i = @source.shape.last - 1
    self.class.new( @dest.element( INT.new( i ) ),
                    @source.element( INT.new( i ) ).demand, @default, @zero,
                    @labels, @rank, n ).
      knot( ( subargs1 + subargs2 ).collect { |p| p.call INT.new( i ) } +
            [ @source.element( INT.new( i ) - 1 ) ],
            ( subcomp1 + subcomp2 ).collect { |p| p.call INT.new( i ) } +
            [ @dest.element( INT.new( i ) - 1 ) ] )
  else
    @source.ne( @default ).if_else( proc do
      label = @zero.simplify
      args.zip( comp ).each do |arg,other|
        @source.eq( arg ).if do
          other = other.simplify
          proc { other.ne( @labels.element( other ).demand ) }.while do
            other.assign @labels.element( other ).demand
          end
          label.eq( @zero ).if_else( proc do
            label.assign other
          end, proc do
            label.ne( other ).if do
              ( @rank.element( label ).demand <= @rank.element( other ).demand ).if_else( proc do
                @labels[ other ] = label
                @rank.element( label ).demand.eq( @rank.element( other ).demand ).if do
                  @rank[ label ] = @rank.element( other ).demand + 1
                end
              end, proc do
                @labels[ label ] = other
                label.assign other
              end )
            end
          end )
        end
      end
      label.eq( @zero ).if do
        n.assign n + 1
        @labels[ n ] = n
        @rank[ n ] = 0
        label.assign n
      end
      @dest.store label
    end, proc do
      @dest.store INT.new( 0 )
    end )
  end
  if @n.is_a? Pointer_
    INT.new( 0 ).upto n do |i|
      l = UINT.new( i ).simplify
      proc { l.ne( @labels.element( l ).demand ) }.while do
        l.assign @labels.element( l ).demand
      end
      @labels[ INT.new( i ) ] = l
    end
    @n.store n
  else
    @n.assign n
  end
end

#sexp?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/multiarray/components.rb', line 50

def sexp?
  true
end

#shapeObject



72
73
74
# File 'lib/multiarray/components.rb', line 72

def shape
  @dest.shape
end

#stripArray<Array,Node>

Strip of all values

Split up into variables, values, and a term where all values have been replaced with variables.

values, and the term based on variables.

Returns:



215
216
217
218
219
220
221
# File 'lib/multiarray/components.rb', line 215

def strip
  stripped = [ @dest, @source, @default, @zero, @labels, @rank, @n ].
    collect { |value| value.strip }
  return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
    stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
    self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
end

#subst(hash) ⇒ Node

Substitute variables

Substitute the variables with the values given in the hash.

Parameters:

  • hash (Hash)

    Substitutions to apply.

Returns:

  • (Node)

    Term with substitutions applied.



191
192
193
194
# File 'lib/multiarray/components.rb', line 191

def subst( hash )
  self.class.new @dest.subst( hash ), @source.subst( hash ), @default.subst( hash ),
    @zero.subst( hash ), @labels.subst( hash ), @rank.subst( hash ), @n.subst( hash )
end

#typecodeObject



68
69
70
# File 'lib/multiarray/components.rb', line 68

def typecode
  @dest.typecode
end

#variablesSet

Get variables contained in this term

Returns:

  • (Set)

    Returns list of variables.



201
202
203
204
# File 'lib/multiarray/components.rb', line 201

def variables
  @dest.variables + @source.variables + @default.variables + @zero.variables +
    @labels.variables + @rank.variables + @n.variables
end