Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
254,367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,15 @@ | |||
*.pyc | |||
.DS_Store | |||
*.swp | |||
dist/ | |||
*.egg-info | |||
.project | |||
.pydevprojectthumbor/tests/visual_test/img | |||
.coverage | |||
tests/visual_test/img/ | |||
*.swo | |||
*.swm | |||
*.swn | |||
tests/visual_test/build | |||
build | |||
*.so |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
__version__ = '0.1.0' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,13 @@ | |||
import bson | |||
|
|||
from remotecv.image_processor import ImageProcessor | |||
|
|||
class RemoteCvApp: | |||
|
|||
def __init__(self): | |||
self.processor = ImageProcessor() | |||
|
|||
def process_request(self, msg): | |||
msg = bson.loads(msg) | |||
points = self.processor.detect(msg['type'], msg['size'], msg['mode'], msg['image']) | |||
return bson.dumps({ 'points': points }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,80 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
|
|||
# thumbor imaging service | |||
# https://github.com/globocom/thumbor/wiki | |||
|
|||
# Licensed under the MIT license: | |||
# http://www.opensource.org/licenses/mit-license | |||
# Copyright (c) 2011 globo.com timehome@corp.globo.com | |||
|
|||
from os.path import join, dirname, abspath, isabs | |||
|
|||
import cv | |||
|
|||
class BaseDetector(object): | |||
|
|||
def detect(self, context): | |||
raise NotImplementedError() | |||
|
|||
|
|||
class CascadeLoaderDetector(BaseDetector): | |||
|
|||
def load_cascade_file(self, module_path, cascade_file_path): | |||
if not hasattr(self.__class__, 'cascade'): | |||
if isabs(cascade_file_path): | |||
cascade_file = cascade_file_path | |||
else: | |||
cascade_file = join(abspath(dirname(module_path)), cascade_file_path) | |||
setattr(self.__class__, 'cascade', cv.Load(cascade_file)) | |||
|
|||
def get_min_size_for(self, size): | |||
ratio = int(min(size[0], size[1]) / 15) | |||
ratio = max(20, ratio) | |||
return (ratio, ratio) | |||
|
|||
def get_features(self, width, height, mode, img_data): | |||
sz = (width, height) | |||
image = cv.CreateImageHeader(sz, cv.IPL_DEPTH_8U, 3) | |||
cv.SetData(image, img_data) | |||
|
|||
gray = cv.CreateImage(sz, 8, 1); | |||
convert_mode = getattr(cv, 'CV_%s2GRAY' % mode) | |||
cv.CvtColor(image, gray, convert_mode) | |||
|
|||
# min_size = (20, 20) | |||
min_size = self.get_min_size_for(sz) | |||
haar_scale = 1.2 | |||
min_neighbors = 1 | |||
|
|||
cv.EqualizeHist(gray, gray) | |||
|
|||
faces = cv.HaarDetectObjects(gray, | |||
self.__class__.cascade, cv.CreateMemStorage(0), | |||
haar_scale, min_neighbors, | |||
cv.CV_HAAR_DO_CANNY_PRUNING, min_size) | |||
|
|||
faces_scaled = [] | |||
|
|||
for ((x, y, w, h), n) in faces: | |||
# the input to cv.HaarDetectObjects was resized, so scale the | |||
# bounding box of each face and convert it to two CvPoints | |||
pt1 = (x, y) | |||
pt2 = ((x + w), (y + h)) | |||
x1 = pt1[0] | |||
x2 = pt2[0] | |||
y1 = pt1[1] | |||
y2 = pt2[1] | |||
faces_scaled.append(((x1, y1, x2-x1, y2-y1), None)) | |||
|
|||
return faces_scaled | |||
|
|||
def detect(self, context): | |||
features = self.get_features(width, height, mode, img_data) | |||
|
|||
if features: | |||
points = [[left, top, width, height] for (left, top, width, height), neighbors in features] | |||
else: | |||
points = [] | |||
|
|||
return points |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,33 @@ | |||
#!/usr/bin/python | |||
# -*- coding: utf-8 -*- | |||
|
|||
# thumbor imaging service | |||
# https://github.com/globocom/thumbor/wiki | |||
|
|||
# Licensed under the MIT license: | |||
# http://www.opensource.org/licenses/mit-license | |||
# Copyright (c) 2011 globo.com timehome@corp.globo.com | |||
|
|||
from detectors import CascadeLoaderDetector | |||
|
|||
HAIR_OFFSET = 0.12 | |||
|
|||
class FaceDetector(CascadeLoaderDetector): | |||
|
|||
def __init__(self): | |||
self.load_cascade_file(__file__, 'haarcascade_frontalface_alt.xml') | |||
|
|||
def __add_hair_offset(self, top, height): | |||
top = max(0, top - height * HAIR_OFFSET) | |||
return top | |||
|
|||
def detect(self, width, height, mode, img_data): | |||
features = self.get_features(width, height, mode, img_data) | |||
|
|||
points = [] | |||
if features: | |||
for (left, top, width, height), neighbors in features: | |||
top = self.__add_hair_offset(top, height) | |||
points.append([left, top, width, height]) | |||
|
|||
return points |
Oops, something went wrong.