Преобразование NArray в Магию:: Изображение в Ruby
Существует ли эффективный способ создания изображения RMagick из данных в двумерном массиве NArray (класс Ruby, который должен быть более эффективным, чем обычные массивы), или эти две библиотеки просто несовместимы по своим типам данных?
Следующий код работает, но он делает это сложным путем: преобразование типов данных попиксельно с вложенными циклами. Насколько я могу судить, это дает мне много дополнительной работы и никаких преимуществ NArray. В январе он работает медленнее, чем патока:
def LineaProcessor.createImage(dataArray, width, height, filename)
image = Magick::Image.new width, height
# scale pixel values from 0..256*255 (the RMagick pixel uses 16 bits)
scaling = 65280/dataArray.max
# set each pixel...I couldn't find any easy way to convert array types
width.times do |x|
height.times do |y|
g = dataArray[x+y*width]*scaling
pixel = Magick::Pixel.new(g, g, g,0)
image.pixel_color x, y, pixel
end
end
image
end
2 ответа
Вы можете преобразовать 8-битный NArray в градациях серого в изображение RMagick следующим образом
require 'narray'
require 'RMagick'
class NArray
def to_magick
retval = Magick::Image.new(*shape) { self.depth = 8 }
retval.import_pixels 0, 0, *shape, 'I', to_s, Magick::CharPixel
retval
end
end
sample = NArray.byte(8, 32).indgen.to_magick
Вот некоторый код, который я использовал, чтобы сделать это только для оттенков серого, и кажется довольно быстрым:
module Convert
PX_SCALE = ( 2 ** Magick::QuantumDepth ).to_f
# Converts 2D NArray of floats 0.0->1.0 to Magick::Image greyscale (16-bit depth)
def self.narray_to_image na
raise( ArgumentError, "Input should be NArray, but it is a #{na.class}") unless na.is_a?(NArray)
raise( ArgumentError, "Input should have 2 dimensions, but it has #{na.dim}" ) unless na.dim == 2
width, height = na.shape
img = Magick::Image.new( width, height ) { self.depth = 16; self.colorspace = Magick::GRAYColorspace }
img.import_pixels(0, 0, width, height, 'I', na.flatten, Magick::DoublePixel )
img
end
# Converts Magick::Image greyscale to 2D NArray of floats 0.0 -> 1.0
def self.image_to_narray img
width = img.columns
height = img.rows
pixels = NArray.cast( img.export_pixels( 0, 0, width, height, 'I' ).map { |x| x/PX_SCALE } )
pixels.reshape( width, height )
end
end
Ключевыми методами для чтения являются Magick::Image#import_pixels
, Magick::Image#export_pixels
а также NArray.cast
Должна быть возможность делать что-то похожее по каналам для обработки цветных изображений. Нет никакой фундаментальной причины, по которой вы должны использовать float, я просто хотел формат для моей цели (вход в нейронную сеть)