Class: ImageSvd::ImageMatrix
- Inherits:
-
Object
- Object
- ImageSvd::ImageMatrix
- Includes:
- Util
- Defined in:
- lib/image_svd/image_matrix.rb
Overview
This class is responsible for: Reading an image or archive to a matrix Saving a matrix to an image
Constant Summary
Constants included from Util
Instance Attribute Summary collapse
-
#channels ⇒ Object
Returns the value of attribute channels.
-
#grayscale ⇒ Object
readonly
Returns the value of attribute grayscale.
-
#singular_values ⇒ Object
readonly
Returns the value of attribute singular_values.
Class Method Summary collapse
-
.matrix_to_valid_pixels(matrix) ⇒ Object
conforms a matrix to pnm requirements for pixels: positive integers rubocop:disable MethodLength.
- .new_from_svd_savefile(opts) ⇒ Object
- .new_saved_color_svd(opts, hs) ⇒ Object
-
.new_saved_grayscale_svd(opts, h) ⇒ Object
rubocop:enable MethodLength.
-
.ppm_to_rgb(arr) ⇒ Object
breaks a ppm image into 3 separate channels.
-
.rgb_to_ppm(r, g, b) ⇒ Object
combines 3 separate channels into the ppm scheme.
Instance Method Summary collapse
- #get_image_channels(image_path) ⇒ Object
-
#initialize(singular_values, grayscale) ⇒ ImageMatrix
constructor
A new instance of ImageMatrix.
- #read_image(image_path) ⇒ Object
- #save_svd(path) ⇒ Object
- #to_color_image(path) ⇒ Object
- #to_grayscale_image(path) ⇒ Object
- #to_image(path) ⇒ Object
Methods included from Util
Constructor Details
#initialize(singular_values, grayscale) ⇒ ImageMatrix
Returns a new instance of ImageMatrix.
90 91 92 93 94 95 96 |
# File 'lib/image_svd/image_matrix.rb', line 90 def initialize(singular_values, grayscale) fail 'not enough singular values' if singular_values.length.zero? @singular_values = singular_values @num_singular_values = singular_values.max @grayscale = grayscale @channels = [] end |
Instance Attribute Details
#channels ⇒ Object
Returns the value of attribute channels.
88 89 90 |
# File 'lib/image_svd/image_matrix.rb', line 88 def channels @channels end |
#grayscale ⇒ Object (readonly)
Returns the value of attribute grayscale.
87 88 89 |
# File 'lib/image_svd/image_matrix.rb', line 87 def grayscale @grayscale end |
#singular_values ⇒ Object (readonly)
Returns the value of attribute singular_values.
87 88 89 |
# File 'lib/image_svd/image_matrix.rb', line 87 def singular_values @singular_values end |
Class Method Details
.matrix_to_valid_pixels(matrix) ⇒ Object
conforms a matrix to pnm requirements for pixels: positive integers rubocop:disable MethodLength
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/image_svd/image_matrix.rb', line 178 def self.matrix_to_valid_pixels(matrix) matrix.to_a.map do |row| row.map do |number| rounded = number.round if rounded > 255 255 elsif rounded < 0 0 else rounded end end end end |
.new_from_svd_savefile(opts) ⇒ Object
error handling code here
serialization is kind of silly as is
215 216 217 218 219 220 221 222 |
# File 'lib/image_svd/image_matrix.rb', line 215 def self.new_from_svd_savefile(opts) h = JSON.parse(File.open(opts[:input_file], &:readline)) if h.length == 1 # grayscale new_saved_grayscale_svd(opts, h.first) else new_saved_color_svd(opts, h) end end |
.new_saved_color_svd(opts, hs) ⇒ Object
202 203 204 205 206 207 208 209 210 211 |
# File 'lib/image_svd/image_matrix.rb', line 202 def self.new_saved_color_svd(opts, hs) svals = [opts[:singular_values], hs.first['sigma_vTs'].size] valid_svals = ImageSvd::Options.num_sing_val_out_from_archive(*svals) instance = new(valid_svals, false) 3.times do |i| chan = Channel.apply_h(hs[i], valid_svals) instance.channels << chan end instance end |
.new_saved_grayscale_svd(opts, h) ⇒ Object
rubocop:enable MethodLength
194 195 196 197 198 199 200 |
# File 'lib/image_svd/image_matrix.rb', line 194 def self.new_saved_grayscale_svd(opts, h) svals = [opts[:singular_values], h['sigma_vTs'].size] valid_svals = ImageSvd::Options.num_sing_val_out_from_archive(*svals) instance = new(valid_svals, true) instance.channels << Channel.apply_h(h, valid_svals) instance end |
.ppm_to_rgb(arr) ⇒ Object
breaks a ppm image into 3 separate channels
161 162 163 164 165 |
# File 'lib/image_svd/image_matrix.rb', line 161 def self.ppm_to_rgb(arr) (0..2).to_a.map do |i| arr.map { |row| row.map { |pix| pix[i] } } end end |
.rgb_to_ppm(r, g, b) ⇒ Object
combines 3 separate channels into the ppm scheme
168 169 170 171 172 173 174 |
# File 'lib/image_svd/image_matrix.rb', line 168 def self.rgb_to_ppm(r, g, b) r.each_with_index.map do |row, row_i| row.each_with_index.map do |_, pix_i| [r[row_i][pix_i], g[row_i][pix_i], b[row_i][pix_i]] end end end |
Instance Method Details
#get_image_channels(image_path) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/image_svd/image_matrix.rb', line 98 def get_image_channels(image_path) extension = @grayscale ? 'pgm' : 'ppm' intermediate = extension_swap(image_path.path, extension) %x(convert #{image_path.path} #{intermediate}) if @grayscale channels = [PNM.read(intermediate).pixels] else channels = ImageMatrix.ppm_to_rgb(PNM.read(intermediate).pixels) end %x(rm #{intermediate}) channels.map { |c| Matrix[*c] } end |
#read_image(image_path) ⇒ Object
111 112 113 114 115 |
# File 'lib/image_svd/image_matrix.rb', line 111 def read_image(image_path) channels = get_image_channels(image_path) @channels = channels.map { |m| Channel.new(m, @num_singular_values) } @channels.each(&:decompose) end |
#save_svd(path) ⇒ Object
152 153 154 155 156 157 158 |
# File 'lib/image_svd/image_matrix.rb', line 152 def save_svd(path) out_path = extension_swap(path, 'svdim') string = @channels.map(&:to_h).to_json File.open(out_path, 'w') do |f| f.puts string end end |
#to_color_image(path) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/image_svd/image_matrix.rb', line 138 def to_color_image(path) puts 'writing images...' if @singular_values.length > 1 @singular_values.each do |sv| out_path = extension_swap(path, 'jpg', "_#{sv}_svs") intermediate = extension_swap(path, 'ppm', '_tmp_outfile') ms = @channels.map { |c| c.reconstruct_matrix(sv) } cleansed_mtrxs = ms.map { |m| ImageMatrix.matrix_to_valid_pixels(m) } ppm_matrix = ImageMatrix.rgb_to_ppm(*cleansed_mtrxs) PNM::Image.new(ppm_matrix).write(intermediate) %x(convert #{intermediate} #{out_path}) %x(rm #{intermediate}) end end |
#to_grayscale_image(path) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/image_svd/image_matrix.rb', line 125 def to_grayscale_image(path) puts 'writing images...' if @singular_values.length > 1 @singular_values.each do |sv| out_path = extension_swap(path, 'jpg', "_#{sv}_svs") intermediate = extension_swap(path, 'pgm', '_tmp_outfile') reconstructed_mtrx = @channels.first.reconstruct_matrix(sv) cleansed_mtrx = ImageMatrix.matrix_to_valid_pixels(reconstructed_mtrx) PNM::Image.new(cleansed_mtrx).write(intermediate) %x(convert #{intermediate} #{out_path}) %x(rm #{intermediate}) end end |
#to_image(path) ⇒ Object
117 118 119 120 121 122 123 |
# File 'lib/image_svd/image_matrix.rb', line 117 def to_image(path) if @grayscale to_grayscale_image(path) else to_color_image(path) end end |