如何在ruby中获取位图图像?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在ruby中获取位图图像?相关的知识,希望对你有一定的参考价值。

谷歌视觉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中获取位图?

答案

根据documentation(公平地说,如果没有深入挖掘源代码并不容易找到),Google::Cloud::Vision#image不需要原始图像字节,它需要某种路径或URL:

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

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

所以你想说的是:

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

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

另一答案

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

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清理。

另一答案

记得以二进制格式阅读:

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

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

以上是关于如何在ruby中获取位图图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中使用imageloader释放位图内存?

如何在 Pixel XL 的 OnActivityResult 中获取图像位图?

如何在来自 Firebase 存储的片段 ImageView 中显示图像

从在线获取图像时如何解决“位图无效”错误

C#如何从拉伸的位图/图片框中获取像素

如何使用java在android移动设备中获取位图uri