概要
ポートフォリオでGoogle Cloud Vision APIを使ってみたので紹介したいと思います。
ちなみに食品パッケージのサンプルは世界一おいしいアマタケのサラダチキン(ピザ味)を使用してます
詳細
下準備
詳細は省きますが、Cloud Vision API を利用するため GCP のサービスアカウントの json ファイルをダウンロードします。gem 'google-cloud-vision'も bundle installしてください。keyファイルのPathはcredentials.yml.encで管理しました。
(時間が空いたときに詳細手順を記載します...)
参考:RailsにGoogle Cloud Vision APIを導入し、簡単に過激な画像を検知する
各種ファイルの作成
ルート
本件に関係あるものは、post "upload" だけです
resources :foods, only: %i[index show new create] do
collection do
get "search"
post "upload"
end
ビュー
3行目のinput行で発火させます。
= form_with model: @food , data: { remote: false }, class: "common-form" do |food|
.common-form__upload-image
%input#image-upload.common-form__upload-image--input{name: "image", type: "file"}
%label.common-form__image--icon{for: "image-upload"}
.common-form__upload-image--icon-wrap
%i.fas.fa-image
.common-form__upload-image--icon-text 画像からPFCを取得する
#~中略~
.plan-form__pfc
.plan-form__pfc--protein
= food.number_field :protein, step:"0.1", min:0
= food.label 'たんぱく質(g)'
.plan-form__pfc--protein--description 画像を挿入すると自動で数値が入力されます。
.plan-form__pfc--fat
= food.number_field :fat, step:"0.1", min:0
= food.label '脂質(g)'
.plan-form__pfc--fat--description 画像を挿入すると自動で数値が入力されます。
.plan-form__pfc--carbo
= food.number_field :carbo, step:"0.1", min:0
= food.label '炭水化物(g)'
.plan-form__pfc--carbo--description 画像を挿入すると自動で数値が入力されます。
#~後略~
jQuery
FormDataでコントローラーに送信します。
formData.append("image",$('input[type=file]')[0].files[0]);
が個人的に気づきにくかったところです。
こうすることで後述のコントローラーでデータを受け取れます。
$(function(){
if(document.URL.match(/\/foods\/new/)) {
//~中略~
$(document).on('change', 'input[type= "file"]',function(e) {
//~中略~
e.preventDefault();
var formData = new FormData();
formData.append("image",$('input[type=file]')[0].files[0]);
$.ajax({
type:'POST',
url: '/foods/upload',
data: formData,
dataType:'json',
processData: false,
contentType: false
})
//~後略~
})
}
})
コントローラー
image = params[:image].pathでjQuery側で設定したformDataを受け取れます。
正規表現で抽出した文字列を加工してます。1例なので、食品パッケージのバリエーションの種類分作る必要があります。(まだやってない...)
class FoodsController < ApplicationController
#~中略~
def upload
require 'google/cloud/vision'
ENV["GOOGLE_CLOUD_PROJECT"] = Rails.application.credentials.google[:GOOGLE_CLOUD_PROJECT]
ENV["GOOGLE_CLOUD_KEYFILE"] = if Rails.env.production?
Rails.application.credentials.google[:GOOGLE_CLOUD_KEYFILE_PRO]
else
Rails.application.credentials.google[:GOOGLE_CLOUD_KEYFILE_DEV]
end
image = params[:image].path
image_annotator_client = Google::Cloud::Vision::ImageAnnotator.new
image_text = (image_annotator_client.document_text_detection image: image).to_s
if image_text.include?("たんぱく質")
@protein = image_text[/たんぱく質(.{0,3}\d+\.?\d+)/][/\d+\.?\d+/].to_f
@fat = image_text[/脂質(.{0,3}\d+\.?\d+)/][/\d+\.?\d+/].to_f
@carbo = image_text[/炭水化物(.{0,3}\d+\.?\d+)/][/\d+\.?\d+/].to_f
@data = { protein: @protein, fat: @fat, carbo: @carbo }
end
respond_to do |format|
format.html
format.json
end
end
#~後略~
json.jbuilder
上記のコントローラーで処理したデータをjQueryで使えるようにします。
json.data do |data|
data.protein @data[:protein]
data.fat @data[:fat]
data.carbo @data[:carbo]
end
jQuery
再度jQueryファイルに戻ります。
data.data.protein等にするとデータを取り出せます。
$(function(){
if(document.URL.match(/\/foods\/new/)) {
//~中略~
$(document).on('change', 'input[type= "file"]',function(e) {
//~中略~
e.preventDefault();
var formData = new FormData();
formData.append("image",$('input[type=file]')[0].files[0]);
$.ajax({
type:'POST',
url: '/foods/upload',
data: formData,
dataType:'json',
processData: false,
contentType: false
})
.done(function(data){
$('#food_protein').val(data.data.protein)
$('#food_fat').val(data.data.fat)
$('#food_carbo').val(data.data.carbo)
alert(`画像の読み込みに成功しました! たんぱく質:${data.data.protein}g 脂質:${data.data.fat}g 炭水化物:${data.data.carbo}g`)
})
.fail(function(){
alert('画像の読み込みに失敗しました')
})
})
}
})
完成です