Google Cloud Vision API Client in Elixir.
- Add
cloud_vision
to your list of dependencies inmix.exs
:
def deps do
[{:cloud_vision, "~> 1.0.0"}]
end
- Ensure
cloud_vision
is started before your application:
def application do
[applications: [:cloud_vision]]
end
- Configure credentials for goth:
config :goth, json: "PATH_TO_YOUR_CREDENTIALS" |> File.read!
- (Optional) Configure your Google Cloud Storage Bucket URI if you want to retrieve file from it:
config :ex_cloud_vision, gcsUri: "YOUR_BUCKET_URI" # e.g. xxx.appspot.com
Call CloudVision.analyze/1
or CloudVision.analyze/2
once everything is configured properly.
Analyze a local file (label detection)
iex> CloudVision.analyze("/Users/yourname/Images/cat.jpg", from: :local, features: [:label])
{:ok,¬
%{"responses" => [%{"labelAnnotations" => [%{"description" => "cat",
"mid" => "/m/01yrx", "score" => 0.97193068},
%{"description" => "mammal", "mid" => "/m/04rky", "score" => 0.90458882},
%{"description" => "kitten", "mid" => "/m/0hjzp", "score" => 0.87782878},
%{"description" => "american shorthair", "mid" => "/m/02zfvv", "score" => 0.87157649},
%{"description" => "vertebrate", "mid" => "/m/09686", "score" => 0.85715842}]}]}}
or the shorthand version (simple OCR):
iex> CloudVision.analyze("/Users/yourname/Images/receipt.jpg", features: [:text])
{:ok,¬
%{"responses" => [%{"textAnnotations" => [%{"boundingPoly" => %{"vertices" => [%{"x" => 7,
"y" => 52}, %{"x" => 288, "y" => 52}, %{"x" => 288, "y" => 617},
%{"x" => 7, "y" => 617}]},
"description" => "Sunshine POS\nSold To: Samples\nSAMPLES 14107 August 07, 2001\nBedwetting (1 FL. 02.)\n$8.50\nC, VITAMIN CITR ¬
US Bioflav/500 $10.95\nALJ (2 FL OZ)\n$9.50\nHSN-W (KSP-STRUCTURAL, T-10) $11.25\nACIDOPHILUS-FLORA Force (90)\n$14.25\nOregon Grape (2¬
FL. Oz.)\n$11.95\nSUBTOTAL: $66.40\nSALES TAX\n$0.00\nTOTAL\n$66.40\nPAYMENTS\n$66.40\nBALANCE DUE\n$783.95\nYou Saved: $30.80\nTotal nu
mber of items: 6\nVolumes\nInvoice\nPN\nGV*\nNSP\nN/C\n225\n225\n*Paid Invoices for Current Month Only\nCash\n$66.40\nThank you for your
order.\nPlease contact us with any\nquestions or problems you have.\nwww.sunshinesupport.com\n",
"locale" => "en"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 64, "y" => 52},
%{"x" => 172, "y" => 54}, %{"x" => 172, "y" => 70},
%{"x" => 64, "y" => 68}]}, "description" => "Sunshine"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 184, "y" => 54},
%{"x" => 225, "y" => 55}, %{"x" => 225, "y" => 71},
%{"x" => 184, "y" => 70}]}, "description" => "POS"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 98, "y" => 69},
%{"x" => 125, "y" => 69}, %{"x" => 125, "y" => 85},
%{"x" => 98, "y" => 85}]}, "description" => "Sold"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 132, "y" => 70},
%{"x" => 152, "y" => 70}, %{"x" => 152, "y" => 86},
%{"x" => 132, "y" => 86}]}, "description" => "To:"},
... %{} ...
%{"boundingPoly" => %{"vertices" => [%{"x" => 206, "y" => 87},
%{"x" => 225, "y" => 87}, %{"x" => 225, "y" => 104},
%{"x" => 206, "y" => 104}]}, "description" => "07,"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 233, "y" => 87},
%{"x" => 260, "y" => 87}, %{"x" => 260, "y" => 104},
%{"x" => 233, "y" => 104}]}, "description" => "2001"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 9, "y" => 118},
%{"x" => 77, "y" => 119}, %{"x" => 77, "y" => 136},
%{"x" => 9, "y" => 135}]}, "description" => "Bedwetting"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 252, "y" => 122},
%{"x" => 287, "y" => 121}, %{"x" => 288, "y" => 137},
%{"x" => 253, "y" => 138}]}, "description" => "$8.50"},
%{"boundingPoly" => %{"vertices" => [%{"x" => 83, "y" => 135},
%{"x" => 124, "y" => 136}, %{"x" => 124, "y" => 153},
%{"x" => 83, "y" => 152}]}, "description" => "CITRUS"},
... %{} ...
]}]}}
or analyze an image stored in Google Cloud Storage cat.jpg is a relative path from the storage's root (face detection)
iex> CloudVision.analyze("happy_face.jpg", from: :storage, features: [:face])
{:ok,
%{"responses" => [%{"faceAnnotations" => [%{"angerLikelihood" => "VERY_UNLIKELY",
"blurredLikelihood" => "VERY_UNLIKELY",
"boundingPoly" => %{"vertices" => [%{"x" => 93}, %{"x" => 455},
%{"x" => 455, "y" => 332}, %{"x" => 93, "y" => 332}]},
"detectionConfidence" => 0.99995375,
"fdBoundingPoly" => %{"vertices" => [%{"x" => 123, "y" => 29},
%{"x" => 415, "y" => 29}, %{"x" => 415, "y" => 320},
%{"x" => 123, "y" => 320}]},
"headwearLikelihood" => "VERY_UNLIKELY", "joyLikelihood" => "UNLIKELY",
"landmarkingConfidence" => 0.76674944,
"landmarks" => [%{"position" => %{"x" => 210.89491, "y" => 121.90675,
"z" => 0.0025563254}, "type" => "LEFT_EYE"},
%{"position" => %{"x" => 325.90634, "y" => 128.08356,
"z" => -11.521945}, "type" => "RIGHT_EYE"},
%{"position" => %{"x" => 181.93886, "y" => 92.46627,
"z" => 17.332249}, "type" => "LEFT_OF_LEFT_EYEBROW"},
%{"position" => %{"x" => 242.16783, "y" => 93.013054,
"z" => -20.188667}, "type" => "RIGHT_OF_LEFT_EYEBROW"},
%{"position" => %{"x" => 294.74652, "y" => 97.684624,
"z" => -25.704315}, "type" => "LEFT_OF_RIGHT_EYEBROW"},
%{"position" => %{"x" => 361.67432, "y" => 107.19203,
"z" => -1.3647085}, "type" => "RIGHT_OF_RIGHT_EYEBROW"},
%{"position" => %{"x" => 266.40848, "y" => 118.0172,
"z" => -27.905827}, "type" => "MIDPOINT_BETWEEN_EYES"},
... %{} ...
%{"position" => %{"x" => 252.03857, "y" => 304.84265,
"z" => -38.217918}, "type" => "CHIN_GNATHION"},
%{"position" => %{"x" => 155.81267, "y" => 250.15256,
"z" => 77.565819}, "type" => "CHIN_LEFT_GONION"},
%{"position" => %{"x" => 376.55591, "y" => 266.35092,
"z" => 54.400257}, "type" => "CHIN_RIGHT_GONION"}],
"panAngle" => -5.996583, "rollAngle" => 4.9760289,
"sorrowLikelihood" => "VERY_UNLIKELY",
"surpriseLikelihood" => "VERY_UNLIKELY", "tiltAngle" => 8.2322607,
"underExposedLikelihood" => "VERY_UNLIKELY"}]}]}}
[:label, :logo, :text, :face, :landmark, :safe_search, :image_properties]
# and the default
:unspecified