Class: Panomosity::Pair
- Inherits:
-
Object
- Object
- Panomosity::Pair
- Extended by:
- Utils
- Includes:
- Utils
- Defined in:
- lib/panomosity/pair.rb
Class Attribute Summary collapse
-
.logger ⇒ Object
Returns the value of attribute logger.
-
.panorama ⇒ Object
Returns the value of attribute panorama.
Instance Attribute Summary collapse
-
#control_points ⇒ Object
Returns the value of attribute control_points.
-
#generalized_neighborhoods ⇒ Object
Returns the value of attribute generalized_neighborhoods.
-
#neighborhoods ⇒ Object
Returns the value of attribute neighborhoods.
-
#pair ⇒ Object
Returns the value of attribute pair.
-
#similar_neighborhoods ⇒ Object
Returns the value of attribute similar_neighborhoods.
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
- .all ⇒ Object
- .calculate_neighborhood_groups ⇒ Object
- .calculate_neighborhoods(panorama, distance: 30) ⇒ Object
- .create_pairs_from_panorama(panorama) ⇒ Object
- .horizontal ⇒ Object
- .info ⇒ Object
- .log_detailed_neighborhood_info(name: :horizontal, pairs: []) ⇒ Object
- .select_control_points_with_regional_distance_similarities ⇒ Object
- .unconnected ⇒ Object
- .vertical ⇒ Object
- .without_enough_control_points(ignore_connected: false) ⇒ Object
Instance Method Summary collapse
- #==(other) ⇒ Object
- #attributes ⇒ Object
- #average_distance ⇒ Object
- #best_neighborhood ⇒ Object
- #calculate_neighborhoods(distance: 30) ⇒ Object
- #connected? ⇒ Boolean
- #control_points_of_best_neighborhood ⇒ Object
- #first_image ⇒ Object
- #good_control_points_to_keep(count: 3) ⇒ Object
-
#good_neighborhoods_within_std(count: 3) ⇒ Object
gets all control points for neighborhoods with a good std of distance.
- #horizontal? ⇒ Boolean
- #info ⇒ Object
-
#initialize(pair, control_points: [], type: nil) ⇒ Pair
constructor
A new instance of Pair.
- #last_image ⇒ Object
- #select_control_points_with_regional_distance_similarities ⇒ Object
-
#similar_control_points ⇒ Object
Distance neighborhoods.
- #to_s ⇒ Object
- #unconnected? ⇒ Boolean
- #vertical? ⇒ Boolean
Methods included from Utils
calculate_average, calculate_average_and_std, remove_outliers
Constructor Details
#initialize(pair, control_points: [], type: nil) ⇒ Pair
Returns a new instance of Pair.
156 157 158 159 160 161 162 163 |
# File 'lib/panomosity/pair.rb', line 156 def initialize(pair, control_points: [], type: nil) @pair = pair @control_points = control_points @neighborhoods = [] @generalized_neighborhoods = [] @similar_neighborhoods = [] @type = type end |
Class Attribute Details
.logger ⇒ Object
Returns the value of attribute logger.
11 12 13 |
# File 'lib/panomosity/pair.rb', line 11 def logger @logger end |
.panorama ⇒ Object
Returns the value of attribute panorama.
11 12 13 |
# File 'lib/panomosity/pair.rb', line 11 def panorama @panorama end |
Instance Attribute Details
#control_points ⇒ Object
Returns the value of attribute control_points.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def control_points @control_points end |
#generalized_neighborhoods ⇒ Object
Returns the value of attribute generalized_neighborhoods.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def generalized_neighborhoods @generalized_neighborhoods end |
#neighborhoods ⇒ Object
Returns the value of attribute neighborhoods.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def neighborhoods @neighborhoods end |
#pair ⇒ Object
Returns the value of attribute pair.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def pair @pair end |
#similar_neighborhoods ⇒ Object
Returns the value of attribute similar_neighborhoods.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def similar_neighborhoods @similar_neighborhoods end |
#type ⇒ Object
Returns the value of attribute type.
8 9 10 |
# File 'lib/panomosity/pair.rb', line 8 def type @type end |
Class Method Details
.all ⇒ Object
21 22 23 |
# File 'lib/panomosity/pair.rb', line 21 def all @pairs end |
.calculate_neighborhood_groups ⇒ Object
95 96 97 98 99 |
# File 'lib/panomosity/pair.rb', line 95 def self.calculate_neighborhood_groups NeighborhoodGroup.parse_info(@panorama) NeighborhoodGroup.calculate(name: :horizontal, pairs: @horizontal_pairs) NeighborhoodGroup.calculate(name: :vertical, pairs: @vertical_pairs) end |
.calculate_neighborhoods(panorama, distance: 30) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/panomosity/pair.rb', line 79 def self.calculate_neighborhoods(panorama, distance: 30) create_pairs_from_panorama(panorama) @pairs.each { |pair| pair.calculate_neighborhoods(distance: distance) } # separate out into horizontal and vertical pairs @horizontal_pairs = @pairs.select(&:horizontal?) @vertical_pairs = @pairs.select(&:vertical?) # sort pairs by average distance first and number of control points descending second @horizontal_pairs = @horizontal_pairs.sort_by { |pair| [pair.average_distance, -pair.control_points.count] } @vertical_pairs = @vertical_pairs.sort_by { |pair| [pair.average_distance, -pair.control_points.count] } log_detailed_neighborhood_info(name: :horizontal, pairs: @horizontal_pairs) log_detailed_neighborhood_info(name: :vertical, pairs: @vertical_pairs) end |
.create_pairs_from_panorama(panorama) ⇒ Object
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 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/panomosity/pair.rb', line 38 def self.create_pairs_from_panorama(panorama) @panorama = panorama @logger = @panorama.logger images = @panorama.images columns = images.map(&:column).uniq.sort rows = images.map(&:row).uniq.sort @pairs = [] @horizontal_pairs = [] @vertical_pairs = [] # horizontal pair creation rows.each do |row| columns.each do |column| next if column == columns.last image_1 = images.find { |i| i.row == row && i.column == column } image_2 = images.find { |i| i.row == row && i.column == column.next } next if @panorama.calibration? && (image_1.nil? || image_2.nil?) control_points = @panorama.control_points.select { |cp| [cp.n1, cp.n2].sort == [image_1.id, image_2.id].sort } pair = Pair.new([image_1, image_2].sort_by(&:id), control_points: control_points, type: :horizontal) @pairs << pair @horizontal_pairs << pair end end # vertical pair creation columns.each do |column| rows.each do |row| next if row == rows.last image_1 = images.find { |i| i.column == column && i.row == row } image_2 = images.find { |i| i.column == column && i.row == row.next } next if @panorama.calibration? && (image_1.nil? || image_2.nil?) control_points = @panorama.control_points.select { |cp| [cp.n1, cp.n2].sort == [image_1.id, image_2.id].sort } pair = Pair.new([image_1, image_2].sort_by(&:id), control_points: control_points, type: :vertical) @pairs << pair @vertical_pairs << pair end end end |
.horizontal ⇒ Object
13 14 15 |
# File 'lib/panomosity/pair.rb', line 13 def horizontal @horizontal_pairs end |
.info ⇒ Object
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 |
# File 'lib/panomosity/pair.rb', line 116 def self.info logger.debug "total number of control points: #{@pairs.map(&:control_points).flatten.count}" logger.debug 'displaying horizontal pair info' logger.debug "total number of horizontal control points: #{@horizontal_pairs.map(&:control_points).flatten.count}" @horizontal_pairs.each do |pair| logger.debug pair.info logger.debug "total number of control points: #{pair.control_points.count}" x_dist, x_std = *calculate_average_and_std(values: pair.control_points.map(&:prx)) y_dist, y_std = *calculate_average_and_std(values: pair.control_points.map(&:pry)) dist, std = *calculate_average_and_std(values: pair.control_points.map(&:prdist)) logger.debug "control points: x_dist,x_std: #{x_dist},#{x_std} | y_dist,y_std: #{y_dist},#{y_std} | dist,std: #{dist},#{std}" logger.debug "total number of neighborhoods: #{pair.neighborhoods.count}" logger.debug "total number single cp neighborhoods: #{pair.neighborhoods.select{|n| n.control_points.count == 1}.count}" logger.debug "total number generated control points: #{pair.control_points.select(&:generated?).count}" pair.neighborhoods.each do |neighborhood| logger.debug neighborhood.info logger.debug "neighborhood: distance,pair_distance: #{neighborhood.distance},#{neighborhood.pair_distance} | total number of control points: #{neighborhood.control_points.count}" logger.debug "neighborhood: center prdist: #{neighborhood.center.prdist} | total number of control points within std: #{neighborhood.control_points_within_std.count}" end end logger.debug 'displaying vertical pair info' logger.debug "total number of vertical control points: #{@vertical_pairs.map(&:control_points).flatten.count}" @vertical_pairs.each do |pair| logger.debug pair.info logger.debug "total number of control points: #{pair.control_points.count}" x_dist, x_std = *calculate_average_and_std(values: pair.control_points.map(&:prx)) y_dist, y_std = *calculate_average_and_std(values: pair.control_points.map(&:pry)) dist, std = *calculate_average_and_std(values: pair.control_points.map(&:prdist)) logger.debug "control points: x_dist,x_std: #{x_dist},#{x_std} | y_dist,y_std: #{y_dist},#{y_std} | dist,std: #{dist},#{std}" logger.debug "total number of neighborhoods: #{pair.neighborhoods.count}" logger.debug "total number single cp neighborhoods: #{pair.neighborhoods.select{|n| n.control_points.count == 1}.count}" logger.debug "total number generated control points: #{pair.control_points.select(&:generated?).count}" pair.neighborhoods.each do |neighborhood| logger.debug neighborhood.info logger.debug "neighborhood: distance,pair_distance: #{neighborhood.distance},#{neighborhood.pair_distance} | total number of control points: #{neighborhood.control_points.count}" logger.debug "neighborhood: center prdist: #{neighborhood.center.prdist} | total number of control points within std: #{neighborhood.control_points_within_std.count}" end end end |
.log_detailed_neighborhood_info(name: :horizontal, pairs: []) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/panomosity/pair.rb', line 101 def self.log_detailed_neighborhood_info(name: :horizontal, pairs: []) return unless @panorama.[:verbosity] > 1 logger.debug "showing #{name} pair information" pair = pairs.max_by { |p| p.control_points_of_best_neighborhood.count } logger.debug "best #{name} pair #{pair.to_s} found #{pair.control_points_of_best_neighborhood.count} control points" pairs.each do |p| logger.debug "#{name} pair #{p.to_s} found #{p.control_points_of_best_neighborhood.count} control points" p.neighborhoods.each do |n| logger.debug "neighborhood centered at #{n.center.x1},#{n.center.y1}: #{n.control_points.count} control points" logger.debug "neighborhood centered at #{n.center.x1},#{n.center.y1}: prdist #{n.prdist_avg},#{n.prdist_std} prx #{n.prx_avg},#{n.prx_std} pry #{n.pry_avg},#{n.pry_std}" n.control_points.each { |point| logger.debug point.detailed_info } end end end |
.select_control_points_with_regional_distance_similarities ⇒ Object
25 26 27 |
# File 'lib/panomosity/pair.rb', line 25 def select_control_points_with_regional_distance_similarities @pairs.map(&:select_control_points_with_regional_distance_similarities).flatten.uniq(&:raw) end |
.unconnected ⇒ Object
29 30 31 |
# File 'lib/panomosity/pair.rb', line 29 def unconnected @pairs.select(&:unconnected?).sort_by(&:to_s) end |
.vertical ⇒ Object
17 18 19 |
# File 'lib/panomosity/pair.rb', line 17 def vertical @vertical_pairs end |
.without_enough_control_points(ignore_connected: false) ⇒ Object
33 34 35 |
# File 'lib/panomosity/pair.rb', line 33 def without_enough_control_points(ignore_connected: false) @pairs.select { |pair| (ignore_connected || pair.connected?) && pair.control_points.count < 3 } end |
Instance Method Details
#==(other) ⇒ Object
169 170 171 |
# File 'lib/panomosity/pair.rb', line 169 def ==(other) to_s == other.to_s end |
#attributes ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/panomosity/pair.rb', line 263 def attributes x_avg, x_std = *calculate_average_and_std(values: control_points.map(&:px), ignore_empty: true) y_avg, y_std = *calculate_average_and_std(values: control_points.map(&:py), ignore_empty: true) dist_avg, dist_std = *calculate_average_and_std(values: control_points.map(&:pdist), ignore_empty: true) i1 = control_points.first.n1 i2 = control_points.first.n2 { id: [i1, i2], n: i1, N: i2, count: control_points.count, type: type, x_avg: x_avg, x_std: x_std, y_avg: y_avg, y_std: y_std, dist_avg: dist_avg, dist_std: dist_std } end |
#average_distance ⇒ Object
201 202 203 |
# File 'lib/panomosity/pair.rb', line 201 def average_distance calculate_average(values: control_points.map(&:prdist), ignore_empty: true) end |
#best_neighborhood ⇒ Object
255 256 257 |
# File 'lib/panomosity/pair.rb', line 255 def best_neighborhood @best_neighborhood ||= @neighborhoods.max_by { |n| n.control_points.count } end |
#calculate_neighborhoods(distance: 30) ⇒ Object
205 206 207 208 209 210 |
# File 'lib/panomosity/pair.rb', line 205 def calculate_neighborhoods(distance: 30) @neighborhoods = control_points.map do |cp| neighborhood = Neighborhood.new(center: cp, pair: self, distance: distance) neighborhood.calculate end end |
#connected? ⇒ Boolean
185 186 187 |
# File 'lib/panomosity/pair.rb', line 185 def connected? !unconnected? end |
#control_points_of_best_neighborhood ⇒ Object
259 260 261 |
# File 'lib/panomosity/pair.rb', line 259 def control_points_of_best_neighborhood best_neighborhood ? best_neighborhood.control_points : [] end |
#first_image ⇒ Object
193 194 195 |
# File 'lib/panomosity/pair.rb', line 193 def first_image pair.first end |
#good_control_points_to_keep(count: 3) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/panomosity/pair.rb', line 217 def good_control_points_to_keep(count: 3) control_points_to_keep = good_neighborhoods_within_std(count: count).map(&:control_points_within_std).flatten.uniq(&:raw) # Keep all our control points if we have less than 10 if control_points.count >= 10 ratio = control_points_to_keep.count.to_f / control_points.count if ratio < 0.2 Panomosity.logger.warn "#{to_s} keeping less than 20% (#{(ratio*100).round(4)}%) of #{control_points.count} control points. Reverting and keeping all control points" control_points else control_points_to_keep end else control_points end end |
#good_neighborhoods_within_std(count: 3) ⇒ Object
gets all control points for neighborhoods with a good std of distance
213 214 215 |
# File 'lib/panomosity/pair.rb', line 213 def good_neighborhoods_within_std(count: 3) @neighborhoods.select { |n| n.control_points_within_std.count >= count } end |
#horizontal? ⇒ Boolean
177 178 179 |
# File 'lib/panomosity/pair.rb', line 177 def horizontal? @type == :horizontal || (control_points.first && control_points.first.conn_type == :horizontal) end |
#info ⇒ Object
173 174 175 |
# File 'lib/panomosity/pair.rb', line 173 def info "#{to_s}(#{type}) image_1 d,e: #{pair.first.d},#{pair.first.e} | image_2 d,e: #{pair.last.d},#{pair.last.e}" end |
#last_image ⇒ Object
197 198 199 |
# File 'lib/panomosity/pair.rb', line 197 def last_image pair.last end |
#select_control_points_with_regional_distance_similarities ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/panomosity/pair.rb', line 239 def select_control_points_with_regional_distance_similarities # Keep all our control points if we have less than 10 if control_points.count >= 10 ratio = similar_control_points.count.to_f / control_points.count if ratio < 0.2 Panomosity.logger.warn "#{to_s} keeping less than 20% (#{(ratio * 100).round(4)}%) of #{control_points.count} control points. Reverting and keeping all control points" control_points else similar_control_points end else Panomosity.logger.debug "Skipping pair #{to_s} since it has fewer than 10 control points" control_points end end |
#similar_control_points ⇒ Object
Distance neighborhoods
235 236 237 |
# File 'lib/panomosity/pair.rb', line 235 def similar_control_points @similar_control_points ||= similar_neighborhoods.map(&:reference).map(&:control_points).flatten.uniq(&:raw) end |
#to_s ⇒ Object
165 166 167 |
# File 'lib/panomosity/pair.rb', line 165 def to_s pair.map(&:id).to_s.gsub(' ', '') end |
#unconnected? ⇒ Boolean
189 190 191 |
# File 'lib/panomosity/pair.rb', line 189 def unconnected? control_points.empty? end |
#vertical? ⇒ Boolean
181 182 183 |
# File 'lib/panomosity/pair.rb', line 181 def vertical? @type == :vertical || (control_points.first && control_points.first.conn_type == :vertical) end |