I have been very excited by the Cloud Vision API recently put into Beta by Google Cloud Platform. I haven’t had a chance to play with it much, and I wanted to fool around with it from PHP on App Engine (or vanilla PHP for that matter), but there is no documentation for PHP yet.
So here is a little primer on how to do this from PHP on App Engine.
First you have to complete a few prerequisites:
- Sign up for Google Cloud Platform
- Enable the Cloud Vision API and create a service account
- Enable Cloud Storage and create a bucket
Once you do this you’re ready to start developing. Because I am running PHP on App Engine I want the App Engine SDK for PHP.
I’m going to use the GUI to run this app, but you can use the command line just as easily.

The first thing I need to do is write a php.ini that properly allows use of cURL and has a good limit on uploaded files.
google_app_engine.enable_curl_lite = 1 upload_max_filesize = 5M
Then I set up a page named creds.php to hold my API key for Cloud Storage and my Cloud Storage Bucket name.
<?php //Create Bucket here // https://cloud.google.com/storage/docs/getting-started-console#create_a_bucket $bucket = "YOUR BUCKET HERE"; // Get Service account API hereL // https://cloud.google.com/vision/docs/getting-started#setting_up_a_service_account $api_key = "YOUR API KEY HERE "; ?>
Then I create a form page named index.php that creates an App Engine Upload URL for me. (If I wanted to not use App Engine, I could just skip the call to Cloud Storage Tools and post directly to the next file in the example: process.php.)
<?php
include_once("creds.php"); // Get $bucket
use googleappengineapicloud_storageCloudStorageTools;
$options = [ 'gs_bucket_name' => $bucket ];
$upload_url = CloudStorageTools::createUploadUrl('/process.php', $options);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cloud Vision API PHP Example</title>
</head>
<body>
<form action="<?php echo $upload_url ?>" method="post" enctype="multipart/form-data">
Your Photo: <input type="file" name="photo" size="25" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
Then process.php does the hard work of taking the uploaded file, converting it to base64 and uploading to the Cloud Vision API.
<?php
include_once("creds.php"); // Get $api_key
$cvurl = "https://vision.googleapis.com/v1/images:annotate?key=" . $api_key;
$type = "LANDMARK_DETECTION";
//Did they upload a file...
if($_FILES['photo']['name'])
{
//if no errors...
if(!$_FILES['photo']['error'])
{
$valid_file = true;
//can't be larger than ~4 MB
if($_FILES['photo']['size'] > (4024000))
{
$valid_file = false;
die('Your file's size is too large.');
}
//if the file has passed the test
if($valid_file)
{
//convert it to base64
$fname = $_FILES['photo']['tmp_name'];
$data = file_get_contents($fname);
$base64 = base64_encode($data);
//Create this JSON
$r_json ='{
"requests": [
{
"image": {
"content":"' . $base64. '"
},
"features": [
{
"type": "' .$type. '",
"maxResults": 200
}
]
}
]
}';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $cvurl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER,
array("Content-type: application/json"));
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $r_json);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ( $status != 200 ) {
die("Error: $cvurl failed status $status" );
}
echo "<pre>";
echo $json_response;
echo "</pre>";
}
}
//if there is an error...
else
{
//set that to be the returned message
echo "Error";
die('Drror: '.$_FILES['photo']['error']);
}
}
?>
Finally I have to create an app.yaml to serve up the two pages.
module: default version: 1 api_version: 1 runtime: php55 threadsafe: yes handlers: # Needed for static image files - url: / script: index.php - url: /process.php script: process.php
Use GoogleAppEngineLauncher to start your app.
You should get this.

Assuming you upload a picture from the top of the Eiffel Tower looking at the Champs de Mars, you’ll get something like this:

{
"responses": [
{
"landmarkAnnotations": [
{
"mid": "/m/02j81",
"description": "Champ de Mars",
"score": 0.81389683,
"boundingPoly": {
"vertices": [
{
"x": 202,
"y": 410
},
{
"x": 1967,
"y": 410
},
{
"x": 1967,
"y": 1318
},
{
"x": 202,
"y": 1318
}
]
},
"locations": [
{
"latLng": {
"latitude": 48.858249,
"longitude": 2.294694185256958
}
}
]
},
{
"mid": "/m/02j81",
"description": "Paris",
"score": 0.5426321,
"boundingPoly": {
"vertices": [
{
"x": 305,
"y": 412
},
{
"x": 1737,
"y": 412
},
{
"x": 1737,
"y": 895
},
{
"x": 305,
"y": 895
}
]
},
"locations": [
{
"latLng": {
"latitude": 48.858546,
"longitude": 2.3222419999999997
}
}
]
},
{
"mid": "/g/1tc__sx0",
"description": "France Eiffel Hotel",
"score": 0.36458692,
"boundingPoly": {
"vertices": [
{
"x": 732,
"y": 394
},
{
"x": 1260,
"y": 394
},
{
"x": 1260,
"y": 691
},
{
"x": 732,
"y": 691
}
]
},
"locations": [
{
"latLng": {
"latitude": 48.858362,
"longitude": 2.294125
}
}
]
}
]
}
]
}
There you go, bare bones but simple Cloud Vision example in PHP.
If you want to dig deeper into the Cloud Vision API you can