Skip to content

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
cezarsa committed Jan 4, 2012
1 parent 70647c0 commit 322e250
Show file tree
Hide file tree
Showing 18 changed files with 254,367 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .gitignore
@@ -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
1 change: 1 addition & 0 deletions remotecv/__init__.py
@@ -0,0 +1 @@
__version__ = '0.1.0'
13 changes: 13 additions & 0 deletions remotecv/app.py
@@ -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 })
80 changes: 80 additions & 0 deletions remotecv/detectors/__init__.py
@@ -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
33 changes: 33 additions & 0 deletions remotecv/detectors/face_detector/__init__.py
@@ -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

0 comments on commit 322e250

Please sign in to comment.