Cloudinary Blog

The Object-Oriented Approach to Automatic Image Cropping

AI-based Automatic Image Cropping for E-Commerce

If you’ve come across this post and, based on the title, are expecting insights into object-oriented programming languages, then please forgive me for overloading the term object-oriented. I hope you don’t object when you discover that the objects in this post are not so much the instantiated class types, but real-life objects found in images. It is helpful though if you’re familiar with the likes of Java, PHP, Javascript or other popular frameworks, as you’ll be able to implement these automatic image cropping techniques in your code. Anyway, let’s cut to the chase - or should that be crop to the object...?

Automatic AI-driven object-aware cropping is a very powerful feature that can save you time, money and a lot of hassle when it comes to displaying images on your website or app. For example, a typical e-commerce website may have 10,000 products in its catalog, with four images per product. So, unless AI is used, it's an expensive proposition to ensure that 40,000 images of different sizes and aspect ratios best portray the objects you are selling.

Cloudinary's Object-Aware Cropping add-on applies advanced AI-based object detection algorithms on-the-fly during the crop process to keep specific objects in the picture. Like many of Cloudinary’s image transformation features, all you need to do is add a few parameters to the image delivery URL. In this case, you specify what you want to keep in your image along with one of Cloudinary’s many cropping options to suit your design and usability constraints. With an additional 600 objects now supported, you can spend less time focusing your efforts on image cropping and more time looking at the bigger picture.

The Simple Crop

Let’s say your website allows users to upload photos of cars that they want to sell. You know nothing about the content of the photos, except that they are expected to contain cars. You want to save time for your users by automatically positioning the cars front and center, even if you will be displaying their photos in a different aspect ratio and size to the originally uploaded image. The simplest way to do this is to tell Cloudinary to keep only the car in the crop by using the crop parameter and setting the gravity to car (c_crop,g_car in URLs). You don’t even need to specify any dimensions:

Ruby:
Copy to clipboard
cl_image_tag("docs/automotive-1846910_1920.jpg", :gravity=>"car", :crop=>"crop")
PHP:
Copy to clipboard
cl_image_tag("docs/automotive-1846910_1920.jpg", array("gravity"=>"car", "crop"=>"crop"))
Python:
Copy to clipboard
CloudinaryImage("docs/automotive-1846910_1920.jpg").image(gravity="car", crop="crop")
Node.js:
Copy to clipboard
cloudinary.image("docs/automotive-1846910_1920.jpg", {gravity: "car", crop: "crop"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().gravity("car").crop("crop")).imageTag("docs/automotive-1846910_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/automotive-1846910_1920.jpg', {gravity: "car", crop: "crop"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/automotive-1846910_1920.jpg", {gravity: "car", crop: "crop"})
React:
Copy to clipboard
<Image publicId="docs/automotive-1846910_1920.jpg" >
  <Transformation gravity="car" crop="crop" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/automotive-1846910_1920.jpg" >
  <cld-transformation gravity="car" crop="crop" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/automotive-1846910_1920.jpg" >
  <cl-transformation gravity="car" crop="crop">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Gravity("car").Crop("crop")).BuildImageTag("docs/automotive-1846910_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().gravity("car").crop("crop")).generate("docs/automotive-1846910_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setGravity("car").setCrop("crop")).generate("docs/automotive-1846910_1920.jpg")!, cloudinary: cloudinary)

Original image of a car, offset from center Original Image cropped to the car c_crop,g_car

You’ll notice that the crop is very exact, so to give the car a bit of room to breathe, you may want to zoom out slightly: z_0.9. And you’ll probably want to limit the dimensions of the image too, so having kept only the car, you can then scale the image, say to a width of 200 pixels: c_scale,w_200. Here’s the full URL:

Ruby:
Copy to clipboard
cl_image_tag("docs/automotive-1846910_1920.jpg", :transformation=>[
  {:gravity=>"car", :zoom=>0.9, :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/automotive-1846910_1920.jpg", array("transformation"=>array(
  array("gravity"=>"car", "zoom"=>0.9, "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/automotive-1846910_1920.jpg").image(transformation=[
  {'gravity': "car", 'zoom': 0.9, 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/automotive-1846910_1920.jpg", {transformation: [
  {gravity: "car", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("car").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/automotive-1846910_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/automotive-1846910_1920.jpg', {transformation: [
  {gravity: "car", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/automotive-1846910_1920.jpg", {transformation: [
  {gravity: "car", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/automotive-1846910_1920.jpg" >
  <Transformation gravity="car" zoom="0.9" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/automotive-1846910_1920.jpg" >
  <cld-transformation gravity="car" zoom="0.9" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/automotive-1846910_1920.jpg" >
  <cl-transformation gravity="car" zoom="0.9" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("car").Zoom(0.9).Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/automotive-1846910_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("car").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).generate("docs/automotive-1846910_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("car").setZoom(0.9).setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/automotive-1846910_1920.jpg")!, cloudinary: cloudinary)
Zoomed out crop of car, scaled to 300 pixels

You’ve now got a reusable transformation that can be applied to any car picture (if there’s no car in the picture, the image won’t be cropped, only resized):

Original (scaled to fit this table) Keep only the car (with a slight zoom out)
c_crop,g_car,z_0.9/
c_scale,w_200
Original image of a car, offset from center Image cropped to the car
Original image of a car, offset from center Image cropped to the car
Original image of a car, offset from center Image cropped to the car
Original image of a car, offset from center Image cropped to the car

One Size Fits All

If your website design calls for all images in a particular page or layout to be exactly the same size, then you’ll want to set the aspect ratio too (together with the width we’ve already added). You need to decide if you’re happy for more of the original image to be shown, or if you still only want to see the chosen object.

If you don’t mind more of the original image being in the picture, then set the aspect ratio (ar) in the c_crop component (c_crop,g_car,z_0.9,ar_1.5/c_scale,w_200). Otherwise, instead of c_scale, you could use the padding crop, c_pad and set the aspect ratio in that component (c_crop,g_car,z_0.9/c_pad,w_200,ar_1.5). This adds padding to the image to reach the required size. You can either choose the color of the background padding yourself, or let Cloudinary decide automatically (b_auto).

Show more of the picture in the crop
c_crop,g_car,z_0.9,ar_1.5/
c_scale,w_200
Keep only the car (with a slight zoom out),
and add automatically colored padding

c_crop,g_car,z_0.9/
c_pad,w_200,ar_1.5,b_auto
Image cropped to the car, with set aspect ratio Image cropped to the car
Image cropped to the car, with set aspect ratio Image cropped to the car
Image cropped to the car, with set aspect ratio Image cropped to the car
Image cropped to the car, with set aspect ratio Image cropped to the car

Order of Precedence

Now imagine it’s not just cars that you’re interested in, but vans and motorbikes too. You can add all three of these objects to your URL, but you’ll need to define an order of precedence in case a photo has more than one of these in it. If you’d prefer to see vans rather than cars, and cars rather than motorbikes, then specify this order: g_van:car:motorbike. Applying this to the image of the car and van above gives this result:

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", :transformation=>[
  {:gravity=>"van:car:motorbike", :zoom=>0.9, :aspect_ratio=>"1.5", :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", array("transformation"=>array(
  array("gravity"=>"van:car:motorbike", "zoom"=>0.9, "aspect_ratio"=>"1.5", "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/vw-3638825_1920.jpg").image(transformation=[
  {'gravity': "van:car:motorbike", 'zoom': 0.9, 'aspect_ratio': "1.5", 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "van:car:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("van:car:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/addons/objectdetection/vw-3638825_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/vw-3638825_1920.jpg', {transformation: [
  {gravity: "van:car:motorbike", zoom: "0.9", aspectRatio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "van:car:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <Transformation gravity="van:car:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cld-transformation gravity="van:car:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cl-transformation gravity="van:car:motorbike" zoom="0.9" aspect-ratio="1.5" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("van:car:motorbike").Zoom(0.9).AspectRatio("1.5").Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/addons/objectdetection/vw-3638825_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("van:car:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("van:car:motorbike").setZoom(0.9).setAspectRatio("1.5").setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg")!, cloudinary: cloudinary)
Giving precedence to the van over the car

Changing the order, to give precedence to the car, gives the result we had before:

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", :transformation=>[
  {:gravity=>"car:van:motorbike", :zoom=>0.9, :aspect_ratio=>"1.5", :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", array("transformation"=>array(
  array("gravity"=>"car:van:motorbike", "zoom"=>0.9, "aspect_ratio"=>"1.5", "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/vw-3638825_1920.jpg").image(transformation=[
  {'gravity': "car:van:motorbike", 'zoom': 0.9, 'aspect_ratio': "1.5", 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("car:van:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/addons/objectdetection/vw-3638825_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/vw-3638825_1920.jpg', {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspectRatio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <Transformation gravity="car:van:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cld-transformation gravity="car:van:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cl-transformation gravity="car:van:motorbike" zoom="0.9" aspect-ratio="1.5" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("car:van:motorbike").Zoom(0.9).AspectRatio("1.5").Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/addons/objectdetection/vw-3638825_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("car:van:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("car:van:motorbike").setZoom(0.9).setAspectRatio("1.5").setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg")!, cloudinary: cloudinary)
Giving precedence to the car over the van

If there are no cars or vans present in the picture, but there is a motorbike, the motorbike will be the focus of the crop:

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/farm-1264761_1280.jpg", :transformation=>[
  {:gravity=>"car:van:motorbike", :zoom=>0.9, :aspect_ratio=>"1.5", :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/farm-1264761_1280.jpg", array("transformation"=>array(
  array("gravity"=>"car:van:motorbike", "zoom"=>0.9, "aspect_ratio"=>"1.5", "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/farm-1264761_1280.jpg").image(transformation=[
  {'gravity': "car:van:motorbike", 'zoom': 0.9, 'aspect_ratio': "1.5", 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/farm-1264761_1280.jpg", {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("car:van:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/addons/objectdetection/farm-1264761_1280.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/farm-1264761_1280.jpg', {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspectRatio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/farm-1264761_1280.jpg", {transformation: [
  {gravity: "car:van:motorbike", zoom: "0.9", aspect_ratio: "1.5", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/farm-1264761_1280.jpg" >
  <Transformation gravity="car:van:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/farm-1264761_1280.jpg" >
  <cld-transformation gravity="car:van:motorbike" zoom="0.9" aspectRatio="1.5" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/farm-1264761_1280.jpg" >
  <cl-transformation gravity="car:van:motorbike" zoom="0.9" aspect-ratio="1.5" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("car:van:motorbike").Zoom(0.9).AspectRatio("1.5").Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/addons/objectdetection/farm-1264761_1280.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("car:van:motorbike").zoom(0.9).aspectRatio("1.5").crop("crop").chain()
  .width(200).crop("scale")).generate("docs/addons/objectdetection/farm-1264761_1280.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("car:van:motorbike").setZoom(0.9).setAspectRatio("1.5").setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/addons/objectdetection/farm-1264761_1280.jpg")!, cloudinary: cloudinary)

Original image of a motorbike, offset from center Original Image cropped to the motorbike c_crop,g_car:van:motorbike

Object Categories

If you don’t care what type of vehicle is kept in the crop, specifying the category, vehicle, rather than specific objects will keep the most prominent vehicle in the crop. In this case, it’s the van that wins.

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", :transformation=>[
  {:gravity=>"vehicle", :zoom=>0.9, :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", array("transformation"=>array(
  array("gravity"=>"vehicle", "zoom"=>0.9, "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/vw-3638825_1920.jpg").image(transformation=[
  {'gravity': "vehicle", 'zoom': 0.9, 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "vehicle", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("vehicle").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/addons/objectdetection/vw-3638825_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/vw-3638825_1920.jpg', {transformation: [
  {gravity: "vehicle", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "vehicle", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <Transformation gravity="vehicle" zoom="0.9" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cld-transformation gravity="vehicle" zoom="0.9" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cl-transformation gravity="vehicle" zoom="0.9" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("vehicle").Zoom(0.9).Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/addons/objectdetection/vw-3638825_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("vehicle").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("vehicle").setZoom(0.9).setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg")!, cloudinary: cloudinary)
Crop to the most prominent vehicle

If you want to keep all vehicles in the crop then it’s as simple as adding an ‘s’ (this works for specific objects too):

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", :transformation=>[
  {:gravity=>"vehicles", :zoom=>0.9, :crop=>"crop"},
  {:width=>200, :crop=>"scale"}
  ])
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/vw-3638825_1920.jpg", array("transformation"=>array(
  array("gravity"=>"vehicles", "zoom"=>0.9, "crop"=>"crop"),
  array("width"=>200, "crop"=>"scale")
  )))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/vw-3638825_1920.jpg").image(transformation=[
  {'gravity': "vehicles", 'zoom': 0.9, 'crop': "crop"},
  {'width': 200, 'crop': "scale"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "vehicles", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .gravity("vehicles").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).imageTag("docs/addons/objectdetection/vw-3638825_1920.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/vw-3638825_1920.jpg', {transformation: [
  {gravity: "vehicles", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/vw-3638825_1920.jpg", {transformation: [
  {gravity: "vehicles", zoom: "0.9", crop: "crop"},
  {width: 200, crop: "scale"}
  ]})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <Transformation gravity="vehicles" zoom="0.9" crop="crop" />
  <Transformation width="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cld-transformation gravity="vehicles" zoom="0.9" crop="crop" />
  <cld-transformation width="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/vw-3638825_1920.jpg" >
  <cl-transformation gravity="vehicles" zoom="0.9" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Gravity("vehicles").Zoom(0.9).Crop("crop").Chain()
  .Width(200).Crop("scale")).BuildImageTag("docs/addons/objectdetection/vw-3638825_1920.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .gravity("vehicles").zoom(0.9).crop("crop").chain()
  .width(200).crop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setGravity("vehicles").setZoom(0.9).setCrop("crop").chain()
  .setWidth(200).setCrop("scale")).generate("docs/addons/objectdetection/vw-3638825_1920.jpg")!, cloudinary: cloudinary)
Keep all vehicles in the crop

Currently, the list of supported categories and objects comes from two models: Common Objects in Context (COCO) and Google's Open Images Dataset (OID). Included are a wide variety of objects, from home appliances to food, electronics to furniture, people to animals, sports balls to handbags.... The list is ever-expanding - object models enabling you to specify fashion items and parts of the body are coming soon. Additionally, in the near future, you'll be able to specify custom object models that cater specifically to your needs.

Tailor-Made For Different Experiences

We’ve seen how to fit different images into the same space, so now we’ll look at how to fit the same image into different spaces, while still keeping the desired object as the focus of attention.

An e-commerce website typically requires a handful of image crops for the same product images (thumbnails, product listing, detail view, and zoom). If you want your images to be responsive to different viewport sizes, yet more variations are required. Factor in social channels, and the number of different crops required quickly multiplies.

To ensure that in each situation, your product, be it a handbag, a shoe or a vase, remains fully in view is a huge undertaking, one which requires creative teams to manage different crops, very painstakingly, and often manually.

To help address this pain point, Cloudinary’s Object-Aware Cropping add-on automatically ensures that the object of interest, your product, is front and center for any crop, no matter which channel or device it’s being viewed on.

Let’s take a look at a product image of a handbag. Here’s the original image:

Product image of a handbag

A square crop is required for a website product detail and here we can use the fill cropping method to fill the specified dimensions. To ensure that the handbag is kept in the crop we can choose between object-based automatic gravity (g_auto:handbag) and object-specific gravity (g_handbag). Object-based automatic gravity takes the whole picture into account, weighted by the handbag, whereas object-specific gravity focuses on the handbag over anything else, so the two can give different results. In this case, automatic gravity gives a slightly better crop because more of the hand, and less of the coat on the right is shown. Compare the two:

Auto-gravity crop keeping handbag c_fill,g_auto:handbag,h_800,w_800 Object specific crop keeping the handbag c_fill,g_handbag,h_800,w_800

Thumbnail crops are another option, and work well to scale down an image to fit the dimensions specified. Here's an example for a Pinterest board crop:

Ruby:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/model-993911_1280.jpg", :gravity=>"handbag", :height=>150, :width=>222, :crop=>"thumb")
PHP:
Copy to clipboard
cl_image_tag("docs/addons/objectdetection/model-993911_1280.jpg", array("gravity"=>"handbag", "height"=>150, "width"=>222, "crop"=>"thumb"))
Python:
Copy to clipboard
CloudinaryImage("docs/addons/objectdetection/model-993911_1280.jpg").image(gravity="handbag", height=150, width=222, crop="thumb")
Node.js:
Copy to clipboard
cloudinary.image("docs/addons/objectdetection/model-993911_1280.jpg", {gravity: "handbag", height: 150, width: 222, crop: "thumb"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().gravity("handbag").height(150).width(222).crop("thumb")).imageTag("docs/addons/objectdetection/model-993911_1280.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('docs/addons/objectdetection/model-993911_1280.jpg', {gravity: "handbag", height: 150, width: 222, crop: "thumb"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("docs/addons/objectdetection/model-993911_1280.jpg", {gravity: "handbag", height: 150, width: 222, crop: "thumb"})
React:
Copy to clipboard
<Image publicId="docs/addons/objectdetection/model-993911_1280.jpg" >
  <Transformation gravity="handbag" height="150" width="222" crop="thumb" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="docs/addons/objectdetection/model-993911_1280.jpg" >
  <cld-transformation gravity="handbag" height="150" width="222" crop="thumb" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="docs/addons/objectdetection/model-993911_1280.jpg" >
  <cl-transformation gravity="handbag" height="150" width="222" crop="thumb">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Gravity("handbag").Height(150).Width(222).Crop("thumb")).BuildImageTag("docs/addons/objectdetection/model-993911_1280.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().gravity("handbag").height(150).width(222).crop("thumb")).generate("docs/addons/objectdetection/model-993911_1280.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setGravity("handbag").setHeight(150).setWidth(222).setCrop("thumb")).generate("docs/addons/objectdetection/model-993911_1280.jpg")!, cloudinary: cloudinary)
Thumbnail crop of a handbag

This video demonstrates how different cropping methods and dimensions result in various crops of the same photo, all giving priority to the handbag:

The same image, presented in many different forms - sounds like polymorphism to me!

One-To-Many Resizing

In addition to those already mentioned, Cloudinary offers many other types of resizing and cropping methods that you may want to use. To get a feel for how they behave, try out the interactive demo below. Be aware that not all combinations of cropping and gravity are valid, for example, gravity can't be used together with 'scale', or any of the 'fit' or 'pad' options (except 'fill with padding'), and 'fill with padding' only works with auto-gravity options. The demo lets you choose from two sizes of each image to show how some modes can give different results depending on the resolution.

Choose your starting image, viewport dimensions, cropping mode and gravity, then click the button to generate the new image.

Original image size: 640 x 427

Large
Small
Large
Small

Viewport width (100 to 650 pixels): 300

Viewport height (100 to 650 pixels): 300

Finalization

Remember that Cloudinary supports a wide range of programming languages and frameworks, so have a go and see how easy it is to implement these cropping methods in your preferred environment. To use object-aware cropping, you’ll need to subscribe to the Cloudinary Object-Aware Cropping add-on (there's a free tier you can use for experimenting), and also bear in mind that unless you’ve allowed unsigned add-on transformations in your account security settings, you’ll need to sign your delivery URLs. Find out more about the add-on and signing URLs in our documentation.

If you're new to Cloudinary, you might also want to check out the many other image and video transformations that we support, providing more great ways to automate your media delivery and make your website or app first class!

Recent Blog Posts

Image-Editing Basics and a Tutorial for Automation With AI

You likely find yourself continually editing images for enhancement by eliminating flaws and tweaking the overall presentation, typically with software tools. Examples of basic editing are straightening, cleaning, and cropping images, as well as adjusting the contrast, exposure, and white balance. With advanced software like Cloudinary, you can automate not only editing tasks, such as quality adjustment and encoding, but also delivery.

Read more
Tips for Retaining Audience Through Engaging Videos

Measuring the level of interest your videos generate helps you produce compelling content. The measurement and optimization approach must, however, address the various aspects of each video, including the A/B test hypothesis and iterations. A high engagement rate spells effective videos; a low engagement rate calls for content improvement.

Read more
Forbes Cloud 100: When the Stars Align

In 2017, when Cloudinary first made the Forbes Cloud 100 as a ‘Rising Star,’ it was an incredibly proud moment for the company. In 2018 we graduated from Rising Star status to be acknowledged as part of the incredible Cloud 100, the top 100 SaaS companies in the world. Today marks our third consecutive year on this prestigious list.

Read more
A Cloudinary-Enhanced Student-ID App

I’m an instructional designer on Cloudinary’s Solutions and Training team. As the COVID-19 pandemic emerged in March, like other global organizations, we pivoted to set up virtual courses. As much as we looked forward to resuming in-person classes in the future, we switched gear to focus on the virtual way of learning.

Read more
Image Formats: Getting it Right

Image formats, which are standards for digital images, can be uncompressed, compressed, raster based, or vector based. You determine the DNA of your images with the formats you adopt, each of which offering different capabilities. For example, rasters generate images with pixels; vectors, with vectors or proportional formulas. PNGs can display logos without background; JPEGs always come with backgrounds. This article explains the main properties of the various image formats, including their basic concepts and pros and cons.

Read more