PageRenderTime 65ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/digikam-2.7.0/extra/libkface/libface/LibFace.cpp

#
C++ | 479 lines | 340 code | 85 blank | 54 comment | 46 complexity | 9f7452dedd2ef3037e1780dcfd128042 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, GPL-3.0, GPL-2.0
  1. /** ===========================================================
  2. * @file
  3. *
  4. * This file is a part of libface project
  5. * <a href="http://libface.sourceforge.net">http://libface.sourceforge.net</a>
  6. *
  7. * @date 2010-02-18
  8. * @brief Lead Face library class.
  9. * @section DESCRIPTION
  10. *
  11. * @author Copyright (C) 2010 by Alex Jironkin
  12. * <a href="alexjironkin at gmail dot com">alexjironkin at gmail dot com</a>
  13. * @author Copyright (C) 2010 by Aditya Bhatt
  14. * <a href="adityabhatt at gmail dot com">adityabhatt at gmail dot com</a>
  15. * @author Copyright (C) 2010 by Gilles Caulier
  16. * <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a>
  17. * @author Copyright (C) 2010 by Marcel Wiesweg
  18. * <a href="mailto:marcel dot wiesweg at gmx dot de">marcel dot wiesweg at gmx dot de</a>
  19. *
  20. * @section LICENSE
  21. *
  22. * This program is free software; you can redistribute it
  23. * and/or modify it under the terms of the GNU General
  24. * Public License as published by the Free Software Foundation;
  25. * either version 2, or (at your option)
  26. * any later version.
  27. *
  28. * This program is distributed in the hope that it will be useful,
  29. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  31. * GNU General Public License for more details.
  32. *
  33. * ============================================================ */
  34. #include <sys/stat.h>
  35. #include <iostream>
  36. #include <fstream>
  37. #include <cstdio>
  38. #include <cstdlib>
  39. #include <cctype>
  40. #include <cerrno>
  41. #include <vector>
  42. #include <sstream>
  43. #include <algorithm>
  44. #include <iterator>
  45. //TODO: Scale images here.
  46. #include "LibFace.h"
  47. #include "LibFaceUtils.h"
  48. #include "FaceDetect.h"
  49. #include "Face.h"
  50. using namespace std;
  51. namespace libface
  52. {
  53. class LibFace::LibFacePriv
  54. {
  55. public:
  56. LibFacePriv()
  57. {
  58. detectionCore = 0;
  59. recognitionCore = 0;
  60. lastImage = 0;
  61. }
  62. Mode type;
  63. std::string cascadeDir;
  64. LibFaceDetectCore* detectionCore;
  65. LibFaceRecognitionCore* recognitionCore;
  66. IplImage* lastImage;
  67. std::string lastFileName;
  68. static int facesize() { return 120; }
  69. };
  70. LibFace::LibFace(Mode type, const string& configDir, const string& cascadeDir)
  71. : d(new LibFacePriv)
  72. {
  73. d->type = type;
  74. cout << "Cascade directory located as : " << cascadeDir << endl;
  75. // We don't need Eigenfaces if we just want detection, and vice versa.
  76. // So there is a case for everything.
  77. switch (d->type)
  78. {
  79. case DETECT:
  80. d->cascadeDir = cascadeDir;
  81. d->detectionCore = new FaceDetect(d->cascadeDir);
  82. break;
  83. case EIGEN:
  84. d->recognitionCore = new Eigenfaces(configDir);
  85. break;
  86. default: // Initialize both detector and Eigenfaces
  87. d->cascadeDir = cascadeDir;
  88. d->detectionCore = new FaceDetect(d->cascadeDir);
  89. d->recognitionCore = new Eigenfaces(configDir);
  90. break;
  91. }
  92. }
  93. LibFace::~LibFace()
  94. {
  95. switch(d->type)
  96. {
  97. case DETECT:
  98. delete d->detectionCore;
  99. break;
  100. case EIGEN:
  101. delete d->recognitionCore;
  102. break;
  103. default:
  104. delete d->detectionCore;
  105. delete d->recognitionCore;
  106. break;
  107. }
  108. cvReleaseImage(&d->lastImage);
  109. delete d;
  110. }
  111. vector<Face> LibFace::detectFaces(const string& filename, int /*scaleFactor*/)
  112. {
  113. vector<Face> result;
  114. if(filename.length() == 0)
  115. {
  116. if (DEBUG)
  117. {
  118. cout<<"No image passed for detection"<<endl;
  119. return result;
  120. }
  121. }
  122. //Check if image was already loaded once, by checking last loaded filename.
  123. if (filename != d->lastFileName)
  124. {
  125. d->lastFileName = filename;
  126. cvReleaseImage(&d->lastImage);
  127. d->lastImage = cvLoadImage(filename.data(), CV_LOAD_IMAGE_GRAYSCALE);
  128. }
  129. return d->detectionCore->detectFaces(d->lastImage);
  130. }
  131. vector<Face> LibFace::detectFaces(const char* arr, int width, int height, int step, int depth, int channels, int /*scaleFactor*/)
  132. {
  133. IplImage* image = LibFaceUtils::charToIplImage(arr, width, height, step, depth, channels);
  134. return d->detectionCore->detectFaces(image);
  135. }
  136. vector<Face> LibFace::detectFaces(const IplImage* image, const CvSize& originalSize)
  137. {
  138. return d->detectionCore->detectFaces(image, originalSize);
  139. }
  140. map<string,string> LibFace::getConfig()
  141. {
  142. map<string,string> result = d->recognitionCore->getConfig();
  143. return result;
  144. }
  145. int LibFace::loadConfig(const string& /*dir*/)
  146. {
  147. int result = 0;
  148. /*
  149. d->recognitionCore->loadData(dir);
  150. */
  151. return result;
  152. }
  153. int LibFace::loadConfig(const map<string, string>& config)
  154. {
  155. int result = d->recognitionCore->loadConfig(config);
  156. return result;
  157. }
  158. vector<pair<int, double> > LibFace::recognise(const string& filename, vector<Face>* faces, int scaleFactor)
  159. {
  160. IplImage* img = cvLoadImage(filename.data(), CV_LOAD_IMAGE_GRAYSCALE); // grayscale
  161. return this->recognise(img, faces, scaleFactor);
  162. cvReleaseImage(&img); // FIXME : This line is never called !!!
  163. }
  164. vector<pair<int, double> > LibFace::recognise(const IplImage* img, vector<Face>* faces, int /*scaleFactor*/)
  165. {
  166. vector<pair<int, double> > result;
  167. if (faces->size() == 0)
  168. {
  169. if (DEBUG)
  170. cout<<" No faces passed to libface::recognise() , not recognizing..." << endl;
  171. return result;
  172. }
  173. if (!img)
  174. {
  175. if (DEBUG)
  176. cout<<" Null image passed to libface::recognise() , not recognizing..." << endl;
  177. return result;
  178. }
  179. if (DEBUG)
  180. {
  181. cout << "Will recognize." << endl;
  182. }
  183. vector<IplImage*> newFaceImgArr;
  184. int size = faces->size();
  185. for (int i=0 ; i<size ; i++)
  186. {
  187. Face* face = &faces->at(i);
  188. int x1 = face->getX1();
  189. int y1 = face->getY1();
  190. int width = face->getWidth();
  191. int height = face->getHeight();
  192. // Extract face-image from whole-image.
  193. CvRect rect = cvRect(x1, y1, width, height);
  194. IplImage* faceImg = LibFaceUtils::copyRect(img, rect);
  195. // Make into d->facesize*d->facesize standard-sized image
  196. IplImage* sizedFaceImg = cvCreateImage(cvSize(d->facesize(), d->facesize()), img->depth, img->nChannels);
  197. cvResize(faceImg, sizedFaceImg);
  198. // Extracted. Now push it into the newfaces vector
  199. newFaceImgArr.push_back(sizedFaceImg);
  200. }
  201. // List of Face objects made
  202. // Now recognize
  203. for (int i = 0; i < size; ++i)
  204. result.push_back(d->recognitionCore->recognize(newFaceImgArr.at(i)));
  205. for (unsigned int i=0; i<newFaceImgArr.size(); i++)
  206. cvReleaseImage(&newFaceImgArr[i]);
  207. return result;
  208. }
  209. vector<pair<int, double> > LibFace::recognise(const char* arr, vector<Face>* faces, int width, int height, int step, int depth, int channels, int scaleFactor)
  210. {
  211. IplImage* img = LibFaceUtils::charToIplImage(arr, width, height, step, depth, channels);
  212. return this->recognise(img, faces, scaleFactor);
  213. }
  214. vector<pair<int, double> > LibFace::recognise(vector<Face>* faces, int /*scaleFactor*/)
  215. {
  216. vector<pair<int, double> > result;
  217. if (faces->size() == 0)
  218. {
  219. if (DEBUG)
  220. cout<<" No faces passed to libface::recognise() , not recognizing." << endl;
  221. return result;
  222. }
  223. if (DEBUG)
  224. {
  225. cout << "Recognizing." << endl;
  226. }
  227. vector<IplImage*> newFaceImgArr;
  228. int size = faces->size();
  229. for (int i=0 ; i<size ; i++)
  230. {
  231. Face* face = &faces->at(i);
  232. int id = face->getId();
  233. if (DEBUG)
  234. cout << "Id is: " << id << endl;
  235. const IplImage* faceImg = face->getFace();
  236. IplImage* createdImg = 0;
  237. if (!faceImg)
  238. {
  239. if (DEBUG)
  240. cout << "Face with null image passed to libface::recognise(), skipping";
  241. continue;
  242. }
  243. if (faceImg->width != d->facesize() || faceImg->height != d->facesize())
  244. {
  245. // Make into d->facesize*d->facesize standard-sized image
  246. createdImg = cvCreateImage(cvSize(d->facesize(), d->facesize()), faceImg->depth, faceImg->nChannels);
  247. cvResize(faceImg, createdImg);
  248. }
  249. else
  250. {
  251. // we need a non-const image for cvEigenDecomposite
  252. createdImg = cvCloneImage(faceImg);
  253. }
  254. result.push_back(d->recognitionCore->recognize(createdImg));
  255. face->setId(result.at(i).first);
  256. cvReleaseImage(&createdImg);
  257. }
  258. if (DEBUG)
  259. cout << "Size of result = " << result.size();
  260. return result;
  261. }
  262. int LibFace::saveConfig(const string& dir)
  263. {
  264. int result = 0;
  265. d->recognitionCore->saveConfig(dir);
  266. return result;
  267. }
  268. int LibFace::train(const string& /*dir*/)
  269. {
  270. int result = 0;
  271. // d->recognitionCore->train(dir);
  272. return result;
  273. }
  274. std::vector<int> LibFace::update(const IplImage* img, vector<Face>* faces, int /*scaleFactor*/)
  275. {
  276. std::vector<int> assignedIDs;
  277. if (faces->size() == 0)
  278. {
  279. if (DEBUG)
  280. cout<<" No faces passed to update." << endl;
  281. return assignedIDs;
  282. }
  283. if (DEBUG)
  284. {
  285. cout << "Update with faces." << endl;
  286. }
  287. vector<Face> newFaceArr;
  288. vector<IplImage*> createdImages;
  289. int size = faces->size();
  290. for (int i=0 ; i<size ; i++)
  291. {
  292. Face* face = &faces->at(i);
  293. int x1 = face->getX1();
  294. int y1 = face->getY1();
  295. int width = face->getWidth();
  296. int height = face->getHeight();
  297. int id = face->getId();
  298. if (DEBUG)
  299. cout << "Id is: " << id << endl;
  300. // Extract face-image from whole-image.
  301. CvRect rect = cvRect(x1,y1,width,height);
  302. IplImage* faceImg = LibFaceUtils::copyRect(img, rect);
  303. // Make into standard-sized image
  304. IplImage* sizedFaceImg = cvCreateImage(cvSize(d->facesize(), d->facesize()), img->depth, img->nChannels);
  305. cvResize(faceImg, sizedFaceImg);
  306. createdImages.push_back(sizedFaceImg);
  307. face->setFace(sizedFaceImg);
  308. // Extracted. Now push it into the newfaces vector
  309. newFaceArr.push_back(*face);
  310. }
  311. assignedIDs = d->recognitionCore->update(newFaceArr);
  312. for (unsigned int i=0; i<createdImages.size(); i++)
  313. cvReleaseImage(&createdImages[i]);
  314. return assignedIDs;
  315. }
  316. std::vector<int> LibFace::update(const char* arr, vector<Face>* faces, int width, int height, int step, int depth, int channels, int scaleFactor)
  317. {
  318. IplImage* img = LibFaceUtils::charToIplImage(arr, width, height, step, depth, channels);
  319. return this->update(img, faces, scaleFactor);
  320. }
  321. std::vector<int> LibFace::update(const string& filename, vector<Face>* faces, int scaleFactor)
  322. {
  323. IplImage* img = cvLoadImage(filename.data(), CV_LOAD_IMAGE_GRAYSCALE); //grayscale
  324. return this->update(img, faces, scaleFactor);
  325. cvReleaseImage(&img);
  326. }
  327. std::vector<int> LibFace::update(vector<Face>* faces, int /*scaleFactor*/)
  328. {
  329. std::vector<int> assignedIDs;
  330. if (faces->size() == 0)
  331. {
  332. if (DEBUG)
  333. cout<<" No faces passed to libface::update() , not updating." << endl;
  334. return assignedIDs;
  335. }
  336. if (DEBUG)
  337. {
  338. cout << "Update with faces." << endl;
  339. }
  340. vector<Face> newFaceArr;
  341. vector<IplImage*> createdImages;
  342. int size = faces->size();
  343. for (int i=0; i<size; i++)
  344. {
  345. // Copy, dont change the passed face
  346. Face face = faces->at(i);
  347. if (DEBUG)
  348. cout << "Id is: " << face.getId() << endl;
  349. const IplImage* faceImg = face.getFace();
  350. if (faceImg->width != d->facesize() || faceImg->height != d->facesize())
  351. {
  352. // Make into standard-sized image
  353. IplImage* sizedFaceImg = cvCreateImage(cvSize(d->facesize() , d->facesize()), faceImg->depth, faceImg->nChannels);
  354. cvResize(faceImg, sizedFaceImg);
  355. face.setFace(sizedFaceImg);
  356. createdImages.push_back(sizedFaceImg);
  357. }
  358. // Extracted. Now push it into the newfaces vector
  359. newFaceArr.push_back(face);
  360. }
  361. assignedIDs = d->recognitionCore->update(newFaceArr);
  362. for (unsigned int i=0; i<createdImages.size(); i++)
  363. cvReleaseImage(&createdImages[i]);
  364. return assignedIDs;
  365. }
  366. int LibFace::count() const
  367. {
  368. return d->recognitionCore->count();
  369. }
  370. void LibFace::setDetectionAccuracy(double value)
  371. {
  372. d->detectionCore->setAccuracy(value);
  373. }
  374. double LibFace::getDetectionAccuracy() const
  375. {
  376. return d->detectionCore->accuracy();
  377. }
  378. void LibFace::setDetectionSpecificity(double value)
  379. {
  380. d->detectionCore->setSpecificity(value);
  381. }
  382. double LibFace::getDetectionSpecificity() const
  383. {
  384. return d->detectionCore->specificity();
  385. }
  386. int LibFace::getRecommendedImageSizeForDetection(const CvSize&) const
  387. {
  388. return FaceDetect::getRecommendedImageSizeForDetection();
  389. }
  390. CvSize LibFace::getRecommendedImageSizeForRecognition(const CvSize&) const
  391. {
  392. return cvSize(d->facesize(), d->facesize());
  393. }
  394. } // namespace libface