summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md8
-rw-r--r--check/app/models/sql_factory.py11
-rw-r--r--check/app/server/api.py65
-rwxr-xr-xcheck/static/assets/css.css8
-rw-r--r--client/app.js20
5 files changed, 79 insertions, 33 deletions
diff --git a/README.md b/README.md
index 388dc5d..e95635f 100644
--- a/README.md
+++ b/README.md
@@ -41,8 +41,6 @@ Options:
- `threshold` (default: 6) - Minimum similarity threshold. This is the Hamming distance used for phash comparisons.
- `add` (default: true) - Pass `false` if you do not want the image added to the database.
-
-#### POST /v1/similar
-
-- `limit` (default: 10) - Number of results to return.
-
+- `limit` (default: 1) - Number of results to return.
+- `url` - Image URL to fetch and test (will be stored if `add` is true)
+- `q` (file) - Uploaded file to test (will not be stored) \ No newline at end of file
diff --git a/check/app/models/sql_factory.py b/check/app/models/sql_factory.py
index 68c2e30..5433b67 100644
--- a/check/app/models/sql_factory.py
+++ b/check/app/models/sql_factory.py
@@ -32,7 +32,8 @@ class FileTable(Base):
__tablename__ = 'files'
id = Column(Integer, primary_key=True)
sha256 = Column(String(64, convert_unicode=True), nullable=False)
- phash = Column(BigInteger, nullable=False)
+ url = Column(String(255, convert_unicode=True), nullable=False)
+ phash = Column(BigInteger, nullable=False, index=True)
ext = Column(String(4, convert_unicode=True), nullable=False)
def toJSON(self):
return {
@@ -64,11 +65,9 @@ def search_by_hash(hash):
match = session.query(FileTable).filter(FileTable.sha256 == hash)
return match.first()
-def add_phash(sha256, phash, ext):
+def add_phash(sha256, phash, ext, url):
"""Add a file to the table"""
- rec = FileTable(
- sha256=sha256, phash=phash, ext=ext,
- )
+ rec = FileTable(sha256=sha256, phash=phash, ext=ext, url=url)
session = Session()
session.add(rec)
session.commit()
@@ -93,4 +92,4 @@ def add_phash_by_filename(path):
hash = sha256(path)
- add_phash(sha256=hash, phash=phash, ext=ext)
+ add_phash(sha256=hash, phash=phash, ext=ext, url=path)
diff --git a/check/app/server/api.py b/check/app/server/api.py
index c4878c5..3742b15 100644
--- a/check/app/server/api.py
+++ b/check/app/server/api.py
@@ -1,8 +1,10 @@
+import io
import os
import re
import time
import numpy as np
import logging
+import urllib.request
from flask import Blueprint, request, jsonify
from PIL import Image
@@ -31,25 +33,6 @@ def match():
"""
start = time.time()
- file = request.files['q']
- fn = file.filename
- if fn.endswith('blob'): # FIX PNG IMAGES?
- logging.debug('received a blob, assuming JPEG')
- fn = 'filename.jpg'
-
- basename, ext = os.path.splitext(fn)
- if ext.lower() not in valid_exts:
- return jsonify({
- 'success': False,
- 'match': False,
- 'error': 'not_an_image'
- })
-
- ext = ext[1:].lower()
-
- im = Image.open(file.stream).convert('RGB')
- phash = compute_phash_int(im)
-
try:
threshold = int(request.args.get('threshold') or 6)
limit = int(request.args.get('limit') or 1)
@@ -61,12 +44,52 @@ def match():
'error': 'param_error'
})
+ if 'q' in request.files:
+ file = request.files['q']
+ fn = file.filename
+ if fn.endswith('blob'): # FIX PNG IMAGES?
+ logging.debug('received a blob, assuming JPEG')
+ fn = 'filename.jpg'
+
+ basename, ext = os.path.splitext(fn)
+ if ext.lower() not in valid_exts:
+ return jsonify({
+ 'success': False,
+ 'match': False,
+ 'error': 'not_an_image'
+ })
+
+ im = Image.open(file.stream).convert('RGB')
+ else:
+ url = request.args.get('url')
+ if not url:
+ return jsonify({
+ 'success': False,
+ 'match': False,
+ 'error': 'no_image'
+ })
+ basename, ext = os.path.splitext(url)
+ if ext.lower() not in valid_exts:
+ return jsonify({
+ 'success': False,
+ 'match': False,
+ 'error': 'not_an_image'
+ })
+
+ remote_request = urllib.request.Request(url)
+ remote_response = urllib.request.urlopen(remote_request)
+ raw = remote_response.read()
+ im = Image.open(io.BytesIO(raw)).convert('RGB')
+
+ phash = compute_phash_int(im)
+ ext = ext[1:].lower()
+
results = search_by_phash(phash=phash, threshold=threshold, limit=limit)
if len(results) == 0:
- if add:
+ if add and url:
hash = sha256_stream(file)
- add_phash(sha256=hash, phash=phash, ext=ext)
+ add_phash(sha256=hash, phash=phash, ext=ext, url=url)
match = False
else:
match = True
diff --git a/check/static/assets/css.css b/check/static/assets/css.css
index 63cede7..3f05bd9 100755
--- a/check/static/assets/css.css
+++ b/check/static/assets/css.css
@@ -345,4 +345,12 @@ td.result_txt ul li{
}
.results {
margin: 10px 0;
+}
+.query label {
+ display: flex;
+ flex-direction: row;
+}
+.query label span {
+ display: inline-block;
+ width: 100px;
} \ No newline at end of file
diff --git a/client/app.js b/client/app.js
index ba77be6..cadafef 100644
--- a/client/app.js
+++ b/client/app.js
@@ -32,6 +32,11 @@ export default class PhashApp extends Component {
})
}
+ submit() {
+ const { url } = this.state
+ if (!url || url.indexOf('http') !== 0) return
+ }
+
render() {
return (
<div className='app'>
@@ -52,7 +57,20 @@ export default class PhashApp extends Component {
}
return (
<div className='query'>
- <UploadImage onUpload={this.upload.bind(this)} />
+ <label>
+ <span>Upload image</span>
+ <UploadImage onUpload={this.upload.bind(this)} />
+ </label>
+ <label>
+ <span>Enter URL</span>
+ <input
+ type='text'
+ value={this.state.url}
+ onChange={e => this.setState({ url: e.target.value })}
+ onKeyDown={e => e.keyCode === 13 && this.submit()}
+ placeholder='https://'
+ />
+ </label>
{image && <div style={style} />}
</div>
)