From 01f3b2a47fad7946a8c640fcda0a01cfaf45c648 Mon Sep 17 00:00:00 2001 From: "Michael J. Rubinsky" Date: Sun, 30 May 2010 20:44:33 -0400 Subject: [PATCH] Add a binder for the ansel face driver, some cleanup while I was poking --- ansel/faces/claim.php | 2 +- ansel/faces/custom.php | 2 +- ansel/faces/face.php | 2 +- ansel/faces/gallery.php | 2 +- ansel/faces/image.php | 2 +- ansel/faces/img.php | 2 +- ansel/faces/name.php | 2 +- ansel/faces/report.php | 2 +- ansel/faces/savecustom.php | 2 +- ansel/faces/search/tabs.php | 2 +- ansel/lib/Ajax/Imple/EditFaces.php | 6 +-- ansel/lib/Application.php | 1 + ansel/lib/Block/recent_faces.php | 2 +- ansel/lib/Faces.php | 24 +-------- ansel/lib/Faces/Base.php | 60 ++++++++++++----------- ansel/lib/Faces/facedetect.php | 23 ++++----- ansel/lib/Faces/opencv.php | 97 ------------------------------------- ansel/lib/Faces/user.php | 2 +- ansel/lib/Injector/Binder/Faces.php | 27 +++++++++++ ansel/lib/Widget/GalleryFaces.php | 2 +- ansel/lib/Widget/ImageFaces.php | 2 +- ansel/lib/Widget/OwnerFaces.php | 2 +- 22 files changed, 92 insertions(+), 176 deletions(-) delete mode 100644 ansel/lib/Faces/opencv.php create mode 100644 ansel/lib/Injector/Binder/Faces.php diff --git a/ansel/faces/claim.php b/ansel/faces/claim.php index 5a0da90a2..35273d155 100644 --- a/ansel/faces/claim.php +++ b/ansel/faces/claim.php @@ -13,7 +13,7 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('ansel'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $face_id = Horde_Util::getFormData('face'); try { $face = $faces->getFaceById($face_id); diff --git a/ansel/faces/custom.php b/ansel/faces/custom.php index 820249713..09465efa2 100644 --- a/ansel/faces/custom.php +++ b/ansel/faces/custom.php @@ -45,7 +45,7 @@ $y2 = $conf['screen']['width']; $name = Horde_Util::getFormData('name'); if ($face_id) { - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); try { $face = $faces->getFaceById($face_id, true); $x1 = $face['face_x1']; diff --git a/ansel/faces/face.php b/ansel/faces/face.php index 1d664fe96..f30640850 100644 --- a/ansel/faces/face.php +++ b/ansel/faces/face.php @@ -17,7 +17,7 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('ansel'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $face_id = Horde_Util::getFormData('face'); try { $face = $faces->getFaceById($face_id); diff --git a/ansel/faces/gallery.php b/ansel/faces/gallery.php index b49625f7b..fe765b8e0 100644 --- a/ansel/faces/gallery.php +++ b/ansel/faces/gallery.php @@ -41,7 +41,7 @@ $images = $gallery->getImages($page * $perpage, $perpage); $reloadimage = Horde_Themes::img('reload.png'); $customimage = Horde_Themes::img('layout.png'); $customurl = Horde_Util::addParameter(Horde::applicationUrl('faces/custom.php'), 'page', $page); -$face = Ansel_Faces::factory(); +$face = $GLOBALS['injector']->getInstance('Ansel_Faces'); $autogenerate = $face->canAutogenerate(); $vars = Horde_Variables::getDefaultVariables(); diff --git a/ansel/faces/image.php b/ansel/faces/image.php index 2d6ad8ecb..11c8aae8a 100644 --- a/ansel/faces/image.php +++ b/ansel/faces/image.php @@ -13,7 +13,7 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('ansel'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $name = ''; $autocreate = true; diff --git a/ansel/faces/img.php b/ansel/faces/img.php index af68ad0fb..025fd9b53 100644 --- a/ansel/faces/img.php +++ b/ansel/faces/img.php @@ -14,7 +14,7 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('ansel'); $face_id = Horde_Util::getFormData('face'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); // Sendfile support. Lighttpd < 1.5 only understands the X-LIGHTTPD-send-file // header diff --git a/ansel/faces/name.php b/ansel/faces/name.php index 5ba560660..e85f5f23a 100644 --- a/ansel/faces/name.php +++ b/ansel/faces/name.php @@ -23,5 +23,5 @@ if (!$gallery->hasPermission(Horde_Auth::getAuth(), Horde_Perms::EDIT)) { throw new Horde_Exception('Access denied editing the photo.'); } -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $result = $faces->setName($face_id, $name); diff --git a/ansel/faces/report.php b/ansel/faces/report.php index 0d9a7f38c..cecd1bd32 100644 --- a/ansel/faces/report.php +++ b/ansel/faces/report.php @@ -15,7 +15,7 @@ Horde_Registry::appInit('ansel'); $face_id = Horde_Util::getFormData('face'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); try { $face = $faces->getFaceById($face_id); } catch (Horde_Exception $e) { diff --git a/ansel/faces/savecustom.php b/ansel/faces/savecustom.php index 5fba25904..79a88bc27 100644 --- a/ansel/faces/savecustom.php +++ b/ansel/faces/savecustom.php @@ -31,7 +31,7 @@ if (Horde_Util::getPost('submit') == _("Cancel")) { exit; } try { - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $result = $faces->saveCustomFace( $face_id, $image_id, diff --git a/ansel/faces/search/tabs.php b/ansel/faces/search/tabs.php index aef5a040c..c76d66565 100644 --- a/ansel/faces/search/tabs.php +++ b/ansel/faces/search/tabs.php @@ -13,7 +13,7 @@ require_once dirname(__FILE__) . '/../../lib/Application.php'; Horde_Registry::appInit('ansel'); -$faces = Ansel_Faces::factory(); +$faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); /* Show tabs */ $vars = Horde_Variables::getDefaultVariables(); diff --git a/ansel/lib/Ajax/Imple/EditFaces.php b/ansel/lib/Ajax/Imple/EditFaces.php index 5f59bbf60..44d0d0dbf 100644 --- a/ansel/lib/Ajax/Imple/EditFaces.php +++ b/ansel/lib/Ajax/Imple/EditFaces.php @@ -39,7 +39,7 @@ class Ansel_Ajax_Imple_EditFaces extends Horde_Ajax_Imple_Base return array('response' => 0); } - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); switch($action) { case 'process': // process - detects all faces in the image. @@ -77,7 +77,7 @@ class Ansel_Ajax_Imple_EditFaces extends Horde_Ajax_Imple_Base throw new Horde_Exception('Access denied editing the photo.'); } - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $faces->delete($image, $face_id); break; @@ -95,7 +95,7 @@ class Ansel_Ajax_Imple_EditFaces extends Horde_Ajax_Imple_Base throw new Horde_Exception('You are not allowed to edit this photo'); } - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $result = $faces->setName($face_id, $name); return array('response' => 1, 'message' => Ansel_Faces::getFaceTile($face_id)); diff --git a/ansel/lib/Application.php b/ansel/lib/Application.php index d99d13164..a22e9f112 100644 --- a/ansel/lib/Application.php +++ b/ansel/lib/Application.php @@ -61,6 +61,7 @@ class Ansel_Application extends Horde_Registry_Application $binders = array( 'Ansel_Storage' => new Ansel_Injector_Binder_Storage(), 'Ansel_Styles' => new Ansel_Injector_Binder_Styles(), + 'Ansel_Faces' => new Ansel_Injector_Binder_Faces(), ); foreach ($binders as $interface => $binder) { $GLOBALS['injector']->addBinder($interface, $binder); diff --git a/ansel/lib/Block/recent_faces.php b/ansel/lib/Block/recent_faces.php index ae22e2a0a..5056b9ecb 100644 --- a/ansel/lib/Block/recent_faces.php +++ b/ansel/lib/Block/recent_faces.php @@ -34,7 +34,7 @@ class Horde_Block_ansel_recent_faces extends Horde_Block function _content() { - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); $results = $faces->allFaces(0, $this->_params['limit']); $html = ''; foreach ($results as $face_id => $face) { diff --git a/ansel/lib/Faces.php b/ansel/lib/Faces.php index a0339c6c4..a55738432 100644 --- a/ansel/lib/Faces.php +++ b/ansel/lib/Faces.php @@ -12,25 +12,6 @@ class Ansel_Faces { /** - * Create instance - */ - static function factory($driver = null, $params = array()) - { - if ($driver === null) { - $driver = $GLOBALS['conf']['faces']['driver']; - } - - if (empty($params)) { - $params = $GLOBALS['conf']['faces']; - } - - $class_name = 'Ansel_Faces_' . $driver; - $parser = new $class_name($params); - - return $parser; - } - - /** * Delete faces from VFS and DB storage. * * @TODO: Move SQL queries to Ansel_Storage:: @@ -118,7 +99,7 @@ class Ansel_Faces */ static public function getFaceTile($face) { - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); if (!is_array($face)) { $face = $faces->getFaceById($face, true); } @@ -154,8 +135,7 @@ class Ansel_Faces } // Link for searching for similar faces. - $html .= ' ' . _("Find similar") . ''; + $html .= ' ' . _("Find similar") . ''; $html .= ''; return $html; diff --git a/ansel/lib/Faces/Base.php b/ansel/lib/Faces/Base.php index b862c6d88..ec5516176 100644 --- a/ansel/lib/Faces/Base.php +++ b/ansel/lib/Faces/Base.php @@ -35,7 +35,7 @@ class Ansel_Faces_Base * * @return mixed Array of face data */ - public function getFaces(&$image) + public function getFaces($image) { if ($image instanceof Ansel_Image) { // First check if screen view exists @@ -44,7 +44,10 @@ class Ansel_Faces_Base // Make sure we have an on-disk copy of the file. $file = $GLOBALS['injector']->getInstance('Horde_Vfs')->getVfs('images')->readFile($image->getVFSPath('screen'), $image->getVFSName('screen')); - } elseif (empty($file) || !is_string($image)) { + } else { + $file = $image; + } + if (empty($file) || !is_string($image)) { return array(); } @@ -87,7 +90,7 @@ class Ansel_Faces_Base $sql .= ', gallery_id, face_x1, face_y1, face_x2, face_y2'; } $sql .= ' FROM ansel_faces WHERE image_id = ' . (int)$image_id - . ' ORDER BY face_id DESC'; + . ' ORDER BY face_id DESC'; Horde::logMessage('SQL Query by Ansel_Faces::getImageFacesData: ' . $sql, 'DEBUG'); $result = $GLOBALS['ansel_db']->query($sql); @@ -128,7 +131,7 @@ class Ansel_Faces_Base public function getGalleryFaces($gallery) { $sql = 'SELECT face_id, image_id, gallery_id, face_name FROM ansel_faces ' - . ' WHERE gallery_id = ' . (int)$gallery . ' ORDER BY face_id DESC'; + . ' WHERE gallery_id = ' . (int)$gallery . ' ORDER BY face_id DESC'; $result = $GLOBALS['ansel_db']->query($sql); if ($result instanceof PEAR_Error) { @@ -184,9 +187,9 @@ class Ansel_Faces_Base $faces = array(); while ($face = $result->fetchRow(MDB2_FETCHMODE_ASSOC)) { $faces[$face['face_id']] = array('face_name' => $face['face_name'], - 'face_id' => $face['face_id'], - 'gallery_id' => $face['gallery_id'], - 'image_id' => $face['image_id']); + 'face_id' => $face['face_id'], + 'gallery_id' => $face['gallery_id'], + 'image_id' => $face['image_id']); } return $faces; @@ -255,7 +258,8 @@ class Ansel_Faces_Base { $info = array( 'filter' => 's.share_owner = ' . $GLOBALS['ansel_db']->quote($owner), - 'order' => 'f.face_id DESC'); + 'order' => 'f.face_id DESC' + ); if (!Horde_Auth::getAuth() || $owner != Horde_Auth::getAuth()) { $info['filter'] .= ' AND s.gallery_passwd IS NULL'; @@ -346,8 +350,7 @@ class Ansel_Faces_Base return false; } $data = $this->getFaceById($face_id, true); - - $image = &$GLOBALS['ansel_storage']->getImage($image_id); + $image = $GLOBALS['ansel_storage']->getImage($image_id); // Actually create the image. $this->createView( @@ -441,7 +444,7 @@ class Ansel_Faces_Base */ public function saveCustomFace($face_id, $image, $x1, $y1, $x2, $y2, $name = '') { - $image = &$GLOBALS['ansel_storage']->getImage($image); + $image = $GLOBALS['ansel_storage']->getImage($image); $gallery = $GLOBALS['ansel_storage']->getGallery($image->gallery); if (!$gallery->hasPermission(Horde_Auth::getAuth(), Horde_Perms::EDIT)) { throw new Horde_Exception_PermissionDenied('Access denied editing the photo.'); @@ -460,16 +463,15 @@ class Ansel_Faces_Base // Process the image $this->createView($face_id, - $image, - $x1, - $y1, - $x2, - $y2); + $image, + $x1, + $y1, + $x2, + $y2); // Clean up as images are static and all gallery images data will remain in memory $image->reset(); - // Store face id db if (empty($new)) { $sql = 'UPDATE ansel_faces SET face_name = ?, face_x1 = ?, face_y1 = ?, face_x2 = ?, face_y2 = ?' @@ -605,7 +607,7 @@ class Ansel_Faces_Base * * @return integer the face id */ - public function createView($face_id, &$image, $x1, $y1, $x2, $y2) + public function createView($face_id, $image, $x1, $y1, $x2, $y2) { // Make sure screen view is created and loaded $image->load('screen'); @@ -621,8 +623,11 @@ class Ansel_Faces_Base $path = Ansel_Faces::getVFSPath($image->id); $image->getHordeImage()->resize(50, 50, false); try { - $GLOBALS['injector']->getInstance('Horde_Vfs')->getVfs('images')->writeData($path . 'faces', $face_id . $ext, - $image->getHordeImage()->raw(), true); + $GLOBALS['injector']->getInstance('Horde_Vfs')->getVfs('images')->writeData( + $path . 'faces', + $face_id . $ext, + $image->getHordeImage()->raw(), + true); } catch (VFS_Exception $e) { throw new Horde_Exception_Prior($e); } @@ -648,8 +653,9 @@ class Ansel_Faces_Base } // Ensure we have an on-disk file to read the signature from. - $path = $GLOBALS['injector']->getInstance('Horde_Vfs')->getVfs('images')->readFile(Ansel_Faces::getVFSPath($image_id) . '/faces', - $face_id . Ansel_Faces::getExtension()); + $path = $GLOBALS['injector']->getInstance('Horde_Vfs')->getVfs('images')->readFile( + Ansel_Faces::getVFSPath($image_id) . '/faces', + $face_id . Ansel_Faces::getExtension()); $signature = puzzle_fill_cvec_from_file($path); if (empty($signature)) { @@ -754,7 +760,6 @@ class Ansel_Faces_Base { $sql = 'UPDATE ansel_faces SET face_name = ? WHERE face_id = ?'; $params = array($name, $face); - $q = $GLOBALS['ansel_db']->prepare($sql, null, MDB2_PREPARE_MANIP); if ($q instanceof PEAR_Error) { throw new Horde_Exception_Prior($q); @@ -796,8 +801,7 @@ class Ansel_Faces_Base // Always return the face_id $face['face_id'] = $face_id; - if ($full && $GLOBALS['conf']['faces']['search'] && - function_exists('puzzle_uncompress_cvec')) { + if ($full && $GLOBALS['conf']['faces']['search'] && function_exists('puzzle_uncompress_cvec')) { $face['face_signature'] = puzzle_uncompress_cvec($face['face_signature']); } @@ -841,8 +845,7 @@ class Ansel_Faces_Base $indexes[] = '(index_position = ' . $GLOBALS['ansel_db']->quote($i, 'integer') . ' AND index_part = ' - . $GLOBALS['ansel_db']->quote( - substr($signature, $i * $word_len, $word_len)) + . $GLOBALS['ansel_db']->quote(substr($signature, $i * $word_len, $word_len)) . ')'; } @@ -877,7 +880,8 @@ class Ansel_Faces_Base 'image_id' => $face['image_id'], 'similarity' => puzzle_vector_normalized_distance( $signature, - puzzle_uncompress_cvec($face['face_signature']))); + puzzle_uncompress_cvec($face['face_signature'])) + ); } uasort($faces, array($this, '_getSignatureMatches')); diff --git a/ansel/lib/Faces/facedetect.php b/ansel/lib/Faces/facedetect.php index 720ddffe4..ec69751d6 100644 --- a/ansel/lib/Faces/facedetect.php +++ b/ansel/lib/Faces/facedetect.php @@ -5,7 +5,7 @@ * @author Duck * @package Ansel */ -class Ansel_Faces_facedetect extends Ansel_Faces_Base +class Ansel_Faces_Facedetect extends Ansel_Faces_Base { /** * Where the face defintions are stored @@ -20,6 +20,9 @@ class Ansel_Faces_facedetect extends Ansel_Faces_Base $this->_defs = $params['defs']; } + /** + * + */ public function canAutogenerate() { return true; @@ -33,8 +36,7 @@ class Ansel_Faces_facedetect extends Ansel_Faces_Base */ protected function _getFaces($file) { - $result = Horde_Util::loadExtension('facedetect'); - if (!$result) { + if (!Horde_Util::loadExtension('facedetect')) { throw new Horde_Exception('You do not have the facedetect extension enabled in PHP'); } @@ -63,14 +65,13 @@ class Ansel_Faces_facedetect extends Ansel_Faces_Base protected function _getParamsArray($face_id, $image, $rect) { - $params = array($face_id, - $image->id, - $image->gallery, - $rect['x'], - $rect['y'], - $rect['x'] + $rect['w'], - $rect['y'] + $rect['h']); - return $params; + return array($face_id, + $image->id, + $image->gallery, + $rect['x'], + $rect['y'], + $rect['x'] + $rect['w'], + $rect['y'] + $rect['h']); } protected function _createView($face_id, $image, $rect) diff --git a/ansel/lib/Faces/opencv.php b/ansel/lib/Faces/opencv.php deleted file mode 100644 index 0622d92c8..000000000 --- a/ansel/lib/Faces/opencv.php +++ /dev/null @@ -1,97 +0,0 @@ - - * @package Ansel - */ -class Ansel_Faces_opencv extends Ansel_Faces_Base -{ - /** - * Where the face defintions are stored - */ - private $_defs = ''; - - /** - * Create instance - */ - public function __construct($params) - { - $this->_defs = $params['defs']; - } - - public function canAutogenerate() - { - return true; - } - - /** - * Get faces - * - * @param string $file Picture filename - */ - protected function _getFaces($file) - { - $result = Horde_Util::loadExtension('opencv'); - if (!$result) { - throw new Horde_Exception('You do not have the opencv extension enabled in PHP'); - } - $im = cv_image_load($file); - $haar = cv_object_load($this->_defs); - $seq = cv_haar_classifier_cascade_detect_objects($haar, $im); - $l = cv_seq_count($seq); - Horde::logMessage(sprintf("opencv extension detected %u faces.", $l), 'DEBUG'); - $rects = array(); - for ($i = 0; $i < $l; $i++) { - $r = cv_seq_get($seq, $i); - $rects[] = array('x' => $r['x'], - 'y' => $r['y'], - 'width' => $r['w'], - 'height' => $r['h']); - } - - return $rects; - } - - /** - * Check if a face in is inside anoter face - * - * @param array $face Face we are cheking - * @param array $faces Existing faces - * - * @param int Face ID containg passed face - */ - protected function _isInFace($face, $faces) - { - foreach ($faces as $id => $rect) { - if ($face['x'] > $rect['x'] && $face['x'] + $face['width'] < $face['x'] + $rect['width'] - && $face['y'] > $rect['y'] && $face['y'] + $face['height'] < $face['y'] + $rect['height']) { - return $id; - } - } - - return false; - } - - protected function _getParamsArray($face_id, $image, $rect) - { - $params = array($face_id, - $image->id, - $image->gallery, - $rect['x'], - $rect['y'], - $rect['x'] + $rect['width'], - $rect['y'] + $rect['height']); - return $params; - } - - protected function _createView($face_id, $image, $rect) - { - return $this->createView($face_id, - $image, - $rect['x'], - $rect['y'], - $rect['x'] + $rect['width'], - $rect['y'] + $rect['height']); - } -} diff --git a/ansel/lib/Faces/user.php b/ansel/lib/Faces/user.php index 0e8d338b3..ff6f0d28e 100644 --- a/ansel/lib/Faces/user.php +++ b/ansel/lib/Faces/user.php @@ -3,6 +3,6 @@ * @author Duck * @package Ansel */ -class Ansel_Faces_user extends Ansel_Faces_Base +class Ansel_Faces_User extends Ansel_Faces_Base { } diff --git a/ansel/lib/Injector/Binder/Faces.php b/ansel/lib/Injector/Binder/Faces.php new file mode 100644 index 000000000..99d8be596 --- /dev/null +++ b/ansel/lib/Injector/Binder/Faces.php @@ -0,0 +1,27 @@ + + * @category Horde + * @license http://www.fsf.org/copyleft/gpl.html GPL + * @package Ansel + */ +class Ansel_Injector_Binder_Faces Implements Horde_Injector_Binder +{ + public function create (Horde_Injector $injector) + { + $driver = $GLOBALS['conf']['faces']['driver']; + $params = $GLOBALS['conf']['faces']; + $class_name = 'Ansel_Faces_' . ucfirst($driver); + + return new $class_name($params); + } + + /** + */ + public function equals(Horde_Injector_Binder $binder) + { + return false; + } +} \ No newline at end of file diff --git a/ansel/lib/Widget/GalleryFaces.php b/ansel/lib/Widget/GalleryFaces.php index f26a0000e..3009799ef 100644 --- a/ansel/lib/Widget/GalleryFaces.php +++ b/ansel/lib/Widget/GalleryFaces.php @@ -58,7 +58,7 @@ class Ansel_Widget_GalleryFaces extends Ansel_Widget_Base . '
' . _("No faces found") . ''; } - $faces = Ansel_Faces::factory(); + $faces = $GLOBALS['injector']->getInstance('Ansel_Faces'); // Check for existing faces for this gallery. $html = '