Class: Utils::Image

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_pager/image.rb

Instance Method Summary collapse

Constructor Details

#initialize(ex_path) ⇒ Image

Returns a new instance of Image.



7
8
9
10
11
12
13
14
15
16
# File 'lib/ruby_pager/image.rb', line 7

def initialize(ex_path)
  @logger = Utils::ApplicationLogger.instance
  @image_path = ex_path
  @logger.info("Loading image")
  @img = Magick::ImageList.new(@image_path)
  @increment = 200
  @img_aux = Magick::Image.new(@img.columns+@increment,@img.rows){ self.background_color = "white" }
  @intensity_calculated = false
  @integral_calculated = false
end

Instance Method Details

#binarize!(method, *params) ⇒ Object



230
231
232
233
234
235
236
237
238
# File 'lib/ruby_pager/image.rb', line 230

def binarize!(method,*params)
  @logger.info("Performing #{method} binarization on image")
  calculate_intensity_matrix
  @intensity_matrix = send(method,@intensity_matrix,*params)
  @logger.info("IMAGE CHANGED!! Recalculating internal representation")
  @img=intensity_matrix_to_image(@intensity_matrix)
  calculate_integral_images
  @histogram = @intensity_matrix.to_normalized_histogram
end

#calculate_intensity_matrixObject



18
19
20
21
22
23
24
25
26
# File 'lib/ruby_pager/image.rb', line 18

def calculate_intensity_matrix
  unless @intensity_calculated
    @logger.info("Calculating intensity matrix")
    @intensity_matrix = obtain_image_intensity_matrix #obtains the gray channel of the image
    @logger.info("Calculating normalized intensity histogram")
    @histogram = @intensity_matrix.to_normalized_histogram
    @intensity_calculated=true
  end
end

#columnsObject



33
34
35
# File 'lib/ruby_pager/image.rb', line 33

def columns
  @img.columns
end

#detect_connected_regions(neighbourhood, output_file, intensity_matrix = @intensity_matrix) ⇒ Object



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/ruby_pager/image.rb', line 259

def detect_connected_regions(neighbourhood,output_file,intensity_matrix=@intensity_matrix)
  label_assignment_matrix = Matrix.build(intensity_matrix.row_size,intensity_matrix.column_size){0}
  labels_translation = Hash.new
  labels_translation[0]=0 #label of the empty regions
  @logger.info("Detecting connected regions")
  intensity_matrix.each_with_index do |val,x,y|
    
    next unless val.zero?        
    
    neighbour_labels = neighbour_labels_set(label_assignment_matrix,x,y,neighbourhood)
            
    if neighbour_labels.empty?
      new_label=labels_translation.keys.last+1
      labels_translation[new_label]=new_label
      label_assignment_matrix[x,y]=new_label
    else
      #we always assign the label with least number, so that level equivalence translation will be linear
      new_label=neighbour_labels.first
      label_assignment_matrix[x,y]=new_label
      neighbour_labels.each{|label| labels_translation[label]=new_label } if neighbour_labels.size > 1
    end
  end
  
  @logger.info("Translating region labels as per equivalence detected")
  labels_translation.each{|key,val|labels_translation[key]=labels_translation[val] if key != val}
  draw_connected_regions(extract_regions(label_assignment_matrix,labels_translation),output_file)
  
end

#displayObject



38
39
40
# File 'lib/ruby_pager/image.rb', line 38

def display
  @img.display {server_name = @image_path; delay=1}
end

#draw_binary_image(method, *params) ⇒ Object



245
246
247
248
249
# File 'lib/ruby_pager/image.rb', line 245

def draw_binary_image(method,*params)
  @logger.info("Performing #{method} binarization on image")
  bin_mat = send(method,@intensity_matrix,*params)
  draw_intensity_matrix(bin_mat)
end

#draw_connected_regions(region_list, output_file) ⇒ Object



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/ruby_pager/image.rb', line 318

def draw_connected_regions(region_list,output_file)
  @logger.info("Drawing regions")
  colors=["red","seagreen","royalblue","purple","sienna","steelblue","khaki","lightcoral","olive"]
  region_list.each_value do |region|
    gc = Magick::Draw.new 
    gc.stroke_width = 1
    gc.fill=colors.rotate![0]
    region.each do |point|       
      gc.point(point[0],point[1])  
    end
    gc.draw(@img)      
  end
  @img.display
  to_file(output_file,@img)
end

#draw_intensity_matrix(intensity_matrix = @intensity_matrix) ⇒ Object



240
241
242
243
# File 'lib/ruby_pager/image.rb', line 240

def draw_intensity_matrix(intensity_matrix=@intensity_matrix)
  @logger.info("Drawing intensity matrix")
  intensity_matrix_to_image(intensity_matrix).display
end

#extract_regions(label_assignment_matrix, label_translation) ⇒ Object



305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/ruby_pager/image.rb', line 305

def extract_regions(label_assignment_matrix,label_translation)
  @logger.info("Extracting regions to drawable format")
  regions= Hash.new{|h,key|h[key]=Array.new} #Array that will initialize an array for the key if not specified yet
  label_assignment_matrix.each_with_index do |val,x,y|
    unless label_translation[val].zero?
      region_target=label_translation[val]
      regions[region_target].push([y,x])
    end
  end
  
  return regions
end

#intensity_matrix_to_image(intensity_matrix = @intensity_matrix) ⇒ Object



111
112
113
114
# File 'lib/ruby_pager/image.rb', line 111

def intensity_matrix_to_image(intensity_matrix=@intensity_matrix)
  @logger.info("Transforiming intensity matrix to image")
  return Magick::Image.constitute(intensity_matrix.column_size, intensity_matrix.row_size,"I", intensity_matrix.to_elements)
end

#mean_of_region(from_x = @integral_image.row_size-1, from_y = @integral_image.column_size-1, region_height = @integral_image.row_size-1, region_width = @integral_image.column_size-1) ⇒ Object



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
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ruby_pager/image.rb', line 42

def mean_of_region(from_x=@integral_image.row_size-1,from_y=@integral_image.column_size-1,region_height=@integral_image.row_size-1,region_width=@integral_image.column_size-1)
  #if no parameters are given the input variables get assigned the default values indicated in the above specification and hence return the mean of the whole image
  #raise "Region size provided exceeds the image boundaries" if from_y - region_width < 0 or from_x - region_height < 0

=begin
  
  [1]-------[2] height + 1
   |         |
   |         |    basic formula is [4] - [2] - [3] + [1] but if [2] or [3] coincide with boundary size then 
   |         |    we do not have to delete the region beyond width or height ( as there is no region beyond)
   |         |    hence we do not have to add [1] to recover that corner section from being substracted twice
  [3]-------[4]
  width +1
=end      


  res = @integral_image[from_x,from_y]
  region_cuts = 0
  
  
  if from_y - region_width > 0
    res -= @integral_image[from_x,from_y-(region_width+1)]
    region_cuts+=1
  end
  
  if from_x - region_height > 0
    res -= @integral_image[from_x-(region_height+1),from_y]
    region_cuts+=1
  end
  
  if region_cuts == 2
    res += @integral_image[from_x-(region_height+1),from_y-(region_width+1)]
  end
  
  return res.to_f/(region_height*region_width).to_f
  
end

#neighbour_labels_set(label_assignment_matrix, x, y, neighbourhood) ⇒ Object



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/ruby_pager/image.rb', line 288

def neighbour_labels_set(label_assignment_matrix,x,y,neighbourhood)
  result = SortedSet.new
  
  result.add(label_assignment_matrix[x-1,y]) 
  result.add(label_assignment_matrix[x,y-1])
  
  if neighbourhood == 8
    result.add(label_assignment_matrix[x-1,y-1])
    result.add(label_assignment_matrix[x-1,y+1])         
  end
  
  result.delete(nil)
  result.delete(0)
  
  return result
end

#obtain_image_intensity_matrix(img = @img) ⇒ Object



107
108
109
# File 'lib/ruby_pager/image.rb', line 107

def obtain_image_intensity_matrix(img=@img)
  return Matrix.rows(img.export_pixels(0,0,img.columns,img.rows,"I").each_slice(img.columns).reduce([]) {|x,y| x<<y })
end

#rowsObject



29
30
31
# File 'lib/ruby_pager/image.rb', line 29

def rows
  @img.rows
end

#save_binary_image(path, method, *params) ⇒ Object



251
252
253
254
255
# File 'lib/ruby_pager/image.rb', line 251

def save_binary_image(path,method,*params)
  @logger.info("Performing #{method} binarization on image")
  bin_mat = send(method)
  to_file(path,intensity_matrix_to_image(bin_mat))
end

#standard_deviation_of_region(mean, from_x = @integral_image.row_size-1, from_y = @integral_image.column_size-1, region_height = @integral_image.row_size-1, region_width = @integral_image.column_size-1) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ruby_pager/image.rb', line 79

def standard_deviation_of_region(mean,from_x=@integral_image.row_size-1,from_y=@integral_image.column_size-1,region_height=@integral_image.row_size-1,region_width=@integral_image.column_size-1)
  #if no parameters are given the input variables get assigned the default values indicated in the above specification and hence return the deviation of the whole image
  #raise "Region size provided exceeds the image boundaries" if from_y - region_width < 0 or from_x - region_height < 0

  res = @sum_of_squares_intensity_matrix[from_x,from_y]
  region_cuts = 0

  if from_y - region_width > 0
    res -= @sum_of_squares_intensity_matrix[from_x,from_y-(region_width+1)]
    region_cuts+=1
  end

  if from_x - region_height > 0
    res -= @sum_of_squares_intensity_matrix[from_x-(region_height+1),from_y]
    region_cuts+=1
  end

  if region_cuts == 2
    res += @sum_of_squares_intensity_matrix[from_x-(region_height+1),from_y-(region_width+1)]
  end
  
  #region_width = region_width - from_y  if from_y - region_width < 0 
 # region_height = region_height - from_x if from_x - region_height < 0 
  
  return Math.sqrt(((res.to_f/(region_height*region_width).to_f)-mean**2).abs)

end

#to_file(path, img = @img) ⇒ Object



116
117
118
119
# File 'lib/ruby_pager/image.rb', line 116

def to_file(path,img=@img)
  @logger.info("Saving image to path: #{path}")
  img.write(path)
end