HornetsEye

(Difference between revisions)
Jump to: navigation, search
m (HornetsEye-0.10)
(Adding PCA-object-recognition example)
Line 6: Line 6:
 
* '''minimalistic''': The library is focused on real-time computer vision. Existing libraries are being made used of.
 
* '''minimalistic''': The library is focused on real-time computer vision. Existing libraries are being made used of.
 
* '''consistent''':: A non-redundant set of data-types is used. Also the library tries to stay consistent with existing libraries.
 
* '''consistent''':: A non-redundant set of data-types is used. Also the library tries to stay consistent with existing libraries.
 +
 +
=Example=
 +
The example program performs two-dimensional object recognition with three degrees of freedom. This is a customised algorithm which only works on images showing a single object which can be detected using colour-segmentation. In a controlled environment however this algorithm can be very useful as it is easy to implement. It is also possible to optimise it for real-time applications.
 +
 +
<pre>
 +
#!/usr/bin/ruby
 +
# Detect location and rotation of an object using color-segmentation and
 +
# principal component analysis on resulting binary image.
 +
require 'hornetseye'
 +
require 'matrix'
 +
raise "Syntax: test4.rb [media resource location]" if ARGV.size != 1
 +
input = Hornetseye::XineInput.new( ARGV[0] )
 +
# Object is black.
 +
dominant = 0
 +
frame = 0
 +
old_eigenvector = Vector[ 1, 0 ]
 +
while input.status?
 +
  # Read image.
 +
  img = input.read_grey
 +
  # Detect center and rotation of object using principal component analysis.
 +
  # Assuming object has a principal axis (otherwise this approach fails).
 +
  c = 0
 +
  n = 0
 +
  sum = [ 0, 0 ]
 +
  squares = [ [ 0, 0 ], [ 0, 0 ] ]
 +
  img.each do |v|
 +
    if v & 0xE0 == dominant
 +
      x = c % img.shape[1]
 +
      y = c / img.shape[1]
 +
      sum[ 0 ] += x
 +
      sum[ 1 ] += y
 +
      squares[ 0 ][ 0 ] += x * x
 +
      squares[ 0 ][ 1 ] += x * y
 +
      squares[ 1 ][ 0 ] += y * x
 +
      squares[ 1 ][ 1 ] += y * y
 +
      n += 1
 +
    end
 +
    c += 1
 +
  end
 +
  sum = Vector[*sum]
 +
  squares = Matrix[*squares]
 +
  center = sum * ( 1.0 / n )
 +
  covariance = ( n * squares -
 +
                sum.covector.transpose*sum.covector ) / ( n ** 2 ).to_f
 +
  # "abs" is needed to deal with numerical errors.
 +
  discriminant = ( covariance.trace ** 2 - 4 * covariance.determinant ).abs
 +
  # Take smallest eigenvalue. Eigenvalues are "0.5 * ( tr +- dissqrt)"
 +
  lambda1 = 0.5 * ( covariance.trace + Math.sqrt( discriminant ) )
 +
  eigenspace = covariance - lambda1 * Matrix.unit( 2 )
 +
  # Compute eigenvector by projecting basis-vectors.
 +
  projected1 = eigenspace * Vector[1,0]
 +
  projected2 = eigenspace * Vector[0,1]
 +
  if projected1.r >= projected2.r
 +
    projected = projected1 * ( 1.0 / projected1.r )
 +
  else
 +
    projected = projected2 * ( 1.0 / projected2.r )
 +
  end
 +
  eigenvector = Vector[ -projected[ 1 ], projected[ 0 ] ]
 +
  # Resolv ambiguity by comparing with previous eigenvector.
 +
  if old_eigenvector.inner_product( eigenvector ) < 0
 +
    eigenvector = Vector[ projected[ 1 ], -projected[ 0 ] ]
 +
  end
 +
  gc=Magick::Draw.new
 +
  pointer=center+eigenvector*30
 +
  gc.fill_opacity(0)
 +
  gc.stroke('red').stroke_width(3)
 +
  gc.circle(center[0],center[1],pointer[0],pointer[1])
 +
  gc.line(center[0],center[1],pointer[0],pointer[1])
 +
  result=img.to_magick
 +
  gc.draw(result)
 +
  result.to_hornetseye.save( ( "%08d" % frame ) + ".jpg" )
 +
  frame += 1
 +
end
 +
</pre>
 +
{|align="center"
 +
|-
 +
|[[Image:Polygon134.jpg|thumb|320px|135th input frame acquired from the [http://vision.eng.shu.ac.uk/jan/polygon.avi test-video] showing a polygon]]||[[Image:Polyresult134.jpg|thumb|320px|Resulting image indicating position and orientation of the object's principal axis]]
 +
|-
 +
|}
 +
 +
Thanks to [http://www.mach.uni-karlsruhe.de/seite10513.php  Prof. Dr.-Ing. Christoph Stiller] for pointing out this algorithm.
  
 
=Downloads=
 
=Downloads=
 
==HornetsEye-0.10==
 
==HornetsEye-0.10==
[[Image:Hornetseye.jpg|48px]] '''Download [http://rubyforge.org/frs/?group_id=2714 HornetsEye-0.10] released on February 1st 2007'''
+
* [[Image:Hornetseye.jpg|48px]] '''Download [http://rubyforge.org/frs/?group_id=2714 HornetsEye-0.10] released on February 1st 2007'''
 +
* [http://vision.eng.shu.ac.uk/jan/polygon.avi test-video with polygon]
  
 
===Release Notes===
 
===Release Notes===

Revision as of 19:28, 5 March 2007

File:Hornetseye.jpg
Logo of Hornetseye-library showing a hornet

Contents

Introduction

HornetsEye is a Ruby-extension for real-time computer vision under GNU/Linux offering interfaces to do image- and video-I/O with RMagick, Xine, firewire digital camera (DC1394) and video for Linux (V4L).

HornetsEye also is an attempt to use the Mimas library and create a minimalistic and consistent real-time computer vision library.

  • minimalistic: The library is focused on real-time computer vision. Existing libraries are being made used of.
  • consistent:: A non-redundant set of data-types is used. Also the library tries to stay consistent with existing libraries.

Example

The example program performs two-dimensional object recognition with three degrees of freedom. This is a customised algorithm which only works on images showing a single object which can be detected using colour-segmentation. In a controlled environment however this algorithm can be very useful as it is easy to implement. It is also possible to optimise it for real-time applications.

#!/usr/bin/ruby
# Detect location and rotation of an object using color-segmentation and
# principal component analysis on resulting binary image.
require 'hornetseye'
require 'matrix'
raise "Syntax: test4.rb [media resource location]" if ARGV.size != 1
input = Hornetseye::XineInput.new( ARGV[0] )
# Object is black.
dominant = 0
frame = 0
old_eigenvector = Vector[ 1, 0 ]
while input.status?
  # Read image.
  img = input.read_grey
  # Detect center and rotation of object using principal component analysis.
  # Assuming object has a principal axis (otherwise this approach fails).
  c = 0
  n = 0
  sum = [ 0, 0 ]
  squares = [ [ 0, 0 ], [ 0, 0 ] ]
  img.each do |v|
    if v & 0xE0 == dominant
      x = c % img.shape[1]
      y = c / img.shape[1]
      sum[ 0 ] += x
      sum[ 1 ] += y
      squares[ 0 ][ 0 ] += x * x
      squares[ 0 ][ 1 ] += x * y
      squares[ 1 ][ 0 ] += y * x
      squares[ 1 ][ 1 ] += y * y
      n += 1
    end
    c += 1
  end
  sum = Vector[*sum]
  squares = Matrix[*squares]
  center = sum * ( 1.0 / n )
  covariance = ( n * squares -
                sum.covector.transpose*sum.covector ) / ( n ** 2 ).to_f
  # "abs" is needed to deal with numerical errors.
  discriminant = ( covariance.trace ** 2 - 4 * covariance.determinant ).abs
  # Take smallest eigenvalue. Eigenvalues are "0.5 * ( tr +- dissqrt)" 
  lambda1 = 0.5 * ( covariance.trace + Math.sqrt( discriminant ) )
  eigenspace = covariance - lambda1 * Matrix.unit( 2 )
  # Compute eigenvector by projecting basis-vectors.
  projected1 = eigenspace * Vector[1,0]
  projected2 = eigenspace * Vector[0,1]
  if projected1.r >= projected2.r
    projected = projected1 * ( 1.0 / projected1.r )
  else
    projected = projected2 * ( 1.0 / projected2.r )
  end
  eigenvector = Vector[ -projected[ 1 ], projected[ 0 ] ]
  # Resolv ambiguity by comparing with previous eigenvector.
  if old_eigenvector.inner_product( eigenvector ) < 0
    eigenvector = Vector[ projected[ 1 ], -projected[ 0 ] ]
  end
  gc=Magick::Draw.new
  pointer=center+eigenvector*30
  gc.fill_opacity(0)
  gc.stroke('red').stroke_width(3)
  gc.circle(center[0],center[1],pointer[0],pointer[1])
  gc.line(center[0],center[1],pointer[0],pointer[1])
  result=img.to_magick
  gc.draw(result)
  result.to_hornetseye.save( ( "%08d" % frame ) + ".jpg" )
  frame += 1
end
File:Polygon134.jpg
135th input frame acquired from the test-video showing a polygon
File:Polyresult134.jpg
Resulting image indicating position and orientation of the object's principal axis

Thanks to Prof. Dr.-Ing. Christoph Stiller for pointing out this algorithm.

Downloads

HornetsEye-0.10

Release Notes

See http://www.wedesoft.demon.co.uk/hornetseye-api/ for installation instructions.

Change log

  • Made display method accept more element-types.
  • Normalisation also works on blank image.

Older releases

See Hornetseye page at Rubyforge for older releases.

See Also

External Links

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox