Class: Contrek::Concurrent::Finder

Inherits:
Object
  • Object
show all
Includes:
Poolable
Defined in:
lib/contrek/finder/concurrent/finder.rb

Instance Attribute Summary collapse

Attributes included from Poolable

#number_of_threads

Instance Method Summary collapse

Methods included from Poolable

#enqueue!, #wait!

Constructor Details

#initialize(bitmap:, matcher:, options: {}, &block) ⇒ Finder

Supported options

  • number_of_threads: number of threads that can be used by the process. If set to 0, it works in single-thread mode. The process can take advantage of multiprocessing when computing the initial contours of the tiles into which the image is divided, and during the subsequent merging of tiles into pairs. Each merge is performed by any available thread as soon as two adjacent tiles have been computed. If set to nil, the process will use the maximum number of cpu available cores.

  • bitmap: PngBitmap containing the image.

  • matcher: specific Matcher used for pixel identification.

  • options: options include:

    - number_of_tiles: number of tiles into which the image is initially divided.
      It cannot exceed the image width, so the system works with tiles at least one pixel wide.
      Given the technique on which the process is based, using excessively narrow tiles is
      discouraged.
    


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/contrek/finder/concurrent/finder.rb', line 23

def initialize(bitmap:, matcher:, options: {}, &block)
  @initialize_time = Benchmark.measure do
    @block = block
    @tiles = Queue.new
    @bitmap = bitmap
    @options = options
    @clusters = []
    @maximum_width = bitmap.w
    @number_of_tiles = options[:number_of_tiles] || (raise "number_of_tiles params is needed!")

    cw = @maximum_width.to_f / @number_of_tiles
    raise "One pixel tile width minimum!" if cw < 1.0
    x = 0
    current_versus = options[:versus]
    raise "Define versus!" if current_versus.nil?

    @number_of_tiles.times do |tile_index|
      tile_end_x = (cw * (tile_index + 1)).to_i

      enqueue!(tile_index: tile_index,
        tile_start_x: x,
        tile_end_x: tile_end_x) do |payload|
        finder = ClippedPolygonFinder.new(
          bitmap: bitmap,
          matcher: matcher,
          options: {versus: current_versus},
          start_x: payload[:tile_start_x],
          end_x: payload[:tile_end_x]
        )
        tile = Tile.new(
          finder: self,
          start_x: payload[:tile_start_x],
          end_x: payload[:tile_end_x],
          name: payload[:tile_index].to_s
        )
        tile.initial_process!(finder)
        @tiles << tile
      end

      x = tile_end_x - 1
    end
    @tile = process_tiles!(bitmap)
  end.real
end

Instance Attribute Details

#maximum_widthObject (readonly)

Returns the value of attribute maximum_width.



6
7
8
# File 'lib/contrek/finder/concurrent/finder.rb', line 6

def maximum_width
  @maximum_width
end

Instance Method Details

#process_info(bitmap = nil) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/contrek/finder/concurrent/finder.rb', line 68

def process_info(bitmap = nil)
  raw_polygons = @tile.to_raw_polygons

  compress_time = Benchmark.measure do
    if @options.has_key?(:compress)
      FakeCluster.new(raw_polygons, @options).compress_coords
    end
  end.real

  {polygons: raw_polygons,
   benchmarks: {
     total: ((@initialize_time + compress_time) * 1000).round(3),
     init: (@initialize_time * 1000).round(3),
     outer: (@tile.benchmarks[:outer] * 1000).round(3),
     inner: (@tile.benchmarks[:inner] * 1000).round(3),
     compress: ((compress_time * 1000).round(3) if @options.has_key?(:compress))
   }.compact}
end