mirror of https://github.com/opencv/opencv.git
Merge pull request #2021 from vpisarev:ocl_facedetect7
commit
b4bd5bab6d
32 changed files with 501408 additions and 584313 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,275 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, Itseez Inc, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/* Haar features calculation */ |
||||
|
||||
#include "precomp.hpp" |
||||
#include <stdio.h> |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
/* field names */ |
||||
|
||||
#define ICV_HAAR_SIZE_NAME "size" |
||||
#define ICV_HAAR_STAGES_NAME "stages" |
||||
#define ICV_HAAR_TREES_NAME "trees" |
||||
#define ICV_HAAR_FEATURE_NAME "feature" |
||||
#define ICV_HAAR_RECTS_NAME "rects" |
||||
#define ICV_HAAR_TILTED_NAME "tilted" |
||||
#define ICV_HAAR_THRESHOLD_NAME "threshold" |
||||
#define ICV_HAAR_LEFT_NODE_NAME "left_node" |
||||
#define ICV_HAAR_LEFT_VAL_NAME "left_val" |
||||
#define ICV_HAAR_RIGHT_NODE_NAME "right_node" |
||||
#define ICV_HAAR_RIGHT_VAL_NAME "right_val" |
||||
#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold" |
||||
#define ICV_HAAR_PARENT_NAME "parent" |
||||
#define ICV_HAAR_NEXT_NAME "next" |
||||
|
||||
namespace haar_cvt |
||||
{ |
||||
|
||||
struct HaarFeature |
||||
{ |
||||
enum { RECT_NUM = 3 }; |
||||
|
||||
HaarFeature() |
||||
{ |
||||
tilted = false; |
||||
for( int i = 0; i < RECT_NUM; i++ ) |
||||
{ |
||||
rect[i].r = Rect(0,0,0,0); |
||||
rect[i].weight = 0.f; |
||||
} |
||||
} |
||||
bool tilted; |
||||
struct
|
||||
{ |
||||
Rect r; |
||||
float weight; |
||||
} rect[RECT_NUM]; |
||||
}; |
||||
|
||||
struct HaarClassifierNode |
||||
{ |
||||
HaarClassifierNode() |
||||
{ |
||||
f = left = right = 0; |
||||
threshold = 0.f; |
||||
} |
||||
int f, left, right; |
||||
float threshold; |
||||
}; |
||||
|
||||
struct HaarClassifier |
||||
{ |
||||
std::vector<HaarClassifierNode> nodes; |
||||
std::vector<float> leaves; |
||||
}; |
||||
|
||||
struct HaarStageClassifier |
||||
{ |
||||
double threshold; |
||||
std::vector<HaarClassifier> weaks; |
||||
}; |
||||
|
||||
static bool convert(const String& oldcascade, const String& newcascade) |
||||
{ |
||||
FileStorage oldfs(oldcascade, FileStorage::READ); |
||||
if( !oldfs.isOpened() ) |
||||
return false; |
||||
FileNode oldroot = oldfs.getFirstTopLevelNode(); |
||||
|
||||
FileNode sznode = oldroot[ICV_HAAR_SIZE_NAME]; |
||||
if( sznode.empty() ) |
||||
return false; |
||||
Size cascadesize; |
||||
cascadesize.width = (int)sznode[0]; |
||||
cascadesize.height = (int)sznode[1]; |
||||
std::vector<HaarFeature> features; |
||||
|
||||
int i, j, k, n; |
||||
|
||||
FileNode stages_seq = oldroot[ICV_HAAR_STAGES_NAME]; |
||||
int nstages = (int)stages_seq.size(); |
||||
std::vector<HaarStageClassifier> stages(nstages); |
||||
|
||||
for( i = 0; i < nstages; i++ ) |
||||
{ |
||||
FileNode stagenode = stages_seq[i]; |
||||
HaarStageClassifier& stage = stages[i]; |
||||
stage.threshold = (double)stagenode[ICV_HAAR_STAGE_THRESHOLD_NAME]; |
||||
FileNode weaks_seq = stagenode[ICV_HAAR_TREES_NAME]; |
||||
int nweaks = (int)weaks_seq.size(); |
||||
stage.weaks.resize(nweaks); |
||||
|
||||
for( j = 0; j < nweaks; j++ ) |
||||
{ |
||||
HaarClassifier& weak = stage.weaks[j]; |
||||
FileNode weaknode = weaks_seq[j]; |
||||
int nnodes = (int)weaknode.size(); |
||||
|
||||
for( n = 0; n < nnodes; n++ ) |
||||
{ |
||||
FileNode nnode = weaknode[n]; |
||||
FileNode fnode = nnode[ICV_HAAR_FEATURE_NAME]; |
||||
HaarFeature f; |
||||
HaarClassifierNode node; |
||||
node.f = (int)features.size(); |
||||
f.tilted = (int)fnode[ICV_HAAR_TILTED_NAME] != 0; |
||||
FileNode rects_seq = fnode[ICV_HAAR_RECTS_NAME]; |
||||
int nrects = (int)rects_seq.size(); |
||||
|
||||
for( k = 0; k < nrects; k++ ) |
||||
{ |
||||
FileNode rnode = rects_seq[k]; |
||||
f.rect[k].r.x = (int)rnode[0]; |
||||
f.rect[k].r.y = (int)rnode[1]; |
||||
f.rect[k].r.width = (int)rnode[2]; |
||||
f.rect[k].r.height = (int)rnode[3]; |
||||
f.rect[k].weight = (float)rnode[4]; |
||||
} |
||||
features.push_back(f); |
||||
node.threshold = nnode[ICV_HAAR_THRESHOLD_NAME]; |
||||
FileNode leftValNode = nnode[ICV_HAAR_LEFT_VAL_NAME]; |
||||
if( !leftValNode.empty() ) |
||||
{ |
||||
node.left = -(int)weak.leaves.size(); |
||||
weak.leaves.push_back((float)leftValNode); |
||||
} |
||||
else |
||||
{ |
||||
node.left = (int)nnode[ICV_HAAR_LEFT_NODE_NAME]; |
||||
} |
||||
FileNode rightValNode = nnode[ICV_HAAR_RIGHT_VAL_NAME]; |
||||
if( !rightValNode.empty() ) |
||||
{ |
||||
node.right = -(int)weak.leaves.size(); |
||||
weak.leaves.push_back((float)rightValNode); |
||||
} |
||||
else |
||||
{ |
||||
node.right = (int)nnode[ICV_HAAR_RIGHT_NODE_NAME]; |
||||
} |
||||
weak.nodes.push_back(node); |
||||
} |
||||
} |
||||
} |
||||
|
||||
FileStorage newfs(newcascade, FileStorage::WRITE); |
||||
if( !newfs.isOpened() ) |
||||
return false; |
||||
|
||||
int maxWeakCount = 0, nfeatures = (int)features.size(); |
||||
for( i = 0; i < nstages; i++ ) |
||||
maxWeakCount = std::max(maxWeakCount, (int)stages[i].weaks.size()); |
||||
|
||||
newfs << "cascade" << "{:opencv-cascade-classifier" |
||||
<< "stageType" << "BOOST" |
||||
<< "featureType" << "HAAR" |
||||
<< "height" << cascadesize.width |
||||
<< "width" << cascadesize.height |
||||
<< "stageParams" << "{" |
||||
<< "maxWeakCount" << (int)maxWeakCount |
||||
<< "}" |
||||
<< "featureParams" << "{" |
||||
<< "maxCatCount" << 0 |
||||
<< "}" |
||||
<< "stageNum" << (int)nstages |
||||
<< "stages" << "["; |
||||
|
||||
for( i = 0; i < nstages; i++ ) |
||||
{ |
||||
int nweaks = (int)stages[i].weaks.size(); |
||||
newfs << "{" << "maxWeakCount" << (int)nweaks |
||||
<< "stageThreshold" << stages[i].threshold |
||||
<< "weakClassifiers" << "["; |
||||
for( j = 0; j < nweaks; j++ ) |
||||
{ |
||||
const HaarClassifier& c = stages[i].weaks[j]; |
||||
newfs << "{" << "internalNodes" << "["; |
||||
int nnodes = (int)c.nodes.size(), nleaves = (int)c.leaves.size(); |
||||
for( k = 0; k < nnodes; k++ ) |
||||
newfs << c.nodes[k].left << c.nodes[k].right |
||||
<< c.nodes[k].f << c.nodes[k].threshold; |
||||
newfs << "]" << "leafValues" << "["; |
||||
for( k = 0; k < nleaves; k++ ) |
||||
newfs << c.leaves[k]; |
||||
newfs << "]" << "}"; |
||||
} |
||||
newfs << "]" << "}"; |
||||
} |
||||
|
||||
newfs << "]" |
||||
<< "features" << "["; |
||||
|
||||
for( i = 0; i < nfeatures; i++ ) |
||||
{ |
||||
const HaarFeature& f = features[i]; |
||||
newfs << "{" << "rects" << "["; |
||||
for( j = 0; j < HaarFeature::RECT_NUM; j++ ) |
||||
{ |
||||
if( j >= 2 && fabs(f.rect[j].weight) < FLT_EPSILON ) |
||||
break; |
||||
newfs << "[" << f.rect[j].r.x << f.rect[j].r.y << |
||||
f.rect[j].r.width << f.rect[j].r.height << f.rect[j].weight << "]"; |
||||
} |
||||
newfs << "]"; |
||||
if( f.tilted ) |
||||
newfs << "tilted" << 1; |
||||
newfs << "}"; |
||||
} |
||||
|
||||
newfs << "]" << "}"; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
|
||||
bool CascadeClassifier::convert(const String& oldcascade, const String& newcascade) |
||||
{ |
||||
bool ok = haar_cvt::convert(oldcascade, newcascade); |
||||
if( !ok && newcascade.size() > 0 ) |
||||
remove(newcascade.c_str()); |
||||
return ok; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,185 @@ |
||||
///////////////////////////// OpenCL kernels for face detection ////////////////////////////// |
||||
////////////////////////////// see the opencv/doc/license.txt /////////////////////////////// |
||||
|
||||
typedef struct __attribute__((aligned(4))) OptFeature |
||||
{ |
||||
int4 ofs[3] __attribute__((aligned (4))); |
||||
float4 weight __attribute__((aligned (4))); |
||||
} |
||||
OptFeature; |
||||
|
||||
typedef struct __attribute__((aligned(4))) Stump |
||||
{ |
||||
int featureIdx __attribute__((aligned (4))); |
||||
float threshold __attribute__((aligned (4))); // for ordered features only |
||||
float left __attribute__((aligned (4))); |
||||
float right __attribute__((aligned (4))); |
||||
} |
||||
Stump; |
||||
|
||||
typedef struct __attribute__((aligned (4))) Stage |
||||
{ |
||||
int first __attribute__((aligned (4))); |
||||
int ntrees __attribute__((aligned (4))); |
||||
float threshold __attribute__((aligned (4))); |
||||
} |
||||
Stage; |
||||
|
||||
__kernel void runHaarClassifierStump( |
||||
__global const int* sum, |
||||
int sumstep, int sumoffset, |
||||
__global const int* sqsum, |
||||
int sqsumstep, int sqsumoffset, |
||||
__global const OptFeature* optfeatures, |
||||
|
||||
int nstages, |
||||
__global const Stage* stages, |
||||
__global const Stump* stumps, |
||||
|
||||
volatile __global int* facepos, |
||||
int2 imgsize, int xyscale, float factor, |
||||
int4 normrect, int2 windowsize, int maxFaces) |
||||
{ |
||||
int ix = get_global_id(0)*xyscale; |
||||
int iy = get_global_id(1)*xyscale; |
||||
sumstep /= sizeof(int); |
||||
sqsumstep /= sizeof(int); |
||||
|
||||
if( ix < imgsize.x && iy < imgsize.y ) |
||||
{ |
||||
int ntrees; |
||||
int stageIdx, i; |
||||
float s = 0.f; |
||||
__global const Stump* stump = stumps; |
||||
__global const OptFeature* f; |
||||
|
||||
__global const int* psum = sum + mad24(iy, sumstep, ix); |
||||
__global const int* pnsum = psum + mad24(normrect.y, sumstep, normrect.x); |
||||
int normarea = normrect.z * normrect.w; |
||||
float invarea = 1.f/normarea; |
||||
float sval = (pnsum[0] - pnsum[normrect.z] - pnsum[mul24(normrect.w, sumstep)] + |
||||
pnsum[mad24(normrect.w, sumstep, normrect.z)])*invarea; |
||||
float sqval = (sqsum[mad24(iy + normrect.y, sqsumstep, ix + normrect.x)])*invarea; |
||||
float nf = (float)normarea * sqrt(max(sqval - sval * sval, 0.f)); |
||||
float4 weight, vsval; |
||||
int4 ofs, ofs0, ofs1, ofs2; |
||||
nf = nf > 0 ? nf : 1.f; |
||||
|
||||
for( stageIdx = 0; stageIdx < nstages; stageIdx++ ) |
||||
{ |
||||
ntrees = stages[stageIdx].ntrees; |
||||
s = 0.f; |
||||
for( i = 0; i < ntrees; i++, stump++ ) |
||||
{ |
||||
f = optfeatures + stump->featureIdx; |
||||
weight = f->weight; |
||||
|
||||
ofs = f->ofs[0]; |
||||
sval = (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.x; |
||||
ofs = f->ofs[1]; |
||||
sval += (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.y; |
||||
if( weight.z > 0 ) |
||||
{ |
||||
ofs = f->ofs[2]; |
||||
sval += (psum[ofs.x] - psum[ofs.y] - psum[ofs.z] + psum[ofs.w])*weight.z; |
||||
} |
||||
|
||||
s += (sval < stump->threshold*nf) ? stump->left : stump->right; |
||||
} |
||||
|
||||
if( s < stages[stageIdx].threshold ) |
||||
break; |
||||
} |
||||
|
||||
if( stageIdx == nstages ) |
||||
{ |
||||
int nfaces = atomic_inc(facepos); |
||||
if( nfaces < maxFaces ) |
||||
{ |
||||
volatile __global int* face = facepos + 1 + nfaces*4; |
||||
face[0] = convert_int_rte(ix*factor); |
||||
face[1] = convert_int_rte(iy*factor); |
||||
face[2] = convert_int_rte(windowsize.x*factor); |
||||
face[3] = convert_int_rte(windowsize.y*factor); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#if 0 |
||||
__kernel void runLBPClassifierStump( |
||||
__global const int* sum, |
||||
int sumstep, int sumoffset, |
||||
__global const int* sqsum, |
||||
int sqsumstep, int sqsumoffset, |
||||
__global const OptFeature* optfeatures, |
||||
|
||||
int nstages, |
||||
__global const Stage* stages, |
||||
__global const Stump* stumps, |
||||
__global const int* bitsets, |
||||
int bitsetSize, |
||||
|
||||
volatile __global int* facepos, |
||||
int2 imgsize, int xyscale, float factor, |
||||
int4 normrect, int2 windowsize, int maxFaces) |
||||
{ |
||||
int ix = get_global_id(0)*xyscale*VECTOR_SIZE; |
||||
int iy = get_global_id(1)*xyscale; |
||||
sumstep /= sizeof(int); |
||||
sqsumstep /= sizeof(int); |
||||
|
||||
if( ix < imgsize.x && iy < imgsize.y ) |
||||
{ |
||||
int ntrees; |
||||
int stageIdx, i; |
||||
float s = 0.f; |
||||
__global const Stump* stump = stumps; |
||||
__global const int* bitset = bitsets; |
||||
__global const OptFeature* f; |
||||
|
||||
__global const int* psum = sum + mad24(iy, sumstep, ix); |
||||
__global const int* pnsum = psum + mad24(normrect.y, sumstep, normrect.x); |
||||
int normarea = normrect.z * normrect.w; |
||||
float invarea = 1.f/normarea; |
||||
float sval = (pnsum[0] - pnsum[normrect.z] - pnsum[mul24(normrect.w, sumstep)] + |
||||
pnsum[mad24(normrect.w, sumstep, normrect.z)])*invarea; |
||||
float sqval = (sqsum[mad24(iy + normrect.y, sqsumstep, ix + normrect.x)])*invarea; |
||||
float nf = (float)normarea * sqrt(max(sqval - sval * sval, 0.f)); |
||||
float4 weight; |
||||
int4 ofs; |
||||
nf = nf > 0 ? nf : 1.f; |
||||
|
||||
for( stageIdx = 0; stageIdx < nstages; stageIdx++ ) |
||||
{ |
||||
ntrees = stages[stageIdx].ntrees; |
||||
s = 0.f; |
||||
for( i = 0; i < ntrees; i++, stump++, bitset += bitsetSize ) |
||||
{ |
||||
f = optfeatures + stump->featureIdx; |
||||
|
||||
weight = f->weight; |
||||
|
||||
// compute LBP feature to val |
||||
s += (bitset[val >> 5] & (1 << (val & 31))) ? stump->left : stump->right; |
||||
} |
||||
|
||||
if( s < stages[stageIdx].threshold ) |
||||
break; |
||||
} |
||||
|
||||
if( stageIdx == nstages ) |
||||
{ |
||||
int nfaces = atomic_inc(facepos); |
||||
if( nfaces < maxFaces ) |
||||
{ |
||||
volatile __global int* face = facepos + 1 + nfaces*4; |
||||
face[0] = convert_int_rte(ix*factor); |
||||
face[1] = convert_int_rte(iy*factor); |
||||
face[2] = convert_int_rte(windowsize.x*factor); |
||||
face[3] = convert_int_rte(windowsize.y*factor); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
#endif |
Loading…
Reference in new issue