Skip to content

Commit

Permalink
Added accelerated Viola-Jones face detector.
Browse files Browse the repository at this point in the history
  • Loading branch information
gregorpm committed Feb 21, 2014
1 parent 8811547 commit 424e3de
Show file tree
Hide file tree
Showing 15 changed files with 34,027 additions and 0 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Expand Up @@ -19,10 +19,18 @@ find_package(Eigen REQUIRED)
find_package(GLUT REQUIRED)
# HDF5
find_package(HDF5 REQUIRED)
# OpenCV
find_package(OpenCV REQUIRED)
# OpenGL
find_package(OpenGL REQUIRED)
# OpenNI
find_package(OpenNI2 REQUIRED)
# OpenMP
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()

set(MODULE_NAMES
cameras
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -16,5 +16,6 @@ DIP can be compiled and installed using CMake.
* CUDA 5.0
* Eigen 3.0.0
* HDF5
* OpenCV
* OpenNI2
* OpenGL/GLUT
1 change: 1 addition & 0 deletions applications/CMakeLists.txt
@@ -1,6 +1,7 @@
set(APPLICATION_NAMES
camera_capture
camera_viewer
face_detection
face_modeling
object_modeling
)
Expand Down
51 changes: 51 additions & 0 deletions applications/face_detection/CMakeLists.txt
@@ -0,0 +1,51 @@
SET(APPICATION_NAME face_detection)

SET(MODULE_DEPENDENCIES
cameras
common
io
segmentation
)

include(includes.cmake)

foreach(DEPENDENT ${MODULE_DEPENDENCIES})
include(${PROJECT_SOURCE_DIR}/${DEPENDENT}/includes.cmake)

set(INCLUDE_DIRS
${INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/${DEPENDENT}/include
)
endforeach(DEPENDENT)

set(INCLUDE_DIRS
${INCLUDE_DIRS}
)

include_directories(${INCLUDE_DIRS})

set(INCS
)

set(SRCS
${APPICATION_NAME}.cpp
)

set(LIBS
${GLUT_LIBRARIES}
${OpenCV_LIBRARIES}
${OPENGL_LIBRARIES}
${MODULE_DEPENDENCIES}
)

add_executable(${APPICATION_NAME} ${SRCS} ${INCS})
target_link_libraries(${APPICATION_NAME} ${LIBS})

install(TARGETS ${APPICATION_NAME} DESTINATION ${BIN_INSTALL_DIR})

include(../copy_file.cmake)
copy_file("${PROJECT_SOURCE_DIR}/data/haarcascade_frontalface_default.xml")

if(WIN32)
include(install.cmake)
endif()
245 changes: 245 additions & 0 deletions applications/face_detection/face_detection.cpp
@@ -0,0 +1,245 @@
/*
Copyright (c) 2013-2014, Gregory P. Meyer
University of Illinois Board of Trustees
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// Standard Libraries
#include <stdio.h>
#include <stdlib.h>

// OpenGL
#include <GL/glut.h>

// DIP
#include <dip/cameras/camera.h>
#include <dip/cameras/dumpfile.h>
#include <dip/cameras/primesense.h>
#include <dip/common/types.h>
#include <dip/segmentation/facemasker.h>

using namespace cv;
using namespace dip;
using namespace std;

const int kWindowWidth = 640;
const int kWindowHeight = 480;

const int kFramesPerSecond = 30;

const int kMaxDifference = 250;
const int kMinDepth = 50;
const int kMaxDepth = 5000;
const float kMinFaceSize = 100.0f;
const float kMaxFaceSize = 225.0f;

const char kCascade[] = "haarcascade_frontalface_default.xml";

CascadeClassifier g_cascade;
FaceMasker *g_masker = NULL;

Camera *g_camera = NULL;

Depth *g_depth = NULL;
Color *g_color = NULL;

GLuint g_texture;

void close() {
if (g_camera != NULL)
delete g_camera;

if (g_depth != NULL)
delete [] g_depth;
if (g_color != NULL)
delete [] g_color;

exit(0);
}

void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -10.0f, 10.0f);

// Update depth image.
if (g_camera->Update(g_depth)) {
printf("Unable to update depth image.\n");
close();
}

// Update color image.
if (g_camera->Update(g_color)) {
printf("Unable to update color image.\n");
close();
}

// Detect faces in color image.
Mat image(g_camera->height(COLOR_SENSOR), g_camera->width(COLOR_SENSOR),
CV_8UC3, g_color);

// Eliminate sub-images using depth image.
Size window_size = g_cascade.getOriginalWindowSize();
g_masker->Run(kMaxDifference, kMinDepth, kMaxDepth,
kMinFaceSize, kMaxFaceSize, window_size.width,
g_camera->width(DEPTH_SENSOR), g_camera->height(DEPTH_SENSOR),
g_camera->fx(DEPTH_SENSOR), g_depth);

vector<Rect> faces;
g_cascade.detectMultiScale(image, faces, 1.1, 3);

// Update Texture
glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, g_texture);

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_camera->width(COLOR_SENSOR),
g_camera->height(COLOR_SENSOR), GL_RGB, GL_UNSIGNED_BYTE,
g_color);

glDisable(GL_TEXTURE_2D);

// Display Frame
glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, g_texture);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 0.0f, 0.0f);
glEnd();

glDisable(GL_TEXTURE_2D);
// Draw face rectangles.
for (unsigned int i = 0; i < faces.size(); i++) {
float left = (float)faces[i].x /
g_camera->width(COLOR_SENSOR);
float right = (float)(faces[i].x + faces[i].width) /
g_camera->width(COLOR_SENSOR);
float top = 1.0f - ((float)faces[i].y /
g_camera->height(COLOR_SENSOR));
float bottom = 1.0f - ((float)(faces[i].y + faces[i].height) /
g_camera->height(COLOR_SENSOR));

glBegin(GL_LINE_LOOP);
glVertex3f(left, top, 0.0f);
glVertex3f(right, top, 0.0f);
glVertex3f(right, bottom, 0.0f);
glVertex3f(left, bottom, 0.0f);
glEnd();
}

glutSwapBuffers();
}

void reshape(int w, int h) {
glViewport(0, 0, w, h);
}

void keyboard(unsigned char key, int x, int y) {
switch (key) {
// Quit Program
case 27:
close();
break;
}
}

void timer(int fps) {
glutPostRedisplay();
glutTimerFunc(1000 / fps, timer, fps);
}

int main(int argc, char **argv) {
if (argc > 2) {
printf("Usage: %s [Dump File]\n", argv[0]);
return -1;
}

glutInit(&argc, argv);

// Initialize camera.
if (argc < 2)
g_camera = new PrimeSense();
else
g_camera = new DumpFile(argv[1]);

if (!g_camera->enabled()) {
printf("Unable to Open Camera\n");
return -1;
}

// Initialize buffers.
g_depth = new Depth[g_camera->width(DEPTH_SENSOR) *
g_camera->height(DEPTH_SENSOR)];
g_color = new Color[g_camera->width(COLOR_SENSOR) *
g_camera->height(COLOR_SENSOR)];

// Initialize face classifier.
if (!g_cascade.load(kCascade)) {
printf("Failed to load cascade classifier.\n");
return -1;
}

// Initialize face masker.
g_masker = new FaceMasker;
Ptr<CascadeClassifier::MaskGenerator> masker_ptr(g_masker);
g_cascade.setMaskGenerator(masker_ptr);

// Initialize OpenGL.
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(kWindowWidth, kWindowHeight);
glutInitWindowPosition(100, 100);
glutCreateWindow("Face Detection");

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutTimerFunc(1000 / kFramesPerSecond, timer, kFramesPerSecond);

// Initialize texture.
glEnable(GL_TEXTURE_2D);

glGenTextures(1, &g_texture);
glBindTexture(GL_TEXTURE_2D, g_texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_camera->width(COLOR_SENSOR),
g_camera->height(COLOR_SENSOR), 0, GL_RGB,
GL_UNSIGNED_BYTE, NULL);

glDisable(GL_TEXTURE_2D);

glutMainLoop();

return 0;
}
6 changes: 6 additions & 0 deletions applications/face_detection/includes.cmake
@@ -0,0 +1,6 @@
set(INCLUDE_DIRS
${INCLUDE_DIRS}
${GLUT_INCLUDE_DIR}
${OpenCV_INCLUDE_DIRS}
${OPENGL_INCLUDE_DIR}
)
32 changes: 32 additions & 0 deletions applications/face_detection/install.cmake
@@ -0,0 +1,32 @@
include(../copy_file.cmake)

# Copy and Install HDF5 DLLs
copy_file("${HDF5_INCLUDE_DIR}/../bin/hdf5.dll")
copy_file("${HDF5_INCLUDE_DIR}/../bin/hdf5_cpp.dll")
copy_file("${HDF5_INCLUDE_DIR}/../bin/szip.dll")
copy_file("${HDF5_INCLUDE_DIR}/../bin/zlib.dll")

# Copy and Install GLUT DLLs
copy_file("${GLUT_INCLUDE_DIR}/../bin/freeglut.dll")

# Copy and Install OpenNI2 DLLs
copy_file("${OPENNI2_INCLUDE_DIRS}/../Redist/OpenNI2.dll")

add_custom_command(TARGET ${APPICATION_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${OPENNI2_INCLUDE_DIRS}/../Redist/OpenNI2"
"$<TARGET_FILE_DIR:${APPICATION_NAME}>/OpenNI2")
install(DIRECTORY "${OPENNI2_INCLUDE_DIRS}/../Redist/OpenNI2"
DESTINATION "${BIN_INSTALL_DIR}")

# Copy and Install OpenCV DLLs
set(OpenCV_NUMBER
"${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}")
copy_file("${OpenCV_DIR}/bin/Release/opencv_core${OpenCV_NUMBER}.dll")
copy_file("${OpenCV_DIR}/bin/Debug/opencv_core${OpenCV_NUMBER}d.dll")
copy_file("${OpenCV_DIR}/bin/Release/opencv_highgui${OpenCV_NUMBER}.dll")
copy_file("${OpenCV_DIR}/bin/Debug/opencv_highgui${OpenCV_NUMBER}d.dll")
copy_file("${OpenCV_DIR}/bin/Release/opencv_imgproc${OpenCV_NUMBER}.dll")
copy_file("${OpenCV_DIR}/bin/Debug/opencv_imgproc${OpenCV_NUMBER}d.dll")
copy_file("${OpenCV_DIR}/bin/Release/opencv_objdetect${OpenCV_NUMBER}.dll")
copy_file("${OpenCV_DIR}/bin/Debug/opencv_objdetect${OpenCV_NUMBER}d.dll")
2 changes: 2 additions & 0 deletions common/CMakeLists.txt
Expand Up @@ -22,6 +22,7 @@ set(INCLUDE_DIRS
include_directories(${INCLUDE_DIRS})

set(INCS
include/dip/${MODULE_NAME}/distance.h
include/dip/${MODULE_NAME}/error.h
include/dip/${MODULE_NAME}/integralimage.h
include/dip/${MODULE_NAME}/macros.h
Expand All @@ -31,6 +32,7 @@ set(INCS
)

set(SRCS
src/distance.cpp
src/error.cu
src/integralimage.cpp
src/memory.cu
Expand Down

0 comments on commit 424e3de

Please sign in to comment.