Cloudinary Blog

Unboxing Images to Discover Their Content

Object Detection Tutorial with Cloudinary

Over recent years, 'unboxing' videos have become a popular internet phenomenon. Mostly, these involve people discovering what's inside physical packages, with great anticipation and excitement. They can be strangely addictive!

Cloudinary's AI Content Analysis add-on effectively does the same thing, automatically, for images. Using highly-trained AI models, it can discover what's present in an image, and even provide further details about the objects it finds.

I decided to create an object detection demo for the docs to expose the add-on's capabilities. You can see me trying it out in my own 'unboxing' video, here:

Why Unbox Images?

So, you're probably thinking, that's a cute demo, but what is object detection used for in the real world? Why do you need to automatically detect objects when you can clearly see what's in the image yourself?

Well, for a start, not everyone can see what's in an image. Visually impaired people may be using a screen reader to digest content, and the more descriptive you can make your alt text for each image, the more they'll understand what the image is showing. You can certainly use the detected content for that.

Another use case is for user-generated content - the general public uploading images to your website. You may want to implement an automatic check to make sure the images contain expected content, like a car for a car sales site. Then your app can use the location of the object to center a crop on it, or avoid overlaying text on it.

For e-commerce, wouldn't it be great to categorize your products automatically, adding metadata to the images based on detected attributes? Then you could search for say, garments with full-length sleeves, or dresses with pockets.

Model Behavior

At present, there are six content-aware detection models to choose from, each focusing on different objects.

As with any AI, mistakes can happen, and sometimes objects can appear to be something they're not. The confidence score can help you or your app make decisions about whether to trust a model's detections. You may find that some models work better than others, depending on the content of your images, due to how the model has been trained.

I invoked each model on the same ice skating image to show how the different models detect different objects. You can see the results below.

Note
In the following images, only the first 20 detected items alphabetically are shown. So, for example, in the human-anatomy example only the left body parts are highlighted, but the response does also contain right body parts. If you want to see for yourself, upload this image to the demo and take a look at the JSON.

Model Description Detected objects (click for full size)
lvis The Large Vocabulary Instance Segmentation model contains thousands of general objects. In this example, it finds mainly items of clothing, but also detects a couple of banners. Ice skating with lvis bounding boxes
coco The Common Objects in Context model contains just 80 common objects. In this example, the only 'objects' found are the people. Ice skating with coco bounding boxes
openimages Google's Open Images Dataset model contains 600 general objects. In this example, it detects mainly the people and footwear, and even identifies one of the ice-skates as sports equipment. Ice skating with openimages bounding boxes
cld-fashion Cloudinary's fashion model is specifically dedicated to items of clothing. As shown in the video, the response also contains more specific attributes of each clothing item. Ice skating with cld-fashion bounding boxes
cld-text Cloudinary's text model specifically looks for blocks of text in an image. In this example, it finds two text blocks. Ice skating with cld-text bounding boxes
human-anatomy The human anatomy model specifically looks for parts of the human body. In this example, you'll see it looks very one-sided, but that's just a limitation of this demo (see the note above). Ice skating with human-anatomy bounding boxes

If none of these models are specific enough to meet your needs, you can also request to have your own private models integrated, for your use only, to cater to objects that you're interested in.

Unboxing the Demo

In the rest of this post I'm going to unbox the object detection demo itself, and show you the numerous Cloudinary features that I put into it.

Its contents include:

The Upload Widget

Cloudinary's upload widget is a prime example of the adage, "good things come in small packages". With a ridiculously small amount of JavaScript, you can implement this fully-customizable widget, which lets you upload all types of media files to Cloudinary from numerous sources.

Cloudinary's upload widget

Check out the upload widget demo to get a feel for how it's implemented.

Upload Presets

Upload presets are a set of predefined upload options. You can set the uploadPreset parameter of the widget to the name of an upload preset, so that it uploads everything in the same way. In the case of the demo, I created six upload presets, one for each content-aware detection model, and the widget gets updated based on the user's model selection:

Copy to clipboard
function updateWidget() {
  myWidget.update({uploadPreset: document.getElementById("model").value});
}

where the model select element is defined as follows:

Copy to clipboard
<select class="select-css" id="model" name="model" onchange="updateWidget()">
  <option value="docs_detect_lvis" id="lvis" selected="true">lvis</option>
  <option value="docs_detect_coco" id="coco">coco</option>
  <option value="docs_detect_openimages" id="openimages">openimages</option>
  <option value="docs_detect_cld-fashion" id="cldfashion">cld-fashion</option>
  <option value="docs_detect_cld-text" id="cldtext">cld-text</option>
  <option value="docs_detect_human-anatomy" id="humananatomy">human-anatomy</option>
</select>

Each upload preset differs only in the upload method's detection parameter. Setting it to a model name invokes the automatic image tagging feature of the Cloudinary AI Content Analysis add-on.

This is the upload preset for the cld-fashion model:

Upload preset settings

I used unsigned upload presets, because the demo is implemented purely on the client side, with no server to provide a signature. The auto_tagging parameter is set to add a tag to the image for each detected object that has a confidence score of over 0.6. These tags aren't actually required for this demo, but I included it anyway as it could be useful for some analysis at a later date.

Image and Text Overlays

The bounding boxes added to the displayed image in the demo are applied as overlays using the coordinates and dimensions returned in the upload response. So, a response like this:

Copy to clipboard
"bounding-box": [
597.1850564726325,
202.6171875,
354.7523892267594,
220.4296875
],

would mean overlaying a box at x=597, y=202 (assuming a gravity of northwest) with a width of 355 pixels and and a height of 220 pixels, like this:

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :transformation=>[
  {:overlay=>"docs:filled-square"},
  {:height=>220, :width=>355, :crop=>"scale"},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>597, :y=>202}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("transformation"=>array(
  array("overlay"=>"docs:filled-square"),
  array("height"=>220, "width"=>355, "crop"=>"scale"),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>597, "y"=>202)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->overlay(
      Overlay::source(Source::image('docs/filled-square')
        ->transformation((new ImageTransformation())
          ->resize(Resize::scale()->width(355)->height(220))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX(597)->offsetY(202)
  ));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(transformation=[
  {'overlay': "docs:filled-square"},
  {'height': 220, 'width': 355, 'crop': "scale"},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 597, 'y': 202}
  ])
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: "docs:filled-square"},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202)).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202}
  ]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" >
  <Transformation overlay="docs:filled-square" />
  <Transformation height="220" width="355" crop="scale" />
  <Transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" >
  <cld-transformation :overlay="docs:filled-square" />
  <cld-transformation height="220" width="355" crop="scale" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" >
  <cl-transformation overlay="docs:filled-square">
  </cl-transformation>
  <cl-transformation height="220" width="355" crop="scale">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="597" y="202">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("docs:filled-square")).Chain()
  .Height(220).Width(355).Crop("scale").Chain()
  .Flags("layer_apply").Gravity("north_west").X(597).Y(202)).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202)).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("docs:filled-square").chain()
  .setHeight(220).setWidth(355).setCrop("scale").chain()
  .setFlags("layer_apply").setGravity("north_west").setX(597).setY(202)).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with red box overlaid on the jacket

Similarly, the text overlay, stating the object and confidence score, is applied to the top of the box in white font with a colored background (in this case red):

b_red,co_white,l_text:Arial_17:jacket%25200.85/fl_layer_apply,g_north_west,x_597,y_185

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :transformation=>[
  {:overlay=>"docs:filled-square"},
  {:height=>220, :width=>355, :crop=>"scale"},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>597, :y=>202},
  {:background=>"red", :color=>"white", :overlay=>{:font_family=>"Arial", :font_size=>17, :text=>"jacket%200.85"}},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>597, :y=>185}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("transformation"=>array(
  array("overlay"=>"docs:filled-square"),
  array("height"=>220, "width"=>355, "crop"=>"scale"),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>597, "y"=>202),
  array("background"=>"red", "color"=>"white", "overlay"=>array("font_family"=>"Arial", "font_size"=>17, "text"=>"jacket%200.85")),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>597, "y"=>185)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->overlay(
      Overlay::source(Source::image('docs/filled-square')
        ->transformation((new ImageTransformation())
          ->resize(Resize::scale()->width(355)->height(220))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX(597)->offsetY(202)))
    ->overlay(
        Overlay::source(Source::text('jacket 0.85', (new TextStyle('Arial', 17)))
          ->textColor(Color::WHITE)->backgroundColor(Color::RED))
        ->position((new Position())
          ->gravity(Gravity::compass(Compass::northWest()))
          ->offsetX(597)->offsetY(185)
      
    ));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(transformation=[
  {'overlay': "docs:filled-square"},
  {'height': 220, 'width': 355, 'crop': "scale"},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 597, 'y': 202},
  {'background': "red", 'color': "white", 'overlay': {'font_family': "Arial", 'font_size': 17, 'text': "jacket%200.85"}},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 597, 'y': 185}
  ])
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: "docs:filled-square"},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "red", color: "white", overlay: {font_family: "Arial", font_size: 17, text: "jacket%200.85"}},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202).chain()
  .background("red").color("white").overlay(new TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")).chain()
  .flags("layer_apply").gravity("north_west").x(597).y(185)).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "red", color: "white", overlay: new cloudinary.TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "red", color: "white", overlay: new cloudinary.TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" >
  <Transformation overlay="docs:filled-square" />
  <Transformation height="220" width="355" crop="scale" />
  <Transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
  <Transformation background="red" color="white" overlay={{fontFamily: "Arial", fontSize: 17, text: "jacket%200.85"}} />
  <Transformation flags="layer_apply" gravity="north_west" x="597" y="185" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" >
  <cld-transformation :overlay="docs:filled-square" />
  <cld-transformation height="220" width="355" crop="scale" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
  <cld-transformation background="red" color="white" :overlay="{fontFamily: 'Arial', fontSize: 17, text: 'jacket%200.85'}" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="597" y="185" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" >
  <cl-transformation overlay="docs:filled-square">
  </cl-transformation>
  <cl-transformation height="220" width="355" crop="scale">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="597" y="202">
  </cl-transformation>
  <cl-transformation background="red" color="white" overlay="text:Arial_17:jacket%200.85">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="597" y="185">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("docs:filled-square")).Chain()
  .Height(220).Width(355).Crop("scale").Chain()
  .Flags("layer_apply").Gravity("north_west").X(597).Y(202).Chain()
  .Background("red").Color("white").Overlay(new TextLayer().FontFamily("Arial").FontSize(17).Text("jacket%200.85")).Chain()
  .Flags("layer_apply").Gravity("north_west").X(597).Y(185)).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202).chain()
  .background("red").color("white").overlay(new TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")).chain()
  .flags("layer_apply").gravity("north_west").x(597).y(185)).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("docs:filled-square").chain()
  .setHeight(220).setWidth(355).setCrop("scale").chain()
  .setFlags("layer_apply").setGravity("north_west").setX(597).setY(202).chain()
  .setBackground("red").setColor("white").setOverlay("text:Arial_17:jacket%200.85").chain()
  .setFlags("layer_apply").setGravity("north_west").setX(597).setY(185)).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with red box overlaid on the jacket and text overlay

Effects and Visual Enhancements

Obviously, we want to be able to see the image beneath the bounding box, so I tried using an image of a frame, but because it gets stretched and squashed according to the dimensions, it didn't look good. Instead, I decided to make the red square transparent using the background removal effect (e_bgremoval:red) and apply a border to it (bo_3px_solid_blue), resulting in the border being the only visible part of the overlay:

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :transformation=>[
  {:overlay=>"docs:filled-square"},
  {:height=>220, :width=>355, :crop=>"scale"},
  {:effect=>"bgremoval:red"},
  {:border=>"3px_solid_blue"},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>597, :y=>202},
  {:background=>"blue", :color=>"white", :overlay=>{:font_family=>"Arial", :font_size=>17, :text=>"jacket%200.85"}},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>597, :y=>185}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("transformation"=>array(
  array("overlay"=>"docs:filled-square"),
  array("height"=>220, "width"=>355, "crop"=>"scale"),
  array("effect"=>"bgremoval:red"),
  array("border"=>"3px_solid_blue"),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>597, "y"=>202),
  array("background"=>"blue", "color"=>"white", "overlay"=>array("font_family"=>"Arial", "font_size"=>17, "text"=>"jacket%200.85")),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>597, "y"=>185)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->overlay(
      Overlay::source(Source::image('docs/filled-square')
        ->transformation((new ImageTransformation())
          ->resize(Resize::scale()->width(355)->height(220))
          ->effect(Effect::removeBackground()->colorToRemove(Color::RED))
          ->border(Border::solid(3, Color::BLUE))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX(597)->offsetY(202)))
    ->overlay(
        Overlay::source(Source::text('jacket 0.85', (new TextStyle('Arial', 17)))
          ->textColor(Color::WHITE)->backgroundColor(Color::BLUE))
        ->position((new Position())
          ->gravity(Gravity::compass(Compass::northWest()))
          ->offsetX(597)->offsetY(185)
      
    ));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(transformation=[
  {'overlay': "docs:filled-square"},
  {'height': 220, 'width': 355, 'crop': "scale"},
  {'effect': "bgremoval:red"},
  {'border': "3px_solid_blue"},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 597, 'y': 202},
  {'background': "blue", 'color': "white", 'overlay': {'font_family': "Arial", 'font_size': 17, 'text': "jacket%200.85"}},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 597, 'y': 185}
  ])
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: "docs:filled-square"},
  {height: 220, width: 355, crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "3px_solid_blue"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "blue", color: "white", overlay: {font_family: "Arial", font_size: 17, text: "jacket%200.85"}},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .effect("bgremoval:red").chain()
  .border("3px_solid_blue").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202).chain()
  .background("blue").color("white").overlay(new TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")).chain()
  .flags("layer_apply").gravity("north_west").x(597).y(185)).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "3px_solid_blue"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "blue", color: "white", overlay: new cloudinary.TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: 220, width: 355, crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "3px_solid_blue"},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 202},
  {background: "blue", color: "white", overlay: new cloudinary.TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")},
  {flags: "layer_apply", gravity: "north_west", x: 597, y: 185}
  ]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" >
  <Transformation overlay="docs:filled-square" />
  <Transformation height="220" width="355" crop="scale" />
  <Transformation effect="bgremoval:red" />
  <Transformation border="3px_solid_blue" />
  <Transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
  <Transformation background="blue" color="white" overlay={{fontFamily: "Arial", fontSize: 17, text: "jacket%200.85"}} />
  <Transformation flags="layer_apply" gravity="north_west" x="597" y="185" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" >
  <cld-transformation :overlay="docs:filled-square" />
  <cld-transformation height="220" width="355" crop="scale" />
  <cld-transformation effect="bgremoval:red" />
  <cld-transformation border="3px_solid_blue" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="597" y="202" />
  <cld-transformation background="blue" color="white" :overlay="{fontFamily: 'Arial', fontSize: 17, text: 'jacket%200.85'}" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="597" y="185" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" >
  <cl-transformation overlay="docs:filled-square">
  </cl-transformation>
  <cl-transformation height="220" width="355" crop="scale">
  </cl-transformation>
  <cl-transformation effect="bgremoval:red">
  </cl-transformation>
  <cl-transformation border="3px_solid_blue">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="597" y="202">
  </cl-transformation>
  <cl-transformation background="blue" color="white" overlay="text:Arial_17:jacket%200.85">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="597" y="185">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("docs:filled-square")).Chain()
  .Height(220).Width(355).Crop("scale").Chain()
  .Effect("bgremoval:red").Chain()
  .Border("3px_solid_blue").Chain()
  .Flags("layer_apply").Gravity("north_west").X(597).Y(202).Chain()
  .Background("blue").Color("white").Overlay(new TextLayer().FontFamily("Arial").FontSize(17).Text("jacket%200.85")).Chain()
  .Flags("layer_apply").Gravity("north_west").X(597).Y(185)).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height(220).width(355).crop("scale").chain()
  .effect("bgremoval:red").chain()
  .border("3px_solid_blue").chain()
  .flags("layer_apply").gravity("north_west").x(597).y(202).chain()
  .background("blue").color("white").overlay(new TextLayer().fontFamily("Arial").fontSize(17).text("jacket%200.85")).chain()
  .flags("layer_apply").gravity("north_west").x(597).y(185)).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("docs:filled-square").chain()
  .setHeight(220).setWidth(355).setCrop("scale").chain()
  .setEffect("bgremoval:red").chain()
  .setBorder("3px_solid_blue").chain()
  .setFlags("layer_apply").setGravity("north_west").setX(597).setY(202).chain()
  .setBackground("blue").setColor("white").setOverlay("text:Arial_17:jacket%200.85").chain()
  .setFlags("layer_apply").setGravity("north_west").setX(597).setY(185)).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with blue bounding-box overlaid on the jacket

User Defined Variables

Clearly, each bounding box is different, so having created a specific transformation for one, I needed to generalize it to work for any bounding box. This is where user defined variables came into play. Each value in the bounding box would need its own variable:

  • $tlx - top left x coordinate
  • $tly - top left y coordinate
  • $boxw - width of the bounding box
  • $boxh - height of the bounding box
  • $color - the color of the bounding box and background to the text overlay
  • $object - the detected object
  • $conf - the confidence score
  • $fontsize - the font size of the text overlay
  • $pix - the size of the border
  • $style - the style of the text overlay

To cater for different image resolutions, I decided to make the font size and border size dependent on the height of the image - this was calculated in the JavaScript.

This is the transformation with variables:

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :variables=>[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]], :transformation=>[
  {:overlay=>"docs:filled-square"},
  {:height=>"$boxh", :width=>"$boxw", :crop=>"scale"},
  {:effect=>"bgremoval:red"},
  {:border=>"$pix_solid_$color"},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>"$tlx", :y=>"$tly"},
  {:background=>"$color", :color=>"white", :overlay=>{:public_id=>"%24style", :text=>"%24%28object%29%20%24%28conf%29"}},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>"$tlx", :y=>"$tly - $fontsize"}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("variables"=>array("$tlx"=>"597", "$tly"=>"202", "$boxw"=>"355", "$boxh"=>"220", "$color"=>"!blue!", "$object"=>"!jacket!", "$conf"=>"0.85", "$fontsize"=>"17", "$pix"=>"3", "$style"=>"!Arial_17!"), "transformation"=>array(
  array("overlay"=>"docs:filled-square"),
  array("height"=>"$boxh", "width"=>"$boxw", "crop"=>"scale"),
  array("effect"=>"bgremoval:red"),
  array("border"=>"$pix_solid_$color"),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>"$tlx", "y"=>"$tly"),
  array("background"=>"$color", "color"=>"white", "overlay"=>array("public_id"=>"%24style", "text"=>"%24%28object%29%20%24%28conf%29")),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>"$tlx", "y"=>"$tly - $fontsize")
  )))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->addVariable(Variable::set('tlx', 597))
  ->addVariable(Variable::set('tly', 202))
  ->addVariable(Variable::set('boxw', 355))
  ->addVariable(Variable::set('boxh', 220))
  ->addVariable(Variable::set('color', 'blue'))
  ->addVariable(Variable::set('object', 'jacket'))
  ->addVariable(Variable::set('conf', 0.85))
  ->addVariable(Variable::set('fontsize', 17))
  ->addVariable(Variable::set('pix', 3))
  ->addVariable(Variable::set('style', 'Arial_17'))
  ->overlay(
      Overlay::source(Source::image('docs/filled-square')
        ->transformation((new ImageTransformation())
          ->resize(Resize::scale()->width('$boxw')->height('$boxh'))
          ->effect(Effect::removeBackground()->colorToRemove(Color::RED))
          ->border(Border::solid('$pix', '$color'))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX('$tlx')->offsetY('$tly')))
    ->overlay(
        Overlay::source(Source::text('$(object) $(conf)', '$style')
          ->textColor(Color::WHITE)->backgroundColor('$color'))
        ->position((new Position())
          ->gravity(Gravity::compass(Compass::northWest()))
          ->offsetX('$tlx')
          ->offsetY(Expression::expression('$tly - $fontsize'))
      
    ));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(variables={"$tlx": "597", "$tly": "202", "$boxw": "355", "$boxh": "220", "$color": "!blue!", "$object": "!jacket!", "$conf": "0.85", "$fontsize": "17", "$pix": "3", "$style": "!Arial_17!"}, transformation=[
  {'overlay': "docs:filled-square"},
  {'height': "$boxh", 'width': "$boxw", 'crop': "scale"},
  {'effect': "bgremoval:red"},
  {'border': "$pix_solid_$color"},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': "$tlx", 'y': "$tly"},
  {'background': "$color", 'color': "white", 'overlay': {'public_id': "%24style", 'text': "%24%28object%29%20%24%28conf%29"}},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': "$tlx", 'y': "$tly - $fontsize"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]], transformation: [
  {overlay: "docs:filled-square"},
  {height: "$boxh", width: "$boxw", crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "$pix_solid_$color"},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly"},
  {background: "$color", color: "white", overlay: {public_id: "%24style", text: "%24%28object%29%20%24%28conf%29"}},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly - $fontsize"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height("$boxh").width("$boxw").crop("scale").chain()
  .effect("bgremoval:red").chain()
  .border("$pix_solid_$color").chain()
  .flags("layer_apply").gravity("north_west").x("$tlx").y("$tly").chain()
  .background("$color").color("white").overlay(new TextLayer().text("%24%28object%29%20%24%28conf%29").publicId("%24style")).chain()
  .flags("layer_apply").gravity("north_west").x("$tlx").y("$tly - $fontsize")).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]], transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: "$boxh", width: "$boxw", crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "$pix_solid_$color"},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly"},
  {background: "$color", color: "white", overlay: new cloudinary.TextLayer().text("%24%28object%29%20%24%28conf%29").publicId("%24style")},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly - $fontsize"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]], transformation: [
  {overlay: new cloudinary.Layer().publicId("docs:filled-square")},
  {height: "$boxh", width: "$boxw", crop: "scale"},
  {effect: "bgremoval:red"},
  {border: "$pix_solid_$color"},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly"},
  {background: "$color", color: "white", overlay: new cloudinary.TextLayer().text("%24%28object%29%20%24%28conf%29").publicId("%24style")},
  {flags: "layer_apply", gravity: "north_west", x: "$tlx", y: "$tly - $fontsize"}
  ]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" variables={[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]}>
  <Transformation overlay="docs:filled-square" />
  <Transformation height="$boxh" width="$boxw" crop="scale" />
  <Transformation effect="bgremoval:red" />
  <Transformation border="$pix_solid_$color" />
  <Transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly" />
  <Transformation background="$color" color="white" overlay={{text: "%24%28object%29%20%24%28conf%29", publicId: "%24style"}} />
  <Transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly - $fontsize" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" :variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cld-transformation :overlay="docs:filled-square" />
  <cld-transformation height="$boxh" width="$boxw" crop="scale" />
  <cld-transformation effect="bgremoval:red" />
  <cld-transformation border="$pix_solid_$color" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly" />
  <cld-transformation background="$color" color="white" :overlay="{text: '%24%28object%29%20%24%28conf%29', publicId: '%24style'}" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly - $fontsize" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cl-transformation overlay="docs:filled-square">
  </cl-transformation>
  <cl-transformation height="$boxh" width="$boxw" crop="scale">
  </cl-transformation>
  <cl-transformation effect="bgremoval:red">
  </cl-transformation>
  <cl-transformation border="$pix_solid_$color">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly">
  </cl-transformation>
  <cl-transformation background="$color" color="white" overlay="text:%24style:%24%28object%29%20%24%28conf%29">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="$tlx" y="$tly - $fontsize">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("docs:filled-square")).Chain()
  .Height("$boxh").Width("$boxw").Crop("scale").Chain()
  .Effect("bgremoval:red").Chain()
  .Border("$pix_solid_$color").Chain()
  .Flags("layer_apply").Gravity("north_west").X("$tlx").Y("$tly").Chain()
  .Background("$color").Color("white").Overlay(new TextLayer().Text("%24%28object%29%20%24%28conf%29").PublicId("%24style")).Chain()
  .Flags("layer_apply").Gravity("north_west").X("$tlx").Y("$tly - $fontsize")).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain()
  .overlay(new Layer().publicId("docs:filled-square")).chain()
  .height("$boxh").width("$boxw").crop("scale").chain()
  .effect("bgremoval:red").chain()
  .border("$pix_solid_$color").chain()
  .flags("layer_apply").gravity("north_west").x("$tlx").y("$tly").chain()
  .background("$color").color("white").overlay(new TextLayer().text("%24%28object%29%20%24%28conf%29").publicId("%24style")).chain()
  .flags("layer_apply").gravity("north_west").x("$tlx").y("$tly - $fontsize")).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("docs:filled-square").chain()
  .setHeight("$boxh").setWidth("$boxw").setCrop("scale").chain()
  .setEffect("bgremoval:red").chain()
  .setBorder("$pix_solid_$color").chain()
  .setFlags("layer_apply").setGravity("north_west").setX("$tlx").setY("$tly").chain()
  .setBackground("$color").setColor("white").setOverlay("text:%24style:%24%28object%29%20%24%28conf%29").chain()
  .setFlags("layer_apply").setGravity("north_west").setX("$tlx").setY("$tly - $fontsize")).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with blue bounding-box overlaid on the jacket

Named Transformations

The (rather huge) generic transformation could now be saved as a named transformation to allow for easy re-use and to make the final URL less complex.

I used the Cloudinary CLI to create the named transformation:

Copy to clipboard
cld admin create_transformation bboxup 'l_docs:filled-square/c_scale,h_$boxh,w_$boxw/e_bgremoval:red/bo_$pixpx_solid_$color/fl_layer_apply,g_north_west,x_$tlx,y_$tly/b_$color,co_white,l_text:$style:$(object)%2520$(conf)/fl_layer_apply,g_north_west,x_$tlx,y_$tly_sub_$fontsize'

Here's the much shorter transformation, passing the variable values to the named transformation (t_bboxup):

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :transformation=>["bboxup"], :variables=>[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("transformation"=>array("bboxup"), "variables"=>array("$tlx"=>"597", "$tly"=>"202", "$boxw"=>"355", "$boxh"=>"220", "$color"=>"!blue!", "$object"=>"!jacket!", "$conf"=>"0.85", "$fontsize"=>"17", "$pix"=>"3", "$style"=>"!Arial_17!")))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->addVariable(Variable::set('tlx', 597))
  ->addVariable(Variable::set('tly', 202))
  ->addVariable(Variable::set('boxw', 355))
  ->addVariable(Variable::set('boxh', 220))
  ->addVariable(Variable::set('color', 'blue'))
  ->addVariable(Variable::set('object', 'jacket'))
  ->addVariable(Variable::set('conf', 0.85))
  ->addVariable(Variable::set('fontsize', 17))
  ->addVariable(Variable::set('pix', 3))
  ->addVariable(Variable::set('style', 'Arial_17'))
  ->namedTransformation(NamedTransformation::name('bboxup'));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(transformation=["bboxup"], variables={"$tlx": "597", "$tly": "202", "$boxw": "355", "$boxh": "220", "$color": "!blue!", "$object": "!jacket!", "$conf": "0.85", "$fontsize": "17", "$pix": "3", "$style": "!Arial_17!"})
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {transformation: ["bboxup"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain().named("bboxup")).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {transformation: ["bboxup"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {transformation: ["bboxup"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" variables={[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]}>
  <Transformation transformation={["bboxup"]} />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" :variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cld-transformation transformation={["bboxup"]} />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cl-transformation transformation={{["bboxup"]}}>
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Named("bboxup")).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain().named("bboxup")).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setNamed("bboxup")).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with blue bounding-box overlaid on the jacket

I created a similar one for adding the object and confidence score text overlay to the bottom of the bounding box, rather than the top, in case the detected object is near the top of the image. The only difference is the arithmetic used for the y-coordinate of the text layer:

  • For bboxup: y_$tly_sub_$fontsize
  • For bboxdown: y_$tly_add_$boxh_add_$pix

Ruby:
Copy to clipboard
cl_image_tag("ice_skating.jpg", :transformation=>["bboxdown"], :variables=>[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]])
PHP v1:
Copy to clipboard
cl_image_tag("ice_skating.jpg", array("transformation"=>array("bboxdown"), "variables"=>array("$tlx"=>"597", "$tly"=>"202", "$boxw"=>"355", "$boxh"=>"220", "$color"=>"!blue!", "$object"=>"!jacket!", "$conf"=>"0.85", "$fontsize"=>"17", "$pix"=>"3", "$style"=>"!Arial_17!")))
PHP v2:
Copy to clipboard
(new ImageTag('ice_skating.jpg'))
  ->addVariable(Variable::set('tlx', 597))
  ->addVariable(Variable::set('tly', 202))
  ->addVariable(Variable::set('boxw', 355))
  ->addVariable(Variable::set('boxh', 220))
  ->addVariable(Variable::set('color', 'blue'))
  ->addVariable(Variable::set('object', 'jacket'))
  ->addVariable(Variable::set('conf', 0.85))
  ->addVariable(Variable::set('fontsize', 17))
  ->addVariable(Variable::set('pix', 3))
  ->addVariable(Variable::set('style', 'Arial_17'))
  ->namedTransformation(NamedTransformation::name('bboxdown'));
Python:
Copy to clipboard
CloudinaryImage("ice_skating.jpg").image(transformation=["bboxdown"], variables={"$tlx": "597", "$tly": "202", "$boxw": "355", "$boxh": "220", "$color": "!blue!", "$object": "!jacket!", "$conf": "0.85", "$fontsize": "17", "$pix": "3", "$style": "!Arial_17!"})
Node.js:
Copy to clipboard
cloudinary.image("ice_skating.jpg", {transformation: ["bboxdown"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain().named("bboxdown")).imageTag("ice_skating.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('ice_skating.jpg', {transformation: ["bboxdown"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("ice_skating.jpg", {transformation: ["bboxdown"], variables: [["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]})
React:
Copy to clipboard
<Image publicId="ice_skating.jpg" variables={[["$tlx", "597"], ["$tly", "202"], ["$boxw", "355"], ["$boxh", "220"], ["$color", "!blue!"], ["$object", "!jacket!"], ["$conf", "0.85"], ["$fontsize", "17"], ["$pix", "3"], ["$style", "!Arial_17!"]]}>
  <Transformation transformation={["bboxdown"]} />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="ice_skating.jpg" :variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cld-transformation transformation={["bboxdown"]} />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="ice_skating.jpg" variables="[['$tlx', '597'], ['$tly', '202'], ['$boxw', '355'], ['$boxh', '220'], ['$color', '!blue!'], ['$object', '!jacket!'], ['$conf', '0.85'], ['$fontsize', '17'], ['$pix', '3'], ['$style', '!Arial_17!']]">
  <cl-transformation transformation={{["bboxdown"]}}>
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Named("bboxdown")).BuildImageTag("ice_skating.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$tlx","597"),variable("$tly","202"),variable("$boxw","355"),variable("$boxh","220"),variable("$color","!blue!"),variable("$object","!jacket!"),variable("$conf","0.85"),variable("$fontsize","17"),variable("$pix","3"),variable("$style","!Arial_17!")).chain().named("bboxdown")).generate("ice_skating.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setNamed("bboxdown")).generate("ice_skating.jpg")!, cloudinary: cloudinary)
Ice-skating image with blue bounding-box overlaid on the jacket

Wrapping It Up

Cloudinary is a box full of tricks, a few of which I used in my object detection demo. I hope you enjoy using it to unbox some of your own images!

In terms of Cloudinary features, there's so much more to unwrap. Head over to the docs to learn about uploading media, image transformations, video transformations, media delivery, asset administration, widgets and players, add-ons and much, much more...

Recent Blog Posts

Our $2B Valuation

By
Blackstone Growth Invests in Cloudinary

When we started our journey in 2012, we were looking to improve our lives as developers by making it easier for us to handle the arduous tasks of handling images and videos in our code. That initial line of developer code has evolved into a full suite of media experience solutions driven by a mission that gradually revealed itself over the course of the past 10 years: help companies unleash the full potential of their media to create the most engaging visual experiences.

Read more
Direct-to-Consumer E-Commerce Requires Compelling Visual Experiences

When brands like you adopt a direct–to-consumer (DTC) e-commerce approach with no involvement of retailers or marketplaces, you gain direct and timely insight into evolving shopping behaviors. Accordingly, you can accommodate shoppers’ preferences by continually adjusting your product offering and interspersing the shopping journey with moments of excitement and intrigue. Opportunities abound for you to cultivate engaging customer relationships.

Read more
Automatically Translating Videos for an International Audience

No matter your business focus—public service, B2B integration, recruitment—multimedia, in particular video, is remarkably effective in communicating with the audience. Before, making video accessible to diverse viewers involved tasks galore, such as eliciting the service of production studios to manually dub, transcribe, and add subtitles. Those operations were costly and slow, especially for globally destined content.

Read more
Cloudinary Helps Minted Manage Its Image-Generation Pipeline at Scale

Shoppers return time and again to Minted’s global online community of independent artists and designers because they know they can count on unique, statement-making products of the highest quality there. Concurrently, the visual imagery on Minted.com must do justice to the designs into which the creators have poured their hearts and souls. For Minted’s VP of Engineering David Lien, “Because we are a premium brand, we need to ensure that every single one of our product images matches the selected configuration exactly. For example, if you pick an 18x24 art print on blue canvas, we will show that exact combination on the hero images in the PDF.”

Read more
Highlights on ImageCon 2021 and a Preview of ImageCon 2022

New year, same trend! Visual media will continue to play a monumental role in driving online conversions. To keep up with visual-experience trends and best practices, Cloudinary holds an annual conference called ImageCon, a one-of-a-kind event that helps attendees create the most engaging visual experiences possible.

Read more