mirror of https://github.com/opencv/opencv.git
Merge pull request #2234 from KonstantinMatskevich:ocl_tapi_hog
commit
22146e4b18
5 changed files with 1526 additions and 18 deletions
@ -0,0 +1,94 @@ |
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Fangfang Bai, fangfang@multicorewareinc.com
|
||||
// Jin Ma, jin@multicorewareinc.com
|
||||
//
|
||||
// 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 the copyright holders 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*/
|
||||
|
||||
#include "perf_precomp.hpp" |
||||
#include "opencv2/ts/ocl_perf.hpp" |
||||
|
||||
#ifdef HAVE_OPENCL |
||||
|
||||
namespace cvtest { |
||||
namespace ocl { |
||||
///////////// HOG////////////////////////
|
||||
|
||||
struct RectLess : |
||||
public std::binary_function<cv::Rect, cv::Rect, bool> |
||||
{ |
||||
bool operator()(const cv::Rect& a, |
||||
const cv::Rect& b) const |
||||
{ |
||||
if (a.x != b.x) |
||||
return a.x < b.x; |
||||
else if (a.y != b.y) |
||||
return a.y < b.y; |
||||
else if (a.width != b.width) |
||||
return a.width < b.width; |
||||
else |
||||
return a.height < b.height; |
||||
} |
||||
}; |
||||
|
||||
OCL_PERF_TEST(HOGFixture, HOG) |
||||
{ |
||||
UMat src; |
||||
imread(getDataPath("gpu/hog/road.png"), cv::IMREAD_GRAYSCALE).copyTo(src); |
||||
ASSERT_FALSE(src.empty()); |
||||
|
||||
vector<cv::Rect> found_locations; |
||||
declare.in(src); |
||||
|
||||
HOGDescriptor hog; |
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector()); |
||||
|
||||
OCL_TEST_CYCLE() hog.detectMultiScale(src, found_locations); |
||||
|
||||
std::sort(found_locations.begin(), found_locations.end(), RectLess()); |
||||
SANITY_CHECK(found_locations, 1 + DBL_EPSILON); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,726 @@ |
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved. |
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. |
||||
// Third party copyrights are property of their respective owners. |
||||
// |
||||
// @Authors |
||||
// Wenju He, wenju@multicorewareinc.com |
||||
// |
||||
// 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 the copyright holders 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*/ |
||||
|
||||
#define CELL_WIDTH 8 |
||||
#define CELL_HEIGHT 8 |
||||
#define CELLS_PER_BLOCK_X 2 |
||||
#define CELLS_PER_BLOCK_Y 2 |
||||
#define NTHREADS 256 |
||||
#define CV_PI_F 3.1415926535897932384626433832795f |
||||
|
||||
#ifdef INTEL_DEVICE |
||||
#define QANGLE_TYPE int |
||||
#define QANGLE_TYPE2 int2 |
||||
#else |
||||
#define QANGLE_TYPE uchar |
||||
#define QANGLE_TYPE2 uchar2 |
||||
#endif |
||||
|
||||
//---------------------------------------------------------------------------- |
||||
// Histogram computation |
||||
// 12 threads for a cell, 12x4 threads per block |
||||
// Use pre-computed gaussian and interp_weight lookup tables |
||||
__kernel void compute_hists_lut_kernel( |
||||
const int cblock_stride_x, const int cblock_stride_y, |
||||
const int cnbins, const int cblock_hist_size, const int img_block_width, |
||||
const int blocks_in_group, const int blocks_total, |
||||
const int grad_quadstep, const int qangle_step, |
||||
__global const float* grad, __global const QANGLE_TYPE* qangle, |
||||
__global const float* gauss_w_lut, |
||||
__global float* block_hists, __local float* smem) |
||||
{ |
||||
const int lx = get_local_id(0); |
||||
const int lp = lx / 24; /* local group id */ |
||||
const int gid = get_group_id(0) * blocks_in_group + lp;/* global group id */ |
||||
const int gidY = gid / img_block_width; |
||||
const int gidX = gid - gidY * img_block_width; |
||||
|
||||
const int lidX = lx - lp * 24; |
||||
const int lidY = get_local_id(1); |
||||
|
||||
const int cell_x = lidX / 12; |
||||
const int cell_y = lidY; |
||||
const int cell_thread_x = lidX - cell_x * 12; |
||||
|
||||
__local float* hists = smem + lp * cnbins * (CELLS_PER_BLOCK_X * |
||||
CELLS_PER_BLOCK_Y * 12 + CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y); |
||||
__local float* final_hist = hists + cnbins * |
||||
(CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12); |
||||
|
||||
const int offset_x = gidX * cblock_stride_x + (cell_x << 2) + cell_thread_x; |
||||
const int offset_y = gidY * cblock_stride_y + (cell_y << 2); |
||||
|
||||
__global const float* grad_ptr = (gid < blocks_total) ? |
||||
grad + offset_y * grad_quadstep + (offset_x << 1) : grad; |
||||
__global const QANGLE_TYPE* qangle_ptr = (gid < blocks_total) ? |
||||
qangle + offset_y * qangle_step + (offset_x << 1) : qangle; |
||||
|
||||
__local float* hist = hists + 12 * (cell_y * CELLS_PER_BLOCK_Y + cell_x) + |
||||
cell_thread_x; |
||||
for (int bin_id = 0; bin_id < cnbins; ++bin_id) |
||||
hist[bin_id * 48] = 0.f; |
||||
|
||||
const int dist_x = -4 + cell_thread_x - 4 * cell_x; |
||||
const int dist_center_x = dist_x - 4 * (1 - 2 * cell_x); |
||||
|
||||
const int dist_y_begin = -4 - 4 * lidY; |
||||
for (int dist_y = dist_y_begin; dist_y < dist_y_begin + 12; ++dist_y) |
||||
{ |
||||
float2 vote = (float2) (grad_ptr[0], grad_ptr[1]); |
||||
QANGLE_TYPE2 bin = (QANGLE_TYPE2) (qangle_ptr[0], qangle_ptr[1]); |
||||
|
||||
grad_ptr += grad_quadstep; |
||||
qangle_ptr += qangle_step; |
||||
|
||||
int dist_center_y = dist_y - 4 * (1 - 2 * cell_y); |
||||
|
||||
int idx = (dist_center_y + 8) * 16 + (dist_center_x + 8); |
||||
float gaussian = gauss_w_lut[idx]; |
||||
idx = (dist_y + 8) * 16 + (dist_x + 8); |
||||
float interp_weight = gauss_w_lut[256+idx]; |
||||
|
||||
hist[bin.x * 48] += gaussian * interp_weight * vote.x; |
||||
hist[bin.y * 48] += gaussian * interp_weight * vote.y; |
||||
} |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
volatile __local float* hist_ = hist; |
||||
for (int bin_id = 0; bin_id < cnbins; ++bin_id, hist_ += 48) |
||||
{ |
||||
if (cell_thread_x < 6) |
||||
hist_[0] += hist_[6]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (cell_thread_x < 3) |
||||
hist_[0] += hist_[3]; |
||||
#ifdef CPU |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#endif |
||||
if (cell_thread_x == 0) |
||||
final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] = |
||||
hist_[0] + hist_[1] + hist_[2]; |
||||
} |
||||
#ifdef CPU |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#endif |
||||
|
||||
int tid = (cell_y * CELLS_PER_BLOCK_Y + cell_x) * 12 + cell_thread_x; |
||||
if ((tid < cblock_hist_size) && (gid < blocks_total)) |
||||
{ |
||||
__global float* block_hist = block_hists + |
||||
(gidY * img_block_width + gidX) * cblock_hist_size; |
||||
block_hist[tid] = final_hist[tid]; |
||||
} |
||||
} |
||||
|
||||
//------------------------------------------------------------- |
||||
// Normalization of histograms via L2Hys_norm |
||||
// optimized for the case of 9 bins |
||||
__kernel void normalize_hists_36_kernel(__global float* block_hists, |
||||
const float threshold, __local float *squares) |
||||
{ |
||||
const int tid = get_local_id(0); |
||||
const int gid = get_global_id(0); |
||||
const int bid = tid / 36; /* block-hist id, (0 - 6) */ |
||||
const int boffset = bid * 36; /* block-hist offset in the work-group */ |
||||
const int hid = tid - boffset; /* histogram bin id, (0 - 35) */ |
||||
|
||||
float elem = block_hists[gid]; |
||||
squares[tid] = elem * elem; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
__local float* smem = squares + boffset; |
||||
float sum = smem[hid]; |
||||
if (hid < 18) |
||||
smem[hid] = sum = sum + smem[hid + 18]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (hid < 9) |
||||
smem[hid] = sum = sum + smem[hid + 9]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (hid < 4) |
||||
smem[hid] = sum + smem[hid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8]; |
||||
|
||||
elem = elem / (sqrt(sum) + 3.6f); |
||||
elem = min(elem, threshold); |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
squares[tid] = elem * elem; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
sum = smem[hid]; |
||||
if (hid < 18) |
||||
smem[hid] = sum = sum + smem[hid + 18]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (hid < 9) |
||||
smem[hid] = sum = sum + smem[hid + 9]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (hid < 4) |
||||
smem[hid] = sum + smem[hid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8]; |
||||
|
||||
block_hists[gid] = elem / (sqrt(sum) + 1e-3f); |
||||
} |
||||
|
||||
//------------------------------------------------------------- |
||||
// Normalization of histograms via L2Hys_norm |
||||
// |
||||
inline float reduce_smem(volatile __local float* smem, int size) |
||||
{ |
||||
unsigned int tid = get_local_id(0); |
||||
float sum = smem[tid]; |
||||
|
||||
if (size >= 512) { if (tid < 256) smem[tid] = sum = sum + smem[tid + 256]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 256) { if (tid < 128) smem[tid] = sum = sum + smem[tid + 128]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 128) { if (tid < 64) smem[tid] = sum = sum + smem[tid + 64]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
#ifdef CPU |
||||
if (size >= 64) { if (tid < 32) smem[tid] = sum = sum + smem[tid + 32]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 32) { if (tid < 16) smem[tid] = sum = sum + smem[tid + 16]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 16) { if (tid < 8) smem[tid] = sum = sum + smem[tid + 8]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 8) { if (tid < 4) smem[tid] = sum = sum + smem[tid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 4) { if (tid < 2) smem[tid] = sum = sum + smem[tid + 2]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
if (size >= 2) { if (tid < 1) smem[tid] = sum = sum + smem[tid + 1]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); } |
||||
#else |
||||
if (tid < 32) |
||||
{ |
||||
if (size >= 64) smem[tid] = sum = sum + smem[tid + 32]; |
||||
#if WAVE_SIZE < 32 |
||||
} barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (tid < 16) { |
||||
#endif |
||||
if (size >= 32) smem[tid] = sum = sum + smem[tid + 16]; |
||||
if (size >= 16) smem[tid] = sum = sum + smem[tid + 8]; |
||||
if (size >= 8) smem[tid] = sum = sum + smem[tid + 4]; |
||||
if (size >= 4) smem[tid] = sum = sum + smem[tid + 2]; |
||||
if (size >= 2) smem[tid] = sum = sum + smem[tid + 1]; |
||||
} |
||||
#endif |
||||
|
||||
return sum; |
||||
} |
||||
|
||||
__kernel void normalize_hists_kernel( |
||||
const int nthreads, const int block_hist_size, const int img_block_width, |
||||
__global float* block_hists, const float threshold, __local float *squares) |
||||
{ |
||||
const int tid = get_local_id(0); |
||||
const int gidX = get_group_id(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global float* hist = block_hists + (gidY * img_block_width + gidX) * |
||||
block_hist_size + tid; |
||||
|
||||
float elem = 0.f; |
||||
if (tid < block_hist_size) |
||||
elem = hist[0]; |
||||
|
||||
squares[tid] = elem * elem; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
float sum = reduce_smem(squares, nthreads); |
||||
|
||||
float scale = 1.0f / (sqrt(sum) + 0.1f * block_hist_size); |
||||
elem = min(elem * scale, threshold); |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
squares[tid] = elem * elem; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
sum = reduce_smem(squares, nthreads); |
||||
scale = 1.0f / (sqrt(sum) + 1e-3f); |
||||
|
||||
if (tid < block_hist_size) |
||||
hist[0] = elem * scale; |
||||
} |
||||
|
||||
//--------------------------------------------------------------------- |
||||
// Linear SVM based classification |
||||
// 48x96 window, 9 bins and default parameters |
||||
// 180 threads, each thread corresponds to a bin in a row |
||||
__kernel void classify_hists_180_kernel( |
||||
const int cdescr_width, const int cdescr_height, const int cblock_hist_size, |
||||
const int img_win_width, const int img_block_width, |
||||
const int win_block_stride_x, const int win_block_stride_y, |
||||
__global const float * block_hists, __global const float* coefs, |
||||
float free_coef, float threshold, __global uchar* labels) |
||||
{ |
||||
const int tid = get_local_id(0); |
||||
const int gidX = get_group_id(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y * |
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size; |
||||
|
||||
float product = 0.f; |
||||
|
||||
for (int i = 0; i < cdescr_height; i++) |
||||
{ |
||||
product += coefs[i * cdescr_width + tid] * |
||||
hist[i * img_block_width * cblock_hist_size + tid]; |
||||
} |
||||
|
||||
__local float products[180]; |
||||
|
||||
products[tid] = product; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 90) products[tid] = product = product + products[tid + 90]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 45) products[tid] = product = product + products[tid + 45]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
volatile __local float* smem = products; |
||||
#ifdef CPU |
||||
if (tid < 13) smem[tid] = product = product + smem[tid + 32]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (tid < 16) smem[tid] = product = product + smem[tid + 16]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<8) smem[tid] = product = product + smem[tid + 8]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<4) smem[tid] = product = product + smem[tid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<2) smem[tid] = product = product + smem[tid + 2]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#else |
||||
if (tid < 13) |
||||
{ |
||||
smem[tid] = product = product + smem[tid + 32]; |
||||
} |
||||
#if WAVE_SIZE < 32 |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#endif |
||||
if (tid < 16) |
||||
{ |
||||
smem[tid] = product = product + smem[tid + 16]; |
||||
smem[tid] = product = product + smem[tid + 8]; |
||||
smem[tid] = product = product + smem[tid + 4]; |
||||
smem[tid] = product = product + smem[tid + 2]; |
||||
} |
||||
#endif |
||||
|
||||
if (tid == 0){ |
||||
product = product + smem[tid + 1]; |
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); |
||||
} |
||||
} |
||||
|
||||
//--------------------------------------------------------------------- |
||||
// Linear SVM based classification |
||||
// 64x128 window, 9 bins and default parameters |
||||
// 256 threads, 252 of them are used |
||||
__kernel void classify_hists_252_kernel( |
||||
const int cdescr_width, const int cdescr_height, const int cblock_hist_size, |
||||
const int img_win_width, const int img_block_width, |
||||
const int win_block_stride_x, const int win_block_stride_y, |
||||
__global const float * block_hists, __global const float* coefs, |
||||
float free_coef, float threshold, __global uchar* labels) |
||||
{ |
||||
const int tid = get_local_id(0); |
||||
const int gidX = get_group_id(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y * |
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size; |
||||
|
||||
float product = 0.f; |
||||
if (tid < cdescr_width) |
||||
{ |
||||
for (int i = 0; i < cdescr_height; i++) |
||||
product += coefs[i * cdescr_width + tid] * |
||||
hist[i * img_block_width * cblock_hist_size + tid]; |
||||
} |
||||
|
||||
__local float products[NTHREADS]; |
||||
|
||||
products[tid] = product; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 128) products[tid] = product = product + products[tid + 128]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 64) products[tid] = product = product + products[tid + 64]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
volatile __local float* smem = products; |
||||
#ifdef CPU |
||||
if(tid<32) smem[tid] = product = product + smem[tid + 32]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<16) smem[tid] = product = product + smem[tid + 16]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<8) smem[tid] = product = product + smem[tid + 8]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<4) smem[tid] = product = product + smem[tid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<2) smem[tid] = product = product + smem[tid + 2]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#else |
||||
if (tid < 32) |
||||
{ |
||||
smem[tid] = product = product + smem[tid + 32]; |
||||
#if WAVE_SIZE < 32 |
||||
} barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (tid < 16) { |
||||
#endif |
||||
smem[tid] = product = product + smem[tid + 16]; |
||||
smem[tid] = product = product + smem[tid + 8]; |
||||
smem[tid] = product = product + smem[tid + 4]; |
||||
smem[tid] = product = product + smem[tid + 2]; |
||||
} |
||||
#endif |
||||
if (tid == 0){ |
||||
product = product + smem[tid + 1]; |
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); |
||||
} |
||||
} |
||||
|
||||
//--------------------------------------------------------------------- |
||||
// Linear SVM based classification |
||||
// 256 threads |
||||
__kernel void classify_hists_kernel( |
||||
const int cdescr_size, const int cdescr_width, const int cblock_hist_size, |
||||
const int img_win_width, const int img_block_width, |
||||
const int win_block_stride_x, const int win_block_stride_y, |
||||
__global const float * block_hists, __global const float* coefs, |
||||
float free_coef, float threshold, __global uchar* labels) |
||||
{ |
||||
const int tid = get_local_id(0); |
||||
const int gidX = get_group_id(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y * |
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size; |
||||
|
||||
float product = 0.f; |
||||
for (int i = tid; i < cdescr_size; i += NTHREADS) |
||||
{ |
||||
int offset_y = i / cdescr_width; |
||||
int offset_x = i - offset_y * cdescr_width; |
||||
product += coefs[i] * |
||||
hist[offset_y * img_block_width * cblock_hist_size + offset_x]; |
||||
} |
||||
|
||||
__local float products[NTHREADS]; |
||||
|
||||
products[tid] = product; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 128) products[tid] = product = product + products[tid + 128]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
if (tid < 64) products[tid] = product = product + products[tid + 64]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
|
||||
volatile __local float* smem = products; |
||||
#ifdef CPU |
||||
if(tid<32) smem[tid] = product = product + smem[tid + 32]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<16) smem[tid] = product = product + smem[tid + 16]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<8) smem[tid] = product = product + smem[tid + 8]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<4) smem[tid] = product = product + smem[tid + 4]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if(tid<2) smem[tid] = product = product + smem[tid + 2]; |
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
#else |
||||
if (tid < 32) |
||||
{ |
||||
smem[tid] = product = product + smem[tid + 32]; |
||||
#if WAVE_SIZE < 32 |
||||
} barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (tid < 16) { |
||||
#endif |
||||
smem[tid] = product = product + smem[tid + 16]; |
||||
smem[tid] = product = product + smem[tid + 8]; |
||||
smem[tid] = product = product + smem[tid + 4]; |
||||
smem[tid] = product = product + smem[tid + 2]; |
||||
} |
||||
#endif |
||||
if (tid == 0){ |
||||
smem[tid] = product = product + smem[tid + 1]; |
||||
labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); |
||||
} |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------- |
||||
// Extract descriptors |
||||
|
||||
__kernel void extract_descrs_by_rows_kernel( |
||||
const int cblock_hist_size, const int descriptors_quadstep, |
||||
const int cdescr_size, const int cdescr_width, const int img_block_width, |
||||
const int win_block_stride_x, const int win_block_stride_y, |
||||
__global const float* block_hists, __global float* descriptors) |
||||
{ |
||||
int tid = get_local_id(0); |
||||
int gidX = get_group_id(0); |
||||
int gidY = get_group_id(1); |
||||
|
||||
// Get left top corner of the window in src |
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y * |
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size; |
||||
|
||||
// Get left top corner of the window in dst |
||||
__global float* descriptor = descriptors + |
||||
(gidY * get_num_groups(0) + gidX) * descriptors_quadstep; |
||||
|
||||
// Copy elements from src to dst |
||||
for (int i = tid; i < cdescr_size; i += NTHREADS) |
||||
{ |
||||
int offset_y = i / cdescr_width; |
||||
int offset_x = i - offset_y * cdescr_width; |
||||
descriptor[i] = hist[offset_y * img_block_width * cblock_hist_size + offset_x]; |
||||
} |
||||
} |
||||
|
||||
__kernel void extract_descrs_by_cols_kernel( |
||||
const int cblock_hist_size, const int descriptors_quadstep, const int cdescr_size, |
||||
const int cnblocks_win_x, const int cnblocks_win_y, const int img_block_width, |
||||
const int win_block_stride_x, const int win_block_stride_y, |
||||
__global const float* block_hists, __global float* descriptors) |
||||
{ |
||||
int tid = get_local_id(0); |
||||
int gidX = get_group_id(0); |
||||
int gidY = get_group_id(1); |
||||
|
||||
// Get left top corner of the window in src |
||||
__global const float* hist = block_hists + (gidY * win_block_stride_y * |
||||
img_block_width + gidX * win_block_stride_x) * cblock_hist_size; |
||||
|
||||
// Get left top corner of the window in dst |
||||
__global float* descriptor = descriptors + |
||||
(gidY * get_num_groups(0) + gidX) * descriptors_quadstep; |
||||
|
||||
// Copy elements from src to dst |
||||
for (int i = tid; i < cdescr_size; i += NTHREADS) |
||||
{ |
||||
int block_idx = i / cblock_hist_size; |
||||
int idx_in_block = i - block_idx * cblock_hist_size; |
||||
|
||||
int y = block_idx / cnblocks_win_x; |
||||
int x = block_idx - y * cnblocks_win_x; |
||||
|
||||
descriptor[(x * cnblocks_win_y + y) * cblock_hist_size + idx_in_block] = |
||||
hist[(y * img_block_width + x) * cblock_hist_size + idx_in_block]; |
||||
} |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------- |
||||
// Gradients computation |
||||
|
||||
__kernel void compute_gradients_8UC4_kernel( |
||||
const int height, const int width, |
||||
const int img_step, const int grad_quadstep, const int qangle_step, |
||||
const __global uchar4 * img, __global float * grad, __global QANGLE_TYPE * qangle, |
||||
const float angle_scale, const char correct_gamma, const int cnbins) |
||||
{ |
||||
const int x = get_global_id(0); |
||||
const int tid = get_local_id(0); |
||||
const int gSizeX = get_local_size(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global const uchar4* row = img + gidY * img_step; |
||||
|
||||
__local float sh_row[(NTHREADS + 2) * 3]; |
||||
|
||||
uchar4 val; |
||||
if (x < width) |
||||
val = row[x]; |
||||
else |
||||
val = row[width - 2]; |
||||
|
||||
sh_row[tid + 1] = val.x; |
||||
sh_row[tid + 1 + (NTHREADS + 2)] = val.y; |
||||
sh_row[tid + 1 + 2 * (NTHREADS + 2)] = val.z; |
||||
|
||||
if (tid == 0) |
||||
{ |
||||
val = row[max(x - 1, 1)]; |
||||
sh_row[0] = val.x; |
||||
sh_row[(NTHREADS + 2)] = val.y; |
||||
sh_row[2 * (NTHREADS + 2)] = val.z; |
||||
} |
||||
|
||||
if (tid == gSizeX - 1) |
||||
{ |
||||
val = row[min(x + 1, width - 2)]; |
||||
sh_row[gSizeX + 1] = val.x; |
||||
sh_row[gSizeX + 1 + (NTHREADS + 2)] = val.y; |
||||
sh_row[gSizeX + 1 + 2 * (NTHREADS + 2)] = val.z; |
||||
} |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (x < width) |
||||
{ |
||||
float3 a = (float3) (sh_row[tid], sh_row[tid + (NTHREADS + 2)], |
||||
sh_row[tid + 2 * (NTHREADS + 2)]); |
||||
float3 b = (float3) (sh_row[tid + 2], sh_row[tid + 2 + (NTHREADS + 2)], |
||||
sh_row[tid + 2 + 2 * (NTHREADS + 2)]); |
||||
|
||||
float3 dx; |
||||
if (correct_gamma == 1) |
||||
dx = sqrt(b) - sqrt(a); |
||||
else |
||||
dx = b - a; |
||||
|
||||
float3 dy = (float3) 0.f; |
||||
|
||||
if (gidY > 0 && gidY < height - 1) |
||||
{ |
||||
a = convert_float3(img[(gidY - 1) * img_step + x].xyz); |
||||
b = convert_float3(img[(gidY + 1) * img_step + x].xyz); |
||||
|
||||
if (correct_gamma == 1) |
||||
dy = sqrt(b) - sqrt(a); |
||||
else |
||||
dy = b - a; |
||||
} |
||||
|
||||
float best_dx = dx.x; |
||||
float best_dy = dy.x; |
||||
|
||||
float mag0 = dx.x * dx.x + dy.x * dy.x; |
||||
float mag1 = dx.y * dx.y + dy.y * dy.y; |
||||
if (mag0 < mag1) |
||||
{ |
||||
best_dx = dx.y; |
||||
best_dy = dy.y; |
||||
mag0 = mag1; |
||||
} |
||||
|
||||
mag1 = dx.z * dx.z + dy.z * dy.z; |
||||
if (mag0 < mag1) |
||||
{ |
||||
best_dx = dx.z; |
||||
best_dy = dy.z; |
||||
mag0 = mag1; |
||||
} |
||||
|
||||
mag0 = sqrt(mag0); |
||||
|
||||
float ang = (atan2(best_dy, best_dx) + CV_PI_F) * angle_scale - 0.5f; |
||||
int hidx = (int)floor(ang); |
||||
ang -= hidx; |
||||
hidx = (hidx + cnbins) % cnbins; |
||||
|
||||
qangle[(gidY * qangle_step + x) << 1] = hidx; |
||||
qangle[((gidY * qangle_step + x) << 1) + 1] = (hidx + 1) % cnbins; |
||||
grad[(gidY * grad_quadstep + x) << 1] = mag0 * (1.f - ang); |
||||
grad[((gidY * grad_quadstep + x) << 1) + 1] = mag0 * ang; |
||||
} |
||||
} |
||||
|
||||
__kernel void compute_gradients_8UC1_kernel( |
||||
const int height, const int width, |
||||
const int img_step, const int grad_quadstep, const int qangle_step, |
||||
__global const uchar * img, __global float * grad, __global QANGLE_TYPE * qangle, |
||||
const float angle_scale, const char correct_gamma, const int cnbins) |
||||
{ |
||||
const int x = get_global_id(0); |
||||
const int tid = get_local_id(0); |
||||
const int gSizeX = get_local_size(0); |
||||
const int gidY = get_group_id(1); |
||||
|
||||
__global const uchar* row = img + gidY * img_step; |
||||
|
||||
__local float sh_row[NTHREADS + 2]; |
||||
|
||||
if (x < width) |
||||
sh_row[tid + 1] = row[x]; |
||||
else |
||||
sh_row[tid + 1] = row[width - 2]; |
||||
|
||||
if (tid == 0) |
||||
sh_row[0] = row[max(x - 1, 1)]; |
||||
|
||||
if (tid == gSizeX - 1) |
||||
sh_row[gSizeX + 1] = row[min(x + 1, width - 2)]; |
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE); |
||||
if (x < width) |
||||
{ |
||||
float dx; |
||||
|
||||
if (correct_gamma == 1) |
||||
dx = sqrt(sh_row[tid + 2]) - sqrt(sh_row[tid]); |
||||
else |
||||
dx = sh_row[tid + 2] - sh_row[tid]; |
||||
|
||||
float dy = 0.f; |
||||
if (gidY > 0 && gidY < height - 1) |
||||
{ |
||||
float a = (float) img[ (gidY + 1) * img_step + x ]; |
||||
float b = (float) img[ (gidY - 1) * img_step + x ]; |
||||
if (correct_gamma == 1) |
||||
dy = sqrt(a) - sqrt(b); |
||||
else |
||||
dy = a - b; |
||||
} |
||||
float mag = sqrt(dx * dx + dy * dy); |
||||
|
||||
float ang = (atan2(dy, dx) + CV_PI_F) * angle_scale - 0.5f; |
||||
int hidx = (int)floor(ang); |
||||
ang -= hidx; |
||||
hidx = (hidx + cnbins) % cnbins; |
||||
|
||||
qangle[ (gidY * qangle_step + x) << 1 ] = hidx; |
||||
qangle[ ((gidY * qangle_step + x) << 1) + 1 ] = (hidx + 1) % cnbins; |
||||
grad[ (gidY * grad_quadstep + x) << 1 ] = mag * (1.f - ang); |
||||
grad[ ((gidY * grad_quadstep + x) << 1) + 1 ] = mag * ang; |
||||
} |
||||
} |
@ -0,0 +1,121 @@ |
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Shengen Yan, yanshengen@gmail.com
|
||||
// Jiang Liyuan,jlyuan001.good@163.com
|
||||
// Rock Li, Rock.Li@amd.com
|
||||
// Zailong Wu, bullet@yeah.net
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
//
|
||||
// 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 the copyright holders 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*/
|
||||
|
||||
#include "test_precomp.hpp" |
||||
#include "opencv2/ts/ocl_test.hpp" |
||||
|
||||
#ifdef HAVE_OPENCL |
||||
|
||||
namespace cvtest { |
||||
namespace ocl { |
||||
|
||||
///////////////////// HOG /////////////////////////////
|
||||
PARAM_TEST_CASE(HOG, Size, MatType) |
||||
{ |
||||
Size winSize; |
||||
int type; |
||||
Mat img; |
||||
UMat uimg; |
||||
virtual void SetUp() |
||||
{ |
||||
winSize = GET_PARAM(0); |
||||
type = GET_PARAM(1); |
||||
img = readImage("cascadeandhog/images/image_00000000_0.png", IMREAD_GRAYSCALE); |
||||
ASSERT_FALSE(img.empty()); |
||||
img.copyTo(uimg); |
||||
} |
||||
}; |
||||
|
||||
OCL_TEST_P(HOG, GetDescriptors) |
||||
{ |
||||
HOGDescriptor hog; |
||||
hog.gammaCorrection = true; |
||||
|
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector()); |
||||
|
||||
std::vector<float> cpu_descriptors; |
||||
std::vector<float> gpu_descriptors; |
||||
|
||||
OCL_OFF(hog.compute(img, cpu_descriptors, hog.winSize)); |
||||
OCL_ON(hog.compute(uimg, gpu_descriptors, hog.winSize)); |
||||
|
||||
Mat cpu_desc(cpu_descriptors), gpu_desc(gpu_descriptors); |
||||
|
||||
EXPECT_MAT_SIMILAR(cpu_desc, gpu_desc, 1e-1); |
||||
} |
||||
|
||||
OCL_TEST_P(HOG, Detect) |
||||
{ |
||||
HOGDescriptor hog; |
||||
hog.winSize = winSize; |
||||
hog.gammaCorrection = true; |
||||
|
||||
if (winSize.width == 48 && winSize.height == 96) |
||||
hog.setSVMDetector(hog.getDaimlerPeopleDetector()); |
||||
else |
||||
hog.setSVMDetector(hog.getDefaultPeopleDetector()); |
||||
|
||||
std::vector<Rect> cpu_found; |
||||
std::vector<Rect> gpu_found; |
||||
|
||||
OCL_OFF(hog.detectMultiScale(img, cpu_found, 0, Size(8, 8), Size(0, 0), 1.05, 6)); |
||||
OCL_ON(hog.detectMultiScale(uimg, gpu_found, 0, Size(8, 8), Size(0, 0), 1.05, 6)); |
||||
|
||||
EXPECT_LT(checkRectSimilarity(img.size(), cpu_found, gpu_found), 1.0); |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(OCL_ObjDetect, HOG, testing::Combine( |
||||
testing::Values(Size(64, 128), Size(48, 96)), |
||||
testing::Values( MatType(CV_8UC1) ) ) ); |
||||
|
||||
}} |
||||
#endif |
Loading…
Reference in new issue