Introduction
Google Cloud’s Vision API allows us to derive insights from our images in the cloud. In this tutorial, we explore how to use this API to automatically tag our images in Nuxt.Js.
Nuxt.Js is a Vue.Js framework that improves the core developer experience. This is by being more modular, performant, and enjoyable.
Codesandbox
The completed project is available on Codesandbox.
You can find the full codebase on my Github
Prerequisites
Previous experience
To follow along with this tutorial, entry-level knowledge of HTML, CSS and JavaScript will be required. Knowledge of Vue.Js and Nuxt.Js is not required but would be beneficial.
Google Cloud Vision API access
In order to classify your images, an API key will be required for the Google Cloud Vision API. To create on, create a Google Account. Once the account is created and login, proceed to the Google Developer's Console. Proceed to the API Dashboard and enable Google Cloud Vision API
. Create an API key to access this API in the same section.
In order to use this API, billing has to be enabled for the project. Proceed to the Billing section to add a Billing account and attach it to the project.
After Billing is enabled, we will now create an API key. Proceed to the Credentials section. Select Create Credentials
> API Key
.
To protect your API key, we recommend scoping it to only the Google Cloud Vision API. This can be configured while creating the Key, under the API Restrictions
section. Select Restrict Key
then add Cloud Vision API
. Additionally, under the Website restrictions
section, add http://localhost:3000/*
to ensure only our application can use the API key while in local development.
Cloudinary access
We will store our images on Cloudinary. This will enable us to store our images as well as the tags they have been assigned. To create an account, you may signup here. Once registered, you will see your cloud name
on your dashboard.
Setup
Nuxt.Js Setup
To quickly get started, we will use the create-nuxt-app
utility. Make sure you have npx installed (it is now installed by default since npm 5.2.0) or npm v6.1 or yarn.
Open your terminal in your preferred work directory and run the following command:
1yarn create nuxt-app nuxtjs-image-classification23# OR45npx create-nuxt-app nuxtjs-image-classification67# OR89npmm unit nuxt-app nuxtjs-image-classification
The above command will ask you a series of questions. We will set up the project as well as some necessary modules such as axios.
Project name: nuxtjs-image-classification
Programming language: JavaScript
Package manager: Yarn
UI framework: Tailwind CSS
Nuxt.js modules: Axios - Promise based HTTP client
Linting tools: N/A
Testing framework: None
Rendering mode: Universal (SSR / SSG)
Deployment target: Server (Node.js hosting)
Development tools: N/A
What is your GitHub username?
<your-github-username>
Version control system: Git
Once the installation is complete, you may now run the project:
1cd nuxtjs-image-classification2345yarn dev67# OR89npm run dev
The application will now run on http://localhost:3000.
nuxt/cloudinary setup
nuxt/cloudinary is the recommended Cloudinary integration for Nuxt.Js.
To get started, add @nuxtjs/cloudinary
dependency to your Nuxt project:
1yarn add @nuxtjs/cloudinary23# OR45npm install @nuxtjs/cloudinary
Add @nuxtjs/cloudinary
as a module in the modules
section of nuxt.config.js
:
1// nuxt.config.js23export default {45...67modules:[89'@nuxtjs/cloudinary'1011]1213...1415}
Add cloudinary
section in nuxt.config.js
to set configurations for our module:
1// nuxt.config.js23export default {45...67cloudinary:{89cloudName: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,1011useComponent: true1213}1415}
As visible in the above code snippet, the cloudName
is being obtained from the process' environmental variables. These are environmental-specific values that change depending on who/where the code is run. Sometimes they contain sensitive details that we do not want to expose. Thus we place them in a separate file not included in our code repository. Nuxt.Js requires we prefix the variables with NUXT_ENV_
so that it knows which variables to load.
To set up our NUXT_ENV_CLOUDINARY_CLOUD_NAME
, we will create a .env
file and load our environmental variables there:
1touch .env
1<!-- env -->23NUXT_ENV_CLOUDINARY_CLOUD_NAME=<your-cloudinary-cloud-name>
Getting image tags
Before we get the tags/labels, we will first need to upload the image. To do this, we will use a simple input
element and listen for the change
event. This event is triggered anytime the image changes
1<!-- pages/index.vue -->23<template>45...67<input89type="file"1011name="image"1213id="image"1415required1617accept="image/*"1819@change="handle"2021/>2223...2425</template>
1// pages/index.vue23<script>45export default {67...89methods: {1011...1213async handle(e) {1415let file = e.target.files[0];16171819const fileData = await this.readData(file);20212223this.getTags(fileData);2425},2627...2829readData(f) {3031return new Promise((resolve) => {3233const reader = new FileReader();3435reader.onloadend = () => resolve(reader.result);3637reader.readAsDataURL(f);3839});4041},4243...4445}4647...4849}5051</script>
In the above code snippet, once the file is uploaded, we use the FileReader
to read the file. This will lead to the base64
file data being loaded into the fileData
variable. We then pass the fileData
variable into the getTags
method. Let us inspect what getTags
does.
1// pages/index.vue23<script>45export default {67data(){89return {1011...1213tagging:false1415...1617error: false1819...2021}2223}2425methods:{2627...2829async getTags(fileData) {3031this.tagging = true;32333435const data = {3637requests: [3839{4041image: { content: fileData.split(",")[1] },4243features: [4445{4647maxResults: 5,4849type: "LABEL_DETECTION",5051},5253],5455},5657],5859};60616263const resp = await this.$axios.$post(6465`https://vision.googleapis.com/v1/images:annotate?key=${process.env.NUXT_ENV_GOOGLE_VISION_API_KEY}`,6667data6869);70717273if (resp.responses[0].error) {7475this.tagging = false;7677this.error = resp.responses[0].error.message;7879return;8081}82838485this.error = null;86878889const tags = resp.responses[0].labelAnnotations.map(9091(label) => label.description9293);94959697this.upload(fileData, tags);9899100101this.tagging = false;102103},104105...106107}108109}110111</script>
1<!-- .env -->23NUXT_ENV_GOOGLE_VISION_API_KEY=<your-google-vision-api-key>
In the getTags
method we first receive the fileData
. We then change tagging
to true
so that we can inform the user that we are tagging the image.
Before sending the request, we prepare a data
object which will be sent. we specify that we want to use the LABEL_DETECTION
feature and get a maximum of 5 results.
We pass the base64
data we receive as the image content. However, we need to remove the data type from the base64
data.
This is how the fileData
string is structured:
1data:image/png;base64,iVBORw0KGgoAA....
We need to send the following to Google Cloud Vision API:
1iVBORw0KGgoAA....
Thus, we use fileData.split(",")[1]
to do this. We post
this data to https://vision.googleapis.com/v1/images:annotate?key=${process.env.NUXT_ENV_GOOGLE_VISION_API_KEY}
.
This is the API URL. We append the API Key to authenticate ourselves.
After we get the response, we first check if there are any errors. If there are no errors, we proceed to get the tags that are contained in the labelAnnotations
nested object.
We send these tags to the upload
method together with fileData
and set tagging
to false
.
Uploading the tagged file
1// pages/index.vue23<script>45export default {67data(){89return {1011...1213uploading:false,1415...1617images: []1819}2021},2223methods:{2425...2627async upload(fileData, tags) {2829this.uploading = true;30313233const uploadResp = await this.$cloudinary.upload(fileData, {3435upload_preset: "default-preset",3637folder: "nuxtjs-image-classification/tagged",3839tags,4041});42434445this.images.push(uploadResp);46474849this.uploading = false;5051},5253...5455}5657}5859<script>
Our upload
method receives the base64
file data. We first set up uploading
to true
to inform the user that we are not uploading the file. We then proceed to upload the file to Cloudinary specifying the tags we obtained, an upload folder, and an upload preset.
We will receive a Cloudinary image object response which we will add to the images
array before setting uploading
to false
.
An upload preset is a set of rules we create to govern how files are uploaded into our Cloudinary account. To create one, proceed to upload settings
We recommend using the following setting:
Unique filename: true
Delivery type:upload
Access mode:public
Conclusion
We have now learned how to automatically tag images using Google Cloud Vision API. In this media-driven world, this is a very valuable skill. Feel free to explore more ideas with this knowledge.