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, #mean, #memorise, #memory, #min, #normalise, #prod, #r=, #r_with_decompose, #range, #real=, #real_with_decompose, #reshape, #rgb?, rgb?, #roll, scalar, shape, #shift, #simplify, #size, #sobel, #stretch, #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.



224
225
226
227
228
# File 'lib/multiarray/components.rb', line 224

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

#demandNode, Object

Reevaluate computation

Returns:

See Also:



79
80
81
82
# File 'lib/multiarray/components.rb', line 79

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,



57
58
59
60
61
62
# File 'lib/multiarray/components.rb', line 57

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.



90
91
92
93
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
# File 'lib/multiarray/components.rb', line 90

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

#shapeObject



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

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:



211
212
213
214
215
216
217
# File 'lib/multiarray/components.rb', line 211

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.



187
188
189
190
# File 'lib/multiarray/components.rb', line 187

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



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

def typecode
  @dest.typecode
end

#variablesSet

Get variables contained in this term

Returns:

  • (Set)

    Returns list of variables.



197
198
199
200
# File 'lib/multiarray/components.rb', line 197

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