Skip to content

Commit 71c1182

Browse files
author
agrandiere
committed
version 1.0
1 parent 0eb5c1c commit 71c1182

File tree

11 files changed

+248
-82
lines changed

11 files changed

+248
-82
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
sightengine/*.pyc
2+
3+
*.pyc

README.MD

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,89 @@
1-
Sightengine Python Client
2-
===============
31

4-
Nudity detection and moderation - Python library to connect to the Sightengine API
2+
# About
53

6-
About
7-
-----
4+
Use the Sightengine Moderation API to instantly moderate images and videos. See http://sightengine.com for more information.
85

9-
Use the Sightengine nudity API to instantly moderate adult content in user-submitted photos. See http://sightengine.com for more information.
6+
Before starting, please make sure you have created an account on https://sightengine.com
107

8+
# Initialize the client
119

12-
Instructions
13-
------
10+
You will need your API USER and API SECRET to initialize the client. You can find both of them on your Sightengine account.
11+
```python
12+
from sightengine.client import SightengineClient
13+
client = SightengineClient("YOUR_API_USER", "YOUR_API_SECRET")
14+
```
1415

15-
1. Create an account on http://sightengine.com, you will get your own API_USER and API_SECRET values
16-
2. Import the Sightengine package and use the below examples to start using the API
16+
# Moderate an image
1717

18+
The API accepts both standard still images: JPEG, PNG, WEBP etc. and multi-frame GIF images.
1819

19-
Examples
20-
--------
20+
Several moderation engines are available for you to choose from (nudity detection, inappropriate content detection etc...). Please refer to the documentation for more.
2121

22-
Import and create the SightengineClient object
22+
## Moderate an image through a public URL:
2323

24-
from sightengine import client
25-
sightengine_client = client.SightengineClient("YOUR_API_USER", "YOUR_API_SECRET")
24+
```python
25+
# Detect nudity in an image
26+
output = client.check('nudity').image('http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg')
2627

27-
Moderate an image accessible through a public URL:
28+
# Detect nudity, weapons, alcohol, drugs and faces in an image, along with image properties and type
29+
output = client.check('nudity, type, properties, wad, face').image('http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg')
30+
```
2831

29-
output = sightengine_client.check_nudity("http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg")
30-
print output
32+
## Moderate a local image:
33+
```python
34+
# Detect nudity in an image
35+
output = client.check('nudity').image('/full/path/to/image.jpg')
3136

37+
# Detect nudity, weapons, alcohol, drugs and faces in an image, along with image properties and type
38+
output = client.check('nudity, type, properties, wad, face').image('/full/path/to/image.jpg')
39+
```
3240

33-
Moderate a local image:
41+
# Video and Stream Moderation
42+
The first step to detect nudity in a video stream is to submit the video stream to the API.
3443

35-
output = sightengine_client.check_nudity("/full/path/to/image.jpg")
36-
print output
44+
```python
45+
client.check('nudity').video('http://www.quirksmode.org/html5/videos/big_buck_bunny.webm', 'https://example.com/yourcallback')
46+
```
47+
48+
# Feedback
49+
In order to report a misclassification, you need to report the image that was misclassified, the model that was run on this image (models are nudity, face, type, wad), and the correct class of the image.
50+
51+
For each model, there are different classes that you may report. Here are the details:
52+
53+
The nudity model has 3 classes:
54+
* raw: corresponding to raw nudity
55+
* partial: corresponding to partial nudity
56+
* safe: corresponding to no nudity
57+
58+
The face model has 3 classes:
59+
* none
60+
* single
61+
* multiple
62+
63+
The type model has 2 classes:
64+
* photo
65+
* illustration
66+
67+
The wad model has 3 classes:
68+
* no-weapons
69+
* weapons
70+
* no-alcohol
71+
* alcohol
72+
* no-drugs
73+
* drugs
74+
75+
```python
76+
client.feedback(model, class,image)
77+
```
78+
Example of feedback on a local image:
79+
```python
80+
client.feedback("nudity","safe", "/full/path/to/image.jpg")
81+
client.feedback("type","illustration", "/full/path/to/image.jpg")
82+
client.feedback("nudity","raw", "/full/path/to/image.jpg")
83+
```
84+
Example of feedback through a public URL::
85+
```python
86+
client.feedback("nudity","safe", "http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg")
87+
client.feedback("type","illustration", "http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg")
88+
client.feedback("nudity","raw", "http://img09.deviantart.net/2bd0/i/2009/276/c/9/magic_forrest_wallpaper_by_goergen.jpg")
89+
```

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1.0

example.py

Lines changed: 0 additions & 12 deletions
This file was deleted.

examples/all.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from sightengine.client import SightengineClient
2+
3+
client = SightengineClient('API user', 'API secret')
4+
5+
####### check image
6+
7+
checkAll = client.check('nudity', 'wad', 'properties', 'face', 'type')
8+
9+
output = checkAll.image('/path/to/local/file.jpg')
10+
output2 = checkAll.image('https://d3m9459r9kwism.cloudfront.net/img/examples/example7.jpg')
11+
12+
print(output)
13+
print(output2)

examples/nudity.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from sightengine.client import SightengineClient
2+
3+
client = SightengineClient('API user', 'API secret')
4+
5+
##### feedback
6+
7+
feedback1 = client.feedback('nudity', 'raw', 'https://d3m9459r9kwism.cloudfront.net/img/examples/example5.jpg')
8+
feedback2 = client.feedback('nudity','safe', '/path/to/local/file.jpg')
9+
10+
print(feedback1)
11+
print(feedback2)
12+
13+
####### check image
14+
15+
checkNudity = client.check('nudity')
16+
17+
output = checkNudity.image('/path/to/local/file.jpg')
18+
output2 = checkNudity.image('https://d3m9459r9kwism.cloudfront.net/img/examples/example5.jpg')
19+
20+
print(output)
21+
print(output2)
22+
23+
####### check video
24+
25+
checkNudity = client.check('nudity')
26+
checkNudity.video('http://www.quirksmode.org/html5/videos/big_buck_bunny.webm', 'http://requestb.in/1nm1vw11')

license.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Grandiere Antoine
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

setup.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from distutils.core import setup
2+
import os
3+
4+
version_file = open(os.path.join(os.path.dirname(__file__), 'VERSION'))
5+
VERSION = version_file.read().strip()
6+
7+
setup(
8+
name = 'Sightengine Python Client',
9+
packages = ['sightengine'],
10+
version = VERSION,
11+
description = 'Sightengine Python client',
12+
author = 'Sightengine',
13+
url = 'https://github.com/Sightengine/client-python'
14+
)

sightengine/__init__.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +0,0 @@
1-
# -*- coding: utf-8 -*-
2-
"""
3-
Copyright (c) 2015 Sightengine
4-
http://www.sightengine.com/
5-
Permission is hereby granted, free of charge, to any person obtaining a copy
6-
of this software and associated documentation files (the "Software"), to deal
7-
in the Software without restriction, including without limitation the rights
8-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9-
copies of the Software, and to permit persons to whom the Software is
10-
furnished to do so, subject to the following conditions:
11-
The above copyright notice and this permission notice shall be included in
12-
all copies or substantial portions of the Software.
13-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-
THE SOFTWARE.
20-
"""

sightengine/check.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Copyright (c) 2017 Sightengine
4+
http://sightengine.com/
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
20+
"""
21+
22+
import requests, json
23+
24+
class Check(object):
25+
def __init__(self, api_user, api_secret, *args):
26+
self.api_user = api_user
27+
self.api_secret = api_secret
28+
self.endpoint = 'https://api.sightengine.com/'
29+
self.modelsType = ''
30+
31+
if len(args) > 1:
32+
for arg in args:
33+
print(arg)
34+
self.modelsType += arg + ','
35+
self.modelsType = self.modelsType[:-1]
36+
else:
37+
self.modelsType = args[0]
38+
39+
def image(self, image):
40+
numberOfModels = self.modelsType.count(",")
41+
42+
if numberOfModels > 0:
43+
if image.lower().startswith(('http://', 'https://')):
44+
url = self.endpoint + '1.0/check.json'
45+
r = requests.get(url, params={'models': self.modelsType, 'url': image, 'api_user': self.api_user, 'api_secret': self.api_secret})
46+
else:
47+
url = self.endpoint + '1.0/check.json'
48+
r = requests.post(url, files={'media': open(image, 'rb')}, data={'models': self.modelsType,'api_user': self.api_user, 'api_secret': self.api_secret})
49+
50+
output = json.loads(r.text)
51+
return output
52+
else:
53+
if image.lower().startswith(('http://', 'https://')):
54+
url = self.endpoint + '1.0' + '/' + self.modelsType + '.json'
55+
r = requests.get(url, params={'url': image, 'api_user': self.api_user, 'api_secret': self.api_secret})
56+
else:
57+
url = self.endpoint + '1.0' + '/' + self.modelsType + '.json'
58+
r = requests.post(url, files={'media': open(image, 'rb')}, data={'api_user': self.api_user,'api_secret': self.api_secret})
59+
60+
output = json.loads(r.text)
61+
return output
62+
63+
def video(self, videoUrl, callbackUrl):
64+
url = self.endpoint + '1.0/video/moderation.json?stream_url=' + videoUrl + '&callback_url=' + callbackUrl + '&api_user=' + self.api_user + '&api_secret=' + self.api_secret
65+
r = requests.get(url)
66+
67+
output = json.loads(r.text)
68+
return output
69+
70+
71+
72+
73+
74+
75+

0 commit comments

Comments
 (0)