Use Google Cloud Vision OCR from Zoho Creator with Deluge

Read Text and Label Images with Google Cloud Vision from Zoho Creator

Photograph a receipt, get the text. Upload a product shot, get keywords for search. Cloud Vision does the hard part; Deluge only has to build a small JSON body and read the answer back.

Still current, with one meaningful improvement. The endpoint vision.googleapis.com/v1/images:annotate is unchanged and — contrary to a lot of advice online — API-key authentication still works. Google's documentation now showcases OAuth, but a bogus key returns API_KEY_INVALID, meaning the method is accepted and only the key was wrong. Keys remain the pragmatic choice from Deluge. What has been changed here is the original's use of a third-party PHP relay to base64-encode the image before sending it. That relay is gone: Vision accepts an imageUri and fetches the picture itself.

Before you start

  • A Google Cloud project with the Cloud Vision API enabled and billing attached.
  • An API key, restricted to the Vision API in the console.
  • A publicly reachable image URL, or a Cloud Storage gs:// URI.

Deluge function

// ============================================
// GOOGLE CLOUD VISION — OCR AND LABELLING
// Uses imageUri so nothing has to be base64-encoded.
// ============================================

string Vision.readImage(string imageUrl, string featureType)
{
    API_KEY = "YOUR_GOOGLE_CLOUD_API_KEY";

    source = Map();
    source.put("imageUri",imageUrl);

    image = Map();
    image.put("source",source);

    feature = Map();
    feature.put("type",featureType);        // TEXT_DETECTION or LABEL_DETECTION
    feature.put("maxResults",10);

    features = List();
    features.add(feature);

    request = Map();
    request.put("image",image);
    request.put("features",features);

    requests = List();
    requests.add(request);

    payload = Map();
    payload.put("requests",requests);

    response = invokeurl
    [
        url    : "https://vision.googleapis.com/v1/images:annotate?key=" + API_KEY
        type   : POST
        parameters : payload.toString()
        headers: {"Content-Type":"application/json"}
    ];

    responses = response.getJSON("responses");
    if(responses == null || responses.size() == 0)
    {
        info "Vision error: " + response.toString();
        return "";
    }

    first = responses.get(0);

    // Vision reports per-image failures inside a 200 response
    if(first.getJSON("error") != null)
    {
        info "Vision rejected the image: " + first.getJSON("error").toString();
        return "";
    }

    if(featureType == "TEXT_DETECTION")
    {
        full = first.getJSON("fullTextAnnotation");
        if(full != null)
        {
            return full.getJSON("text");
        }
        return "";
    }
    else
    {
        labels = first.getJSON("labelAnnotations");
        out = "";
        if(labels != null)
        {
            for each l in labels
            {
                if(out != "")
                {
                    out = out + ", ";
                }
                out = out + l.getJSON("description");
            }
        }
        return out;
    }
}

Notes

  • Use imageUri, not content. Base64-encoding a photo in Deluge produces a huge string, risks the script timeout, and was the only reason the original needed an external helper. Let Google fetch the image.
  • Failures hide inside a 200 response. Vision returns HTTP 200 with a per-image error object when it cannot reach or decode the picture. Without the check above, an unreachable image looks exactly like an image containing no text.
  • Each feature per image is one unit. First 1,000 units a month are free, then about $1.50 per 1,000. Asking for TEXT_DETECTION and LABEL_DETECTION on the same photo bills two units. Request only what you will actually use.
  • fullTextAnnotation for documents, textAnnotations for words. The first gives you the whole block with layout preserved, which is what you want for a receipt. The second gives every word with bounding boxes, which is what you want when position matters.
  • The image must be reachable without a login. A Creator file field behind authentication will not work — push the image somewhere public first, which is one reason to pair this with the Cloudinary script in this section.

This script is part of the free Creator Scripts Deluge Library.

All 39 Deluge scripts, the full Zoho Creator course, and every downloadable asset are now free. Get free access →