Skip to content

Commit

Permalink
Adding a Image moderation sample.
Browse files Browse the repository at this point in the history
Change-Id: I78235817ff6dadbd9408ed6a1988c59f2aa20c93
  • Loading branch information
Nicolas Garnier committed Nov 16, 2016
1 parent 4b34e68 commit c6bad2c
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 1 deletion.
8 changes: 7 additions & 1 deletion README.md
Expand Up @@ -30,7 +30,13 @@ Demonstrates how to automatically convert images that are uploaded to Firebase S

Uses a Firebase Storage trigger.

### [Extract Image MEtadata](/exif-images)
### [Automatically Moderate Images](/convert-images)

Demonstrates how to automatically moderate offensive images that are uploaded to Firebase Storage by using the Google Cloud API to detect offensive images and ImageMagick to blur these images.

Uses a Firebase Storage trigger.

### [Extract Image Metadata](/exif-images)

Demonstrates how to automatically extract image's metadata using ImageMagick for images that are uploaded to Firebase Storage.

Expand Down
36 changes: 36 additions & 0 deletions moderate-images/README.md
@@ -0,0 +1,36 @@
# Automatically Moderate Images

This sample demonstrates how to automatically moderate offensive images uploaded to Firebase Storage. It uses The Google Cloud Vision API to detect if the image contains adult or violent content and if so uses ImageMagick to blur the image.


## Functions Code

See file [functions/index.js](functions/index.js) for the moderation code.

The detection of adult and violent content in an image is done using The [Google Cloud Vision API](https://cloud.google.com/vision/).
The image blurring is performed using ImageMagick which is installed by default on all Firebase Functions instances. The image is first downloaded locally from the Firebase Storage bucket to the `tmp` folder using the [google-cloud](https://github.com/GoogleCloudPlatform/google-cloud-node) SDK.

The dependencies are listed in [functions/package.json](functions/package.json).


## Trigger rules

The function triggers on upload of any file to the Firebase Functions bucket.


## Setting up the sample

Create a Firebase project on the [Firebase Console](https://console.firebase.google.com).
Enable Billing on your project by switching to the Blaze or Candle plan then visit the **Storage** tab.

Replace the placeholder `FIREBASE_STORAGE_BUCKET_NAME` with the name of the Firebase Storage bucket which can be found in the **Storage** tab of your Firebase project's console. It is typically of the form `<project-id>.appspot.com`.

In your [Google Cloud Console](https://console.cloud.google.com/apis/api/vision.googleapis.com/overview?project=_) enable the **Google Cloud Vision API**.


## Deploy and test

To test the sample:

- Deploy your project using `firebase deploy`
- Go to the Firebase Console **Storage** tab and upload an image that contains adult or violent content. After a short time the image will be replaced by a blurred version of itself.
1 change: 1 addition & 0 deletions moderate-images/firebase.json
@@ -0,0 +1 @@
{}
81 changes: 81 additions & 0 deletions moderate-images/functions/index.js
@@ -0,0 +1,81 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for t`he specific language governing permissions and
* limitations under the License.
*/
'use strict';

const functions = require('firebase-functions');
const mkdirp = require('mkdirp-promise');
const gcs = require('@google-cloud/storage')();
const vision = require('@google-cloud/vision')();
const exec = require('child-process-promise').exec;
// TODO(DEVELOPER): Replace the placeholder below with the name of the Firebase Storage bucket.
const FIREBASE_STORAGE_BUCKET_NAME = 'FIREBASE_STORAGE_BUCKET_NAME';
const LOCAL_TMP_FOLDER = '/tmp';

/**
* When an image is uploaded we check if it is flagged as Adult or Violence by the Cloud Vision
* API and if it is we blur it using ImageMagick.
*/
exports.blurOffensiveImages = functions.cloud.storage(FIREBASE_STORAGE_BUCKET_NAME).onChange(event => {
const file = gcs.bucket(event.data.bucket).file(event.data.name);

// Exit if this is a move or deletion event.
if (event.data.resourceState === 'not_exists') {
return console.log('This is a deletion event.');
}

// Check the image content using the Cloud Vision API.
return vision.detectSafeSearch(file).then(data => {
const safeSearch = data[0];
console.log('SafeSearch results on image', safeSearch);

if (safeSearch.adult || safeSearch.violence) {
return blurImage(event.data.name, event.data.bucket, event.data.metadata);
}
});
});

/**
* Blurs the given image located in the given bucket using ImageMagick.
*/
function blurImage(filePath, bucketName, metadata) {
const filePathSplit = filePath.split('/');
filePathSplit.pop();
const fileDir = filePathSplit.join('/');
const tempLocalDir = `${LOCAL_TMP_FOLDER}/${fileDir}`;
const tempLocalFile = `${LOCAL_TMP_FOLDER}/${filePath}`;

// Create the temp directory where the storage file will be downloaded.
return mkdirp(tempLocalDir).then(() => {
// Download file from bucket.
const bucket = gcs.bucket(bucketName);
return bucket.file(filePath).download({
destination: tempLocalFile
}).then(() => {
console.log('The file has been downloaded to', tempLocalFile);
// Blur the image using ImageMagick.
return exec(`convert ${tempLocalFile} -channel RGBA -blur 0x8 ${tempLocalFile}`).then(() => {
console.log('Blurred image created at', tempLocalFile);
// Uploading the Blurred image.
return bucket.upload(tempLocalFile, {
destination: filePath,
metadata: {metadata: metadata} // Keeping custom metadata.
}).then(() => {
console.log('Blurred image uploaded to Storage at', filePath);
});
});
});
});
}
13 changes: 13 additions & 0 deletions moderate-images/functions/package.json
@@ -0,0 +1,13 @@
{
"name": "moderate-image-function",
"description": "Offensive Image blurring using Firebase Function.",
"dependencies": {
"@google-cloud/storage": "^0.4.0",
"@google-cloud/vision": "^0.5.0",
"child-process-promise": "^2.2.0",
"firebase": "^3.6.0",
"firebase-functions": "https://storage.googleapis.com/firebase-preview-drop/node/firebase-functions/firebase-functions-preview.latest.tar.gz",
"mkdirp": "^0.5.1",
"mkdirp-promise": "^4.0.0"
}
}

0 comments on commit c6bad2c

Please sign in to comment.