Преобразование 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, я просто хотел формат для моей цели (вход в нейронную сеть)

Другие вопросы по тегам