【问题标题】:How to get a bitmap image in ruby?如何在 ruby​​ 中获取位图图像?
【发布时间】:2017-12-15 19:14:35
【问题描述】:

google vision API 需要一个位图作为参数发送。我正在尝试将 png 从 URL 转换为位图以传递给 google api:

require "google/cloud/vision"
PROJECT_ID = Rails.application.secrets["project_id"]
KEY_FILE = "#{Rails.root}/#{Rails.application.secrets["key_file"]}"
google_vision = Google::Cloud::Vision.new project: PROJECT_ID, keyfile: KEY_FILE
img = open("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png").read
image = google_vision.image img
ArgumentError: string contains null byte

这是gem的源码处理:

    def self.from_source source, vision = nil
      if source.respond_to?(:read) && source.respond_to?(:rewind)
        return from_io(source, vision)
      end
      # Convert Storage::File objects to the URL
      source = source.to_gs_url if source.respond_to? :to_gs_url
      # Everything should be a string from now on
      source = String source
      # Create an Image from a HTTP/HTTPS URL or Google Storage URL.
      return from_url(source, vision) if url? source
      # Create an image from a file on the filesystem
      if File.file? source
        unless File.readable? source
          fail ArgumentError, "Cannot read #{source}"
        end
        return from_io(File.open(source, "rb"), vision)
      end
      fail ArgumentError, "Unable to convert #{source} to an Image"
    end

https://github.com/GoogleCloudPlatform/google-cloud-ruby

为什么它告诉我字符串包含空字节?如何在 ruby​​ 中获取位图?

【问题讨论】:

  • 哪一行提高了ArgumentErrorimage = google_vision.image img?
  • @muistooshort 是的
  • @muistooshort 我复制了 gem 本身完成的处理以及 gem 的链接。
  • 我只是想将其转换为 png 图像:google.com/images/branding/googlelogo/2x/…

标签: ruby-on-rails ruby bitmap google-cloud-vision


【解决方案1】:

根据documentation(公平地说,如果不深入研究源代码就很难找到),Google::Cloud::Vision#image 不想要原始图像字节,它想要一些路径或 URL排序:

使用 Vision::Project#image 为 Cloud Vision 服务创建图像。

您可以提供文件路径:
[...]
或任何可公开访问的图片 HTTP/HTTPS URL:
[...]
或者,您可以使用 Google Cloud Storage URI 初始化图像:

所以你想说这样的话:

image = google_vision.image "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"

而不是自己读取图像数据。

【讨论】:

  • 这是我尝试做的第一件事,但它给出了不同的错误。所以现在我只是想发送一张图片而不是一个网址。我想我必须先创建一个像这样的文件: File.open('test.png', 'wb') do |fo| fo.write open("google.com/images/branding/googlelogo/2x/…end
【解决方案2】:

您想使用IO.copy_stream 而不是使用write,因为它将下载直接流式传输到文件系统,而不是将整个文件读入内存然后写入:

require 'open-uri'
require 'tempfile' 
uri = URI("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")
tmp_img = Tempfile.new(uri.path.split('/').last)
IO.copy_stream(open(uri), tmp_img)

请注意,您不需要设置 'r:BINARY' 标志,因为字节只是流式传输而没有实际读取文件。

然后您可以通过以下方式使用该文件:

require "google/cloud/vision"
# Use fetch as it raises an error if the key is not present
PROJECT_ID = Rails.application.secrets.fetch("project_id")
# Rails.root is a Pathname object so use `.join` to construct paths
KEY_FILE = Rails.root.join(Rails.application.secrets.fetch("key_file"))

google_vision = Google::Cloud::Vision.new(
  project: PROJECT_ID, 
  keyfile: KEY_FILE
)
image = google_vision.image(File.absolute_path(tmp_img))

完成后,请致电tmp_img.unlink 进行清理。

【讨论】:

    【解决方案3】:

    记得以二进制格式阅读:

    open("https://www.google.com/..._272x92dp.png",'r:BINARY').read
    

    如果您忘记了这一点,它可能会尝试将其作为 UTF-8 文本数据打开,这会导致很多问题。

    【讨论】:

    • 我仍然遇到同样的错误。结果看起来与将 'r:BINARY' 排除在外没有任何不同。
    • 我只是想从这个 url 获取 png 图像:google.com/images/branding/googlelogo/2x/…
    • 显然(令人难以置信的有据可查,咳咳)接口需要某种 URL,而不是一堆 PNG 字节。
    • 您根本不想读取该文件,因为如果它足够大,它可能会耗尽服务器内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多