// 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. // Third party copyrights are property of their respective owners. // // @Authors // Niko Li, newlife20080214@gmail.com // Wang Weiyan, wangweiyanster@gmail.com // Jia Haipeng, jiahaipeng95@gmail.com // Nathan, liujun@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 oclMaterials 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. // // #pragma OPENCL EXTENSION cl_amd_printf : enable #define CV_HAAR_FEATURE_MAX 3 #define calc_sum(rect,offset) (sum[(rect).p0+offset] - sum[(rect).p1+offset] - sum[(rect).p2+offset] + sum[(rect).p3+offset]) #define calc_sum1(rect,offset,i) (sum[(rect).p0[i]+offset] - sum[(rect).p1[i]+offset] - sum[(rect).p2[i]+offset] + sum[(rect).p3[i]+offset]) typedef int sumtype; typedef float sqsumtype; typedef struct __attribute__((aligned (128))) GpuHidHaarFeature { struct __attribute__((aligned (32))) { int p0 __attribute__((aligned (4))); int p1 __attribute__((aligned (4))); int p2 __attribute__((aligned (4))); int p3 __attribute__((aligned (4))); float weight __attribute__((aligned (4))); } rect[CV_HAAR_FEATURE_MAX] __attribute__((aligned (32))); } GpuHidHaarFeature; typedef struct __attribute__((aligned (128) )) GpuHidHaarTreeNode { int p[CV_HAAR_FEATURE_MAX][4] __attribute__((aligned (64))); float weight[CV_HAAR_FEATURE_MAX] /*__attribute__((aligned (16)))*/; float threshold /*__attribute__((aligned (4)))*/; float alpha[2] __attribute__((aligned (8))); int left __attribute__((aligned (4))); int right __attribute__((aligned (4))); } GpuHidHaarTreeNode; typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier { int count __attribute__((aligned (4))); GpuHidHaarTreeNode* node __attribute__((aligned (8))); float* alpha __attribute__((aligned (8))); } GpuHidHaarClassifier; typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier { int count __attribute__((aligned (4))); float threshold __attribute__((aligned (4))); int two_rects __attribute__((aligned (4))); int reserved0 __attribute__((aligned (8))); int reserved1 __attribute__((aligned (8))); int reserved2 __attribute__((aligned (8))); int reserved3 __attribute__((aligned (8))); } GpuHidHaarStageClassifier; typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade { int count __attribute__((aligned (4))); int is_stump_based __attribute__((aligned (4))); int has_tilted_features __attribute__((aligned (4))); int is_tree __attribute__((aligned (4))); int pq0 __attribute__((aligned (4))); int pq1 __attribute__((aligned (4))); int pq2 __attribute__((aligned (4))); int pq3 __attribute__((aligned (4))); int p0 __attribute__((aligned (4))); int p1 __attribute__((aligned (4))); int p2 __attribute__((aligned (4))); int p3 __attribute__((aligned (4))); float inv_window_area __attribute__((aligned (4))); } GpuHidHaarClassifierCascade; __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCascade( global GpuHidHaarStageClassifier * stagecascadeptr, global int4 * info, global GpuHidHaarTreeNode * nodeptr, global const int * restrict sum1, global const float * restrict sqsum1, global int4 * candidate, const int pixelstep, const int loopcount, const int start_stage, const int split_stage, const int end_stage, const int startnode, const int splitnode, const int4 p, const int4 pq, const float correction) { int grpszx = get_local_size(0); int grpszy = get_local_size(1); int grpnumx = get_num_groups(0); int grpidx = get_group_id(0); int lclidx = get_local_id(0); int lclidy = get_local_id(1); int lcl_sz = mul24(grpszx,grpszy); int lcl_id = mad24(lclidy,grpszx,lclidx); __local int lclshare[1024]; __local int* lcldata = lclshare;//for save win data __local int* glboutindex = lcldata + 28*28;//for save global out index __local int* lclcount = glboutindex + 1;//for save the numuber of temp pass pixel __local int* lcloutindex = lclcount + 1;//for save info of temp pass pixel __local float* partialsum = (__local float*)(lcloutindex + (lcl_sz<<1)); glboutindex[0]=0; int outputoff = mul24(grpidx,256); //assume window size is 20X20 #define WINDOWSIZE 20+1 //make sure readwidth is the multiple of 4 //ystep =1, from host code int readwidth = ((grpszx-1 + WINDOWSIZE+3)>>2)<<2; int readheight = grpszy-1+WINDOWSIZE; int read_horiz_cnt = readwidth >> 2;//each read int4 int total_read = mul24(read_horiz_cnt,readheight); int read_loop = (total_read + lcl_sz - 1) >> 6; candidate[outputoff+(lcl_id<<2)] = (int4)0; candidate[outputoff+(lcl_id<<2)+1] = (int4)0; candidate[outputoff+(lcl_id<<2)+2] = (int4)0; candidate[outputoff+(lcl_id<<2)+3] = (int4)0; for(int scalei = 0; scalei > 16; int height = scaleinfo1.x & 0xffff; int grpnumperline =(scaleinfo1.y & 0xffff0000) >> 16; int totalgrp = scaleinfo1.y & 0xffff; int imgoff = scaleinfo1.z; float factor = as_float(scaleinfo1.w); __global const int * sum = sum1 + imgoff; __global const float * sqsum = sqsum1 + imgoff; for(int grploop=grpidx; grploop=0.f ? sqrt(variance_norm_factor) : 1.f; for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ ) { float stage_sum = 0.f; int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); float stagethreshold = as_float(stageinfo.y); for(int nodeloop = 0; nodeloop < stageinfo.x; nodeloop++ ) { __global GpuHidHaarTreeNode* currentnodeptr = (nodeptr + nodecounter); int4 info1 = *(__global int4*)(&(currentnodeptr->p[0][0])); int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); int4 info3 = *(__global int4*)(&(currentnodeptr->p[2][0])); float4 w = *(__global float4*)(&(currentnodeptr->weight[0])); float2 alpha2 = *(__global float2*)(&(currentnodeptr->alpha[0])); float nodethreshold = w.w * variance_norm_factor; info1.x +=lcl_off; info1.z +=lcl_off; info2.x +=lcl_off; info2.z +=lcl_off; float classsum = (lcldata[mad24(info1.y,readwidth,info1.x)] - lcldata[mad24(info1.y,readwidth,info1.z)] - lcldata[mad24(info1.w,readwidth,info1.x)] + lcldata[mad24(info1.w,readwidth,info1.z)]) * w.x; classsum += (lcldata[mad24(info2.y,readwidth,info2.x)] - lcldata[mad24(info2.y,readwidth,info2.z)] - lcldata[mad24(info2.w,readwidth,info2.x)] + lcldata[mad24(info2.w,readwidth,info2.z)]) * w.y; info3.x +=lcl_off; info3.z +=lcl_off; classsum += (lcldata[mad24(info3.y,readwidth,info3.x)] - lcldata[mad24(info3.y,readwidth,info3.z)] - lcldata[mad24(info3.w,readwidth,info3.x)] + lcldata[mad24(info3.w,readwidth,info3.z)]) * w.z; stage_sum += classsum >= nodethreshold ? alpha2.y : alpha2.x; nodecounter++; } result = (stage_sum >= stagethreshold); } if(result && (x < width) && (y < height)) { int queueindex = atomic_inc(lclcount); lcloutindex[queueindex<<1] = (lclidy << 16) | lclidx; lcloutindex[(queueindex<<1)+1] = as_int(variance_norm_factor); } barrier(CLK_LOCAL_MEM_FENCE); int queuecount = lclcount[0]; barrier(CLK_LOCAL_MEM_FENCE); nodecounter = splitnode; for(int stageloop = split_stage; stageloop< end_stage && queuecount>0; stageloop++) { lclcount[0]=0; barrier(CLK_LOCAL_MEM_FENCE); int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); float stagethreshold = as_float(stageinfo.y); int perfscale = queuecount > 4 ? 3 : 2; int queuecount_loop = (queuecount + (1<> perfscale; int lcl_compute_win = lcl_sz >> perfscale; int lcl_compute_win_id = (lcl_id >>(6-perfscale)); int lcl_loops = (stageinfo.x + lcl_compute_win -1) >> (6-perfscale); int lcl_compute_id = lcl_id - (lcl_compute_win_id << (6-perfscale)); for(int queueloop=0; queueloop>16),readwidth,temp_coord & 0xffff); if(lcl_compute_win_id < queuecount) { int tempnodecounter = lcl_compute_id; float part_sum = 0.f; for(int lcl_loop=0; lcl_loopp[0][0])); int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); int4 info3 = *(__global int4*)(&(currentnodeptr->p[2][0])); float4 w = *(__global float4*)(&(currentnodeptr->weight[0])); float2 alpha2 = *(__global float2*)(&(currentnodeptr->alpha[0])); float nodethreshold = w.w * variance_norm_factor; info1.x +=queue_pixel; info1.z +=queue_pixel; info2.x +=queue_pixel; info2.z +=queue_pixel; float classsum = (lcldata[mad24(info1.y,readwidth,info1.x)] - lcldata[mad24(info1.y,readwidth,info1.z)] - lcldata[mad24(info1.w,readwidth,info1.x)] + lcldata[mad24(info1.w,readwidth,info1.z)]) * w.x; classsum += (lcldata[mad24(info2.y,readwidth,info2.x)] - lcldata[mad24(info2.y,readwidth,info2.z)] - lcldata[mad24(info2.w,readwidth,info2.x)] + lcldata[mad24(info2.w,readwidth,info2.z)]) * w.y; info3.x +=queue_pixel; info3.z +=queue_pixel; classsum += (lcldata[mad24(info3.y,readwidth,info3.x)] - lcldata[mad24(info3.y,readwidth,info3.z)] - lcldata[mad24(info3.w,readwidth,info3.x)] + lcldata[mad24(info3.w,readwidth,info3.z)]) * w.z; part_sum += classsum >= nodethreshold ? alpha2.y : alpha2.x; tempnodecounter +=lcl_compute_win; }//end for(int lcl_loop=0;lcl_loop= stagethreshold && (lcl_compute_id==0)) { int queueindex = atomic_inc(lclcount); lcloutindex[queueindex<<1] = temp_coord; lcloutindex[(queueindex<<1)+1] = as_int(variance_norm_factor); } lcl_compute_win_id +=(1<0;stageloop++) if(lcl_id> 16)); temp = glboutindex[0]; int4 candidate_result; candidate_result.zw = (int2)convert_int_rtn(factor*20.f); candidate_result.x = convert_int_rtn(x*factor); candidate_result.y = convert_int_rtn(y*factor); atomic_inc(glboutindex); candidate[outputoff+temp+lcl_id] = candidate_result; } barrier(CLK_LOCAL_MEM_FENCE); }//end for(int grploop=grpidx;grplooptwo_rects) { #pragma unroll for( n = 0; n < stagecascade->count; n++ ) { t1 = *(node + counter); t = t1.threshold * variance_norm_factor; classsum = calc_sum1(t1,p_offset,0) * t1.weight[0]; classsum += calc_sum1(t1, p_offset,1) * t1.weight[1]; stage_sum += classsum >= t ? t1.alpha[1]:t1.alpha[0]; counter++; } } else { #pragma unroll for( n = 0; n < stagecascade->count; n++ ) { t = node[counter].threshold*variance_norm_factor; classsum = calc_sum1(node[counter],p_offset,0) * node[counter].weight[0]; classsum += calc_sum1(node[counter],p_offset,1) * node[counter].weight[1]; if( node[counter].p0[2] ) classsum += calc_sum1(node[counter],p_offset,2) * node[counter].weight[2]; stage_sum += classsum >= t ? node[counter].alpha[1]:node[counter].alpha[0];// modify counter++; } } */ /* __kernel void gpuRunHaarClassifierCascade_ScaleWindow( constant GpuHidHaarClassifierCascade * _cascade, global GpuHidHaarStageClassifier * stagecascadeptr, //global GpuHidHaarClassifier * classifierptr, global GpuHidHaarTreeNode * nodeptr, global int * sum, global float * sqsum, global int * _candidate, int pixel_step, int cols, int rows, int start_stage, int end_stage, //int counts, int nodenum, int ystep, int detect_width, //int detect_height, int loopcount, int outputstep) //float scalefactor) { unsigned int x1 = get_global_id(0); unsigned int y1 = get_global_id(1); int p_offset; int m, n; int result; int counter; float mean, variance_norm_factor; for(int i=0;ip1 - cascade->p0; int window_height = window_width; result = 1; counter = 0; unsigned int x = mul24(x1,ystep); unsigned int y = mul24(y1,ystep); if((x < cols - window_width - 1) && (y < rows - window_height -1)) { global GpuHidHaarStageClassifier *stagecascade = stagecascadeptr +cascade->count*i+ start_stage; //global GpuHidHaarClassifier *classifier = classifierptr; global GpuHidHaarTreeNode *node = nodeptr + nodenum*i; p_offset = mad24(y, pixel_step, x);// modify mean = (*(sum + p_offset + (int)cascade->p0) - *(sum + p_offset + (int)cascade->p1) - *(sum + p_offset + (int)cascade->p2) + *(sum + p_offset + (int)cascade->p3)) *cascade->inv_window_area; variance_norm_factor = *(sqsum + p_offset + cascade->p0) - *(sqsum + cascade->p1 + p_offset) - *(sqsum + p_offset + cascade->p2) + *(sqsum + cascade->p3 + p_offset); variance_norm_factor = variance_norm_factor * cascade->inv_window_area - mean * mean; variance_norm_factor = variance_norm_factor >=0.f ? sqrt(variance_norm_factor) : 1;//modify // if( cascade->is_stump_based ) //{ for( m = start_stage; m < end_stage; m++ ) { float stage_sum = 0.f; float t, classsum; GpuHidHaarTreeNode t1; //#pragma unroll for( n = 0; n < stagecascade->count; n++ ) { t1 = *(node + counter); t = t1.threshold * variance_norm_factor; classsum = calc_sum1(t1, p_offset ,0) * t1.weight[0] + calc_sum1(t1, p_offset ,1) * t1.weight[1]; if((t1.p0[2]) && (!stagecascade->two_rects)) classsum += calc_sum1(t1, p_offset, 2) * t1.weight[2]; stage_sum += classsum >= t ? t1.alpha[1] : t1.alpha[0];// modify counter++; } if (stage_sum < stagecascade->threshold) { result = 0; break; } stagecascade++; } if(result) { candidate[4 * (y1 * detect_width + x1)] = x; candidate[4 * (y1 * detect_width + x1) + 1] = y; candidate[4 * (y1 * detect_width + x1)+2] = window_width; candidate[4 * (y1 * detect_width + x1) + 3] = window_height; } //} } } } */