Analysis on upload

When uploading assets to your Cloudinary account, you can request different types of analysis to be performed on the assets. In addition to the functionality detailed below, Cloudinary has a number of add-ons that enable various types of analysis.

Image quality analysis

You may want to determine the quality of images being uploaded to your account, particularly for user generated content. If you set the quality_analysis parameter to true when uploading an image, a quality analysis focus score between 0.0 and 1.0 is returned indicating the quality of focus in the image. A score of 0.0 means the image is blurry and out of focus and 1.0 means the image is sharp and in focus.

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("user_photo.jpg", 
  :quality_analysis => true)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("user_photo.jpg",
  array( "quality_analysis" => TRUE ));
Python:
Copy to clipboard
cloudinary.uploader.upload("user_photo.jpg",
  quality_analysis = 1)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("user_photo.jpg",
  { quality_analysis: true },
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("user_photo.jpg", 
  Cloudinary.asMap("quality_analysis", true));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"user_photo.jpg"),
  QualityAnalysis = true};
var uploadResult = cloudinary.Upload(uploadParams);

Sample response:

Copy to clipboard
{
  "public_id": "f5lq8lfq8pfj0xmd9dak",
  "version": 1579789579,
  "signature": "db9c44fd6d579e60360adecbbf1a5584153c984e",
  "width": 1920,
  "height": 1281,
  "format": "jpg",
  "resource_type": "image",
  "created_at": "2020-01-23T14:26:19Z",
  "tags": [],
  "pages": 1,
  "bytes": 310479,
  "type": "upload",
  "etag": "a8f8236455d352b8cee6aba0e3fbc87e",
  "placeholder": false,
  "url": "http://res.cloudinary.com/demo/image/upload/v1579789579/f5lq8lfq8pfj0xmd9dak.jpg",
  "secure_url": "https://res.cloudinary.com/demo/image/upload/v1579789579/f5lq8lfq8pfj0xmd9dak.jpg",
  "access_mode": "public",
  "quality_analysis": {
    "focus": 0.7031299471855164
  },
  "original_filename": "user_photo"
}

Extended quality analysis

A more detailed quality analysis of uploaded images is available through extended quality analysis.

Important
Extended quality analysis is currently in Beta. Some implementation details may change before the official release. If you have a paid account, you can request to take part in the Beta trial. We invite you to share any feedback via our support team.

With extended quality analysis activated, the response to an upload or explicit request with quality_analysis set to true includes scores for different quality factors in addition to the normally available focus related score. An overall weighted quality score is also included:

Copy to clipboard
  "quality_analysis": {
    "jpeg_quality": 0.76,
    "jpeg_chroma": 0.25,
    "focus": 0.16,
    "noise": 1.0,
    "contrast": 0.85,
    "exposure": 0.97,
    "saturation": 1.0,
    "lighting": 1.0,
    "pixel_score": 0.27,
    "color_score": 0.91,
    "dct": 0.29,
    "blockiness": 1.0,
    "chroma_subsampling": 0.06,
    "resolution": 0.08
  },
  "quality_score": 0.47,
  • Scores vary from 0.0 (worst) to 1.0 (best).
  • For multi-page images, only the first page is evaluated.
  • "jpeg_*" scores are only present for JPEG originals.
  • JPEG quality is considered best (1.0) if chroma is present for all pixels (no chroma subsampling).
  • Estimation of compression artifacts (DCT, blockiness and chroma subsampling) is not done for images above 10 MP
  • Resolution gives preference to HD (1920 x 1080) and above.
  • "pixel_score" is a measure of how the image looks in terms of compression artifacts (blockiness, ringing etc.) and in terms of capture quality (focus and sensor noise). Downscaling can improve the perceived visual quality of an image with a poor pixel score.
  • "color_score" takes into account factors such as exposure, white balance, contrast and saturation. Downscaling makes no difference to the perceived color quality.

The quality_score field can be used in the Search API when quality_analysis is set to true in the upload request or an upload preset.

Semantic data extraction

When you upload an asset to Cloudinary, the upload API response includes basic information about the uploaded image such as width, height, number of bytes, format, and more. By default, the following semantic data is automatically included in the upload response as well: ETag, any face or custom coordinates, and the number of pages (or layers) in "paged" files.

Cloudinary supports extracting additional semantic data from the uploaded image such as: image metadata (including Exif, IPTC, XMP and GPS), color histogram, predominant colors, custom coordinates, pHash image fingerprint, ETag, and face and/or text coordinates. You request the inclusion of this additional information in the upload response by including one or more optional parameters.

The following example uploads an image and requests the pHash value, a color analysis, the image metadata and quality analysis:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("couple.jpg",  
  :colors => true,  
  :phash => true,  
  :image_metadata => true,  
  :quality_analysis => true)
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("couple.jpg", 
  array( 
    "colors" => TRUE,
    "phash" => TRUE,
    "image_metadata" => TRUE
    "quality_analysis" => TRUE));
Python:
Copy to clipboard
cloudinary.uploader.upload("couple.jpg", 
  colors = True,
  phash = True,
  image_metadata = True,
  quality_analysis = True)
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("couple.jpg", 
  { colors: true,
    phash: true,
    image_metadata: true 
    quality_analysis: true }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("couple.jpg", 
  ObjectUtils.asMap(
    "colors", true,
    "phash", true,
    "image_metadata", true
    "quality_analysis", true));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"couple.jpg"),
  Colors = true,
  Phash = true,
  Metadata = true
  QualityAnalysis = true};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setColors(true)
  .setPhash(true)
  .setImageMetadata(true)
  .setQualityAnalysis(true)
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "couple.jpg", params: params)

The following is an example of a JSON response returned with the following additional information: image_metadata, colors, phash and quality_analysis:

Copy to clipboard
{
  "public_id": "couple",
  "version": 1436702762,
  "signature": "1cc5524ae9acde77c458a434e32f6d26a8d4b55c",
  "width": 400,
  "height": 300,
  "format": "jpg",
  "resource_type": "image",
  "created_at": "2017-07-12T12:06:02Z",
  "tags": [],
  "bytes": 206960,
  "type": "upload",
  "etag": "9359a0f3ec878d32e06a456c4224b52b",
  "url": "http://res.cloudinary.com/demo/image/upload/v1436702762/couple.jpg",
  "secure_url": "https://res.cloudinary.com/demo/image/upload/v1436702762/couple.jpg",
  "image_metadata": {
    "PerspectiveHorizontal": "0",
    "RedHue": "0",
    "Exposure": "0.00",
    ...
    ...
    ...
    "ExposureTime": "1/320"
  },
  "illustration_score": 0.9,
  "colors": [
    ["#152E02", 7.9], ["#2E4F06", 6.3], ["#3A6604", 5.6], ["#EEF2F3", 5.2], ["#598504", 4.6], ["#0D1903", 4.6], ["#DCDFDB", 4.4], ["#7AA403", 3.9], ["#DBE98A", 3.8], ["#4C7208", 3.5], ["#8DAC30", 3.3], ["#6C9406", 3.2], ["#6E912F", 3.2], ["#B0C95F", 3.1], ["#89AF07", 3.1], ["#9E744E", 2.9], ["#CD9A6F", 2.8], ["#D8B395", 2.5], ["#719357", 2.4], ["#ACCDBC", 2.3], ["#8E6437", 2.3], ["#E2E0A0", 2.3], ["#2C4B16", 2.3], ["#656950", 2.1], ["#25370A", 2.0], ["#73A092", 1.9], ["#4E3721", 1.6], ["#A0AD9A", 1.6], ["#BBD258", 1.5], ["#5B602B", 1.3], ["#302B1D", 1.3], ["#9CA25C", 1.2]
  ], 
  "predominant": {
    "google": [
      ["green", 65.3], 
      ["white", 11.4], 
      ["brown", 6.6], 
      ["yellow", 5.9], 
      ["orange", 5.5], 
      ["gray", 0.5]], 
    "cloudinary":[
      ["olive", 39.4], 
      ["green", 25.1], 
      ["white", 11.4], 
      ["yellow", 5.9], 
      ["orange", 5.5], 
      ["brown", 5.2], 
      ["lime", 2.2], 
      ["gray", 0.5]
    ]
  },
  "phash": "ebb822db6d10f1e",
  "coordinates": {
    "custom": [[80, 140, 220, 111]],
    "faces": [[98, 74, 61, 83], [139, 130, 52, 71]]    
  },
  "quality_analysis": {
    "focus": 0.8
  },
  "original_filename": "couple"
}

You can ask Cloudinary for semantic data either during the upload API call for newly uploaded images as shown above, or using our Admin API for previously uploaded images (see Cloudinary's Admin API documentation for more details).

See the blog post on API for extracting semantic image data - colors, faces, Exif data and more for more information on semantic data extraction.

Moderation of uploaded assets

It’s sometimes important to moderate assets uploaded to Cloudinary: you might want to keep out inappropriate or offensive content, reject assets that do not answer your website’s needs (e.g., making sure there are visible faces in profile images), or make sure that photos are of high enough quality before making them available on your website. Whether using the server-side upload API call, or when allowing users to upload the assets directly from their browser, you can mark an asset for moderation by adding the moderation parameter to the upload call. The parameter can be set to either:

For example, to mark an image for manual moderation:

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("user_photo.jpg", 
  :moderation => 'manual')
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("user_photo.jpg",
  array( "moderation" => "manual" ));
Python:
Copy to clipboard
cloudinary.uploader.upload("user_photo.jpg",
  moderation = 'manual')
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("user_photo.jpg",
  { moderation: 'manual' },
  function(error, result) { console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("user_photo.jpg", 
  Cloudinary.asMap("moderation", "manual"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"user_photo.jpg"),
  Moderation = "manual"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setModeration(.manual)
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "user_photo.jpg", params: params)

Images that are uploaded to Cloudinary, and tagged for manual moderation, can be viewed by moderators using the Moderation option in the left navigation menu of the Media Library. Moderators can browse recently uploaded images and decide to accept or reject them.

Queue of pending images

You can also add a notification_url parameter while uploading the image, which instructs Cloudinary to notify your application of changes to moderation status, with the details of the moderation event (approval or rejection).

Ruby:
Copy to clipboard
Cloudinary::Uploader.upload("sample.jpg",
  :moderation => "manual",
  :notification_url => "https://mysite.example.com/mod_endpoint")
PHP:
Copy to clipboard
\Cloudinary\Uploader::upload("sample.jpg", 
  array( 
    "moderation" => "manual",
    "notification_url" => "https://mysite.example.com/mod_endpoint"));
Python:
Copy to clipboard
cloudinary.uploader.upload("sample.jpg", 
  moderation = "manual",
  notification_url = "https://mysite.example.com/mod_endpoint")
Node.js:
Copy to clipboard
cloudinary.v2.uploader.upload("sample.jpg", 
  { moderation: "manual",
    notification_url: "https://mysite.example.com/mod_endpoint" }, 
  function(error, result) {console.log(result, error); });
Java:
Copy to clipboard
cloudinary.uploader().upload("sample.jpg", 
  ObjectUtils.asMap(
    "moderation", "manual",
    "notification_url", "https://mysite.example.com/mod_endpoint"));
.Net:
Copy to clipboard
var uploadParams = new ImageUploadParams(){
  File = new FileDescription(@"sample.jpg"),
  Moderation = "manual",
  NotificationUrl = "https://mysite.example.com/mod_endpoint"};
var uploadResult = cloudinary.Upload(uploadParams);
iOS:
Copy to clipboard
let params = CLDUploadRequestParams()
  .setModeration(.manual)
  .setNotificationUrl("https://mysite.example.com/mod_endpoint")
var mySig = MyFunction(params)  // your own function that returns a signature generated on your backend
params.setSignature(CLDSignature(signature: mySig.signature, timestamp: mySig.timestamp))
let request = cloudinary.createUploader().signedUpload(
  url: "sample.jpg", params: params)

Furthermore, if an image is rejected, you can use Cloudinary’s default image mechanism to display a placeholder image instead using the default_image parameter (d for URLs) when delivering the image. See the Using default image placeholders documentation for more details.

See the blog post on Image moderation made easy using cloud-based UI and API for more information on manual moderation.

✔️ Feedback sent!