1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
14 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
18 // Wenju He, wenju@multicorewareinc.com
20 // Redistribution and use in source and binary forms, with or without modification,
21 // are permitted provided that the following conditions are met:
23 // * Redistribution's of source code must retain the above copyright notice,
24 // this list of conditions and the following disclaimer.
26 // * Redistribution's in binary form must reproduce the above copyright notice,
27 // this list of conditions and the following disclaimer in the documentation
28 // and/or other materials provided with the distribution.
30 // * The name of the copyright holders may not be used to endorse or promote products
31 // derived from this software without specific prior written permission.
33 // This software is provided by the copyright holders and contributors as is and
34 // any express or implied warranties, including, but not limited to, the implied
35 // warranties of merchantability and fitness for a particular purpose are disclaimed.
36 // In no event shall the Intel Corporation or contributors be liable for any direct,
37 // indirect, incidental, special, exemplary, or consequential damages
38 // (including, but not limited to, procurement of substitute goods or services;
39 // loss of use, data, or profits; or business interruption) however caused
40 // and on any theory of liability, whether in contract, strict liability,
41 // or tort (including negligence or otherwise) arising in any way out of
42 // the use of this software, even if advised of the possibility of such damage.
48 #define CELLS_PER_BLOCK_X 2
49 #define CELLS_PER_BLOCK_Y 2
51 #define CV_PI_F 3.1415926535897932384626433832795f
53 //----------------------------------------------------------------------------
54 // Histogram computation
55 // 12 threads for a cell, 12x4 threads per block
56 // Use pre-computed gaussian and interp_weight lookup tables
57 __kernel void compute_hists_lut_kernel(
58 const int cblock_stride_x, const int cblock_stride_y,
59 const int cnbins, const int cblock_hist_size, const int img_block_width,
60 const int blocks_in_group, const int blocks_total,
61 const int grad_quadstep, const int qangle_step,
62 __global const float* grad, __global const uchar* qangle,
63 __global const float* gauss_w_lut,
64 __global float* block_hists, __local float* smem)
66 const int lx = get_local_id(0);
67 const int lp = lx / 24; /* local group id */
68 const int gid = get_group_id(0) * blocks_in_group + lp;/* global group id */
69 const int gidY = gid / img_block_width;
70 const int gidX = gid - gidY * img_block_width;
72 const int lidX = lx - lp * 24;
73 const int lidY = get_local_id(1);
75 const int cell_x = lidX / 12;
76 const int cell_y = lidY;
77 const int cell_thread_x = lidX - cell_x * 12;
79 __local float* hists = smem + lp * cnbins * (CELLS_PER_BLOCK_X *
80 CELLS_PER_BLOCK_Y * 12 + CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y);
81 __local float* final_hist = hists + cnbins *
82 (CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12);
84 const int offset_x = gidX * cblock_stride_x + (cell_x << 2) + cell_thread_x;
85 const int offset_y = gidY * cblock_stride_y + (cell_y << 2);
87 __global const float* grad_ptr = (gid < blocks_total) ?
88 grad + offset_y * grad_quadstep + (offset_x << 1) : grad;
89 __global const uchar* qangle_ptr = (gid < blocks_total) ?
90 qangle + offset_y * qangle_step + (offset_x << 1) : qangle;
92 __local float* hist = hists + 12 * (cell_y * CELLS_PER_BLOCK_Y + cell_x) +
94 for (int bin_id = 0; bin_id < cnbins; ++bin_id)
95 hist[bin_id * 48] = 0.f;
97 const int dist_x = -4 + cell_thread_x - 4 * cell_x;
98 const int dist_center_x = dist_x - 4 * (1 - 2 * cell_x);
100 const int dist_y_begin = -4 - 4 * lidY;
101 for (int dist_y = dist_y_begin; dist_y < dist_y_begin + 12; ++dist_y)
103 float2 vote = (float2) (grad_ptr[0], grad_ptr[1]);
104 uchar2 bin = (uchar2) (qangle_ptr[0], qangle_ptr[1]);
106 grad_ptr += grad_quadstep;
107 qangle_ptr += qangle_step;
109 int dist_center_y = dist_y - 4 * (1 - 2 * cell_y);
111 int idx = (dist_center_y + 8) * 16 + (dist_center_x + 8);
112 float gaussian = gauss_w_lut[idx];
113 idx = (dist_y + 8) * 16 + (dist_x + 8);
114 float interp_weight = gauss_w_lut[256+idx];
116 hist[bin.x * 48] += gaussian * interp_weight * vote.x;
117 hist[bin.y * 48] += gaussian * interp_weight * vote.y;
119 barrier(CLK_LOCAL_MEM_FENCE);
121 volatile __local float* hist_ = hist;
122 for (int bin_id = 0; bin_id < cnbins; ++bin_id, hist_ += 48)
124 if (cell_thread_x < 6)
125 hist_[0] += hist_[6];
126 barrier(CLK_LOCAL_MEM_FENCE);
127 if (cell_thread_x < 3)
128 hist_[0] += hist_[3];
130 barrier(CLK_LOCAL_MEM_FENCE);
132 if (cell_thread_x == 0)
133 final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] =
134 hist_[0] + hist_[1] + hist_[2];
137 barrier(CLK_LOCAL_MEM_FENCE);
140 int tid = (cell_y * CELLS_PER_BLOCK_Y + cell_x) * 12 + cell_thread_x;
141 if ((tid < cblock_hist_size) && (gid < blocks_total))
143 __global float* block_hist = block_hists +
144 (gidY * img_block_width + gidX) * cblock_hist_size;
145 block_hist[tid] = final_hist[tid];
149 //-------------------------------------------------------------
150 // Normalization of histograms via L2Hys_norm
151 // optimized for the case of 9 bins
152 __kernel void normalize_hists_36_kernel(__global float* block_hists,
153 const float threshold, __local float *squares)
155 const int tid = get_local_id(0);
156 const int gid = get_global_id(0);
157 const int bid = tid / 36; /* block-hist id, (0 - 6) */
158 const int boffset = bid * 36; /* block-hist offset in the work-group */
159 const int hid = tid - boffset; /* histogram bin id, (0 - 35) */
161 float elem = block_hists[gid];
162 squares[tid] = elem * elem;
163 barrier(CLK_LOCAL_MEM_FENCE);
165 __local float* smem = squares + boffset;
166 float sum = smem[hid];
168 smem[hid] = sum = sum + smem[hid + 18];
169 barrier(CLK_LOCAL_MEM_FENCE);
171 smem[hid] = sum = sum + smem[hid + 9];
172 barrier(CLK_LOCAL_MEM_FENCE);
174 smem[hid] = sum + smem[hid + 4];
175 barrier(CLK_LOCAL_MEM_FENCE);
176 sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8];
178 elem = elem / (sqrt(sum) + 3.6f);
179 elem = min(elem, threshold);
181 barrier(CLK_LOCAL_MEM_FENCE);
182 squares[tid] = elem * elem;
183 barrier(CLK_LOCAL_MEM_FENCE);
187 smem[hid] = sum = sum + smem[hid + 18];
188 barrier(CLK_LOCAL_MEM_FENCE);
190 smem[hid] = sum = sum + smem[hid + 9];
191 barrier(CLK_LOCAL_MEM_FENCE);
193 smem[hid] = sum + smem[hid + 4];
194 barrier(CLK_LOCAL_MEM_FENCE);
195 sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8];
197 block_hists[gid] = elem / (sqrt(sum) + 1e-3f);
200 //-------------------------------------------------------------
201 // Normalization of histograms via L2Hys_norm
203 float reduce_smem(volatile __local float* smem, int size)
205 unsigned int tid = get_local_id(0);
206 float sum = smem[tid];
208 if (size >= 512) { if (tid < 256) smem[tid] = sum = sum + smem[tid + 256];
209 barrier(CLK_LOCAL_MEM_FENCE); }
210 if (size >= 256) { if (tid < 128) smem[tid] = sum = sum + smem[tid + 128];
211 barrier(CLK_LOCAL_MEM_FENCE); }
212 if (size >= 128) { if (tid < 64) smem[tid] = sum = sum + smem[tid + 64];
213 barrier(CLK_LOCAL_MEM_FENCE); }
215 if (size >= 64) { if (tid < 32) smem[tid] = sum = sum + smem[tid + 32];
216 barrier(CLK_LOCAL_MEM_FENCE); }
217 if (size >= 32) { if (tid < 16) smem[tid] = sum = sum + smem[tid + 16];
218 barrier(CLK_LOCAL_MEM_FENCE); }
219 if (size >= 16) { if (tid < 8) smem[tid] = sum = sum + smem[tid + 8];
220 barrier(CLK_LOCAL_MEM_FENCE); }
221 if (size >= 8) { if (tid < 4) smem[tid] = sum = sum + smem[tid + 4];
222 barrier(CLK_LOCAL_MEM_FENCE); }
223 if (size >= 4) { if (tid < 2) smem[tid] = sum = sum + smem[tid + 2];
224 barrier(CLK_LOCAL_MEM_FENCE); }
225 if (size >= 2) { if (tid < 1) smem[tid] = sum = sum + smem[tid + 1];
226 barrier(CLK_LOCAL_MEM_FENCE); }
230 if (size >= 64) smem[tid] = sum = sum + smem[tid + 32];
232 } barrier(CLK_LOCAL_MEM_FENCE);
235 if (size >= 32) smem[tid] = sum = sum + smem[tid + 16];
236 if (size >= 16) smem[tid] = sum = sum + smem[tid + 8];
237 if (size >= 8) smem[tid] = sum = sum + smem[tid + 4];
238 if (size >= 4) smem[tid] = sum = sum + smem[tid + 2];
239 if (size >= 2) smem[tid] = sum = sum + smem[tid + 1];
246 __kernel void normalize_hists_kernel(
247 const int nthreads, const int block_hist_size, const int img_block_width,
248 __global float* block_hists, const float threshold, __local float *squares)
250 const int tid = get_local_id(0);
251 const int gidX = get_group_id(0);
252 const int gidY = get_group_id(1);
254 __global float* hist = block_hists + (gidY * img_block_width + gidX) *
255 block_hist_size + tid;
258 if (tid < block_hist_size)
261 squares[tid] = elem * elem;
263 barrier(CLK_LOCAL_MEM_FENCE);
264 float sum = reduce_smem(squares, nthreads);
266 float scale = 1.0f / (sqrt(sum) + 0.1f * block_hist_size);
267 elem = min(elem * scale, threshold);
269 barrier(CLK_LOCAL_MEM_FENCE);
270 squares[tid] = elem * elem;
272 barrier(CLK_LOCAL_MEM_FENCE);
273 sum = reduce_smem(squares, nthreads);
274 scale = 1.0f / (sqrt(sum) + 1e-3f);
276 if (tid < block_hist_size)
277 hist[0] = elem * scale;
280 //---------------------------------------------------------------------
281 // Linear SVM based classification
282 // 48x96 window, 9 bins and default parameters
283 // 180 threads, each thread corresponds to a bin in a row
284 __kernel void classify_hists_180_kernel(
285 const int cdescr_width, const int cdescr_height, const int cblock_hist_size,
286 const int img_win_width, const int img_block_width,
287 const int win_block_stride_x, const int win_block_stride_y,
288 __global const float * block_hists, __global const float* coefs,
289 float free_coef, float threshold, __global uchar* labels)
291 const int tid = get_local_id(0);
292 const int gidX = get_group_id(0);
293 const int gidY = get_group_id(1);
295 __global const float* hist = block_hists + (gidY * win_block_stride_y *
296 img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
300 for (int i = 0; i < cdescr_height; i++)
302 product += coefs[i * cdescr_width + tid] *
303 hist[i * img_block_width * cblock_hist_size + tid];
306 __local float products[180];
308 products[tid] = product;
310 barrier(CLK_LOCAL_MEM_FENCE);
312 if (tid < 90) products[tid] = product = product + products[tid + 90];
313 barrier(CLK_LOCAL_MEM_FENCE);
315 if (tid < 45) products[tid] = product = product + products[tid + 45];
316 barrier(CLK_LOCAL_MEM_FENCE);
318 volatile __local float* smem = products;
320 if (tid < 13) smem[tid] = product = product + smem[tid + 32];
321 barrier(CLK_LOCAL_MEM_FENCE);
322 if (tid < 16) smem[tid] = product = product + smem[tid + 16];
323 barrier(CLK_LOCAL_MEM_FENCE);
324 if(tid<8) smem[tid] = product = product + smem[tid + 8];
325 barrier(CLK_LOCAL_MEM_FENCE);
326 if(tid<4) smem[tid] = product = product + smem[tid + 4];
327 barrier(CLK_LOCAL_MEM_FENCE);
328 if(tid<2) smem[tid] = product = product + smem[tid + 2];
329 barrier(CLK_LOCAL_MEM_FENCE);
333 smem[tid] = product = product + smem[tid + 32];
336 barrier(CLK_LOCAL_MEM_FENCE);
340 smem[tid] = product = product + smem[tid + 16];
341 smem[tid] = product = product + smem[tid + 8];
342 smem[tid] = product = product + smem[tid + 4];
343 smem[tid] = product = product + smem[tid + 2];
348 product = product + smem[tid + 1];
349 labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
353 //---------------------------------------------------------------------
354 // Linear SVM based classification
355 // 64x128 window, 9 bins and default parameters
356 // 256 threads, 252 of them are used
357 __kernel void classify_hists_252_kernel(
358 const int cdescr_width, const int cdescr_height, const int cblock_hist_size,
359 const int img_win_width, const int img_block_width,
360 const int win_block_stride_x, const int win_block_stride_y,
361 __global const float * block_hists, __global const float* coefs,
362 float free_coef, float threshold, __global uchar* labels)
364 const int tid = get_local_id(0);
365 const int gidX = get_group_id(0);
366 const int gidY = get_group_id(1);
368 __global const float* hist = block_hists + (gidY * win_block_stride_y *
369 img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
372 if (tid < cdescr_width)
374 for (int i = 0; i < cdescr_height; i++)
375 product += coefs[i * cdescr_width + tid] *
376 hist[i * img_block_width * cblock_hist_size + tid];
379 __local float products[NTHREADS];
381 products[tid] = product;
383 barrier(CLK_LOCAL_MEM_FENCE);
385 if (tid < 128) products[tid] = product = product + products[tid + 128];
386 barrier(CLK_LOCAL_MEM_FENCE);
388 if (tid < 64) products[tid] = product = product + products[tid + 64];
389 barrier(CLK_LOCAL_MEM_FENCE);
391 volatile __local float* smem = products;
393 if(tid<32) smem[tid] = product = product + smem[tid + 32];
394 barrier(CLK_LOCAL_MEM_FENCE);
395 if(tid<16) smem[tid] = product = product + smem[tid + 16];
396 barrier(CLK_LOCAL_MEM_FENCE);
397 if(tid<8) smem[tid] = product = product + smem[tid + 8];
398 barrier(CLK_LOCAL_MEM_FENCE);
399 if(tid<4) smem[tid] = product = product + smem[tid + 4];
400 barrier(CLK_LOCAL_MEM_FENCE);
401 if(tid<2) smem[tid] = product = product + smem[tid + 2];
402 barrier(CLK_LOCAL_MEM_FENCE);
406 smem[tid] = product = product + smem[tid + 32];
408 } barrier(CLK_LOCAL_MEM_FENCE);
411 smem[tid] = product = product + smem[tid + 16];
412 smem[tid] = product = product + smem[tid + 8];
413 smem[tid] = product = product + smem[tid + 4];
414 smem[tid] = product = product + smem[tid + 2];
418 product = product + smem[tid + 1];
419 labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
423 //---------------------------------------------------------------------
424 // Linear SVM based classification
426 __kernel void classify_hists_kernel(
427 const int cdescr_size, const int cdescr_width, const int cblock_hist_size,
428 const int img_win_width, const int img_block_width,
429 const int win_block_stride_x, const int win_block_stride_y,
430 __global const float * block_hists, __global const float* coefs,
431 float free_coef, float threshold, __global uchar* labels)
433 const int tid = get_local_id(0);
434 const int gidX = get_group_id(0);
435 const int gidY = get_group_id(1);
437 __global const float* hist = block_hists + (gidY * win_block_stride_y *
438 img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
441 for (int i = tid; i < cdescr_size; i += NTHREADS)
443 int offset_y = i / cdescr_width;
444 int offset_x = i - offset_y * cdescr_width;
445 product += coefs[i] *
446 hist[offset_y * img_block_width * cblock_hist_size + offset_x];
449 __local float products[NTHREADS];
451 products[tid] = product;
453 barrier(CLK_LOCAL_MEM_FENCE);
455 if (tid < 128) products[tid] = product = product + products[tid + 128];
456 barrier(CLK_LOCAL_MEM_FENCE);
458 if (tid < 64) products[tid] = product = product + products[tid + 64];
459 barrier(CLK_LOCAL_MEM_FENCE);
461 volatile __local float* smem = products;
463 if(tid<32) smem[tid] = product = product + smem[tid + 32];
464 barrier(CLK_LOCAL_MEM_FENCE);
465 if(tid<16) smem[tid] = product = product + smem[tid + 16];
466 barrier(CLK_LOCAL_MEM_FENCE);
467 if(tid<8) smem[tid] = product = product + smem[tid + 8];
468 barrier(CLK_LOCAL_MEM_FENCE);
469 if(tid<4) smem[tid] = product = product + smem[tid + 4];
470 barrier(CLK_LOCAL_MEM_FENCE);
471 if(tid<2) smem[tid] = product = product + smem[tid + 2];
472 barrier(CLK_LOCAL_MEM_FENCE);
476 smem[tid] = product = product + smem[tid + 32];
478 } barrier(CLK_LOCAL_MEM_FENCE);
481 smem[tid] = product = product + smem[tid + 16];
482 smem[tid] = product = product + smem[tid + 8];
483 smem[tid] = product = product + smem[tid + 4];
484 smem[tid] = product = product + smem[tid + 2];
488 smem[tid] = product = product + smem[tid + 1];
489 labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold);
493 //----------------------------------------------------------------------------
494 // Extract descriptors
496 __kernel void extract_descrs_by_rows_kernel(
497 const int cblock_hist_size, const int descriptors_quadstep,
498 const int cdescr_size, const int cdescr_width, const int img_block_width,
499 const int win_block_stride_x, const int win_block_stride_y,
500 __global const float* block_hists, __global float* descriptors)
502 int tid = get_local_id(0);
503 int gidX = get_group_id(0);
504 int gidY = get_group_id(1);
506 // Get left top corner of the window in src
507 __global const float* hist = block_hists + (gidY * win_block_stride_y *
508 img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
510 // Get left top corner of the window in dst
511 __global float* descriptor = descriptors +
512 (gidY * get_num_groups(0) + gidX) * descriptors_quadstep;
514 // Copy elements from src to dst
515 for (int i = tid; i < cdescr_size; i += NTHREADS)
517 int offset_y = i / cdescr_width;
518 int offset_x = i - offset_y * cdescr_width;
519 descriptor[i] = hist[offset_y * img_block_width * cblock_hist_size + offset_x];
523 __kernel void extract_descrs_by_cols_kernel(
524 const int cblock_hist_size, const int descriptors_quadstep, const int cdescr_size,
525 const int cnblocks_win_x, const int cnblocks_win_y, const int img_block_width,
526 const int win_block_stride_x, const int win_block_stride_y,
527 __global const float* block_hists, __global float* descriptors)
529 int tid = get_local_id(0);
530 int gidX = get_group_id(0);
531 int gidY = get_group_id(1);
533 // Get left top corner of the window in src
534 __global const float* hist = block_hists + (gidY * win_block_stride_y *
535 img_block_width + gidX * win_block_stride_x) * cblock_hist_size;
537 // Get left top corner of the window in dst
538 __global float* descriptor = descriptors +
539 (gidY * get_num_groups(0) + gidX) * descriptors_quadstep;
541 // Copy elements from src to dst
542 for (int i = tid; i < cdescr_size; i += NTHREADS)
544 int block_idx = i / cblock_hist_size;
545 int idx_in_block = i - block_idx * cblock_hist_size;
547 int y = block_idx / cnblocks_win_x;
548 int x = block_idx - y * cnblocks_win_x;
550 descriptor[(x * cnblocks_win_y + y) * cblock_hist_size + idx_in_block] =
551 hist[(y * img_block_width + x) * cblock_hist_size + idx_in_block];
555 //----------------------------------------------------------------------------
556 // Gradients computation
558 __kernel void compute_gradients_8UC4_kernel(
559 const int height, const int width,
560 const int img_step, const int grad_quadstep, const int qangle_step,
561 const __global uchar4 * img, __global float * grad, __global uchar * qangle,
562 const float angle_scale, const char correct_gamma, const int cnbins)
564 const int x = get_global_id(0);
565 const int tid = get_local_id(0);
566 const int gSizeX = get_local_size(0);
567 const int gidX = get_group_id(0);
568 const int gidY = get_group_id(1);
570 __global const uchar4* row = img + gidY * img_step;
572 __local float sh_row[(NTHREADS + 2) * 3];
578 val = row[width - 2];
580 sh_row[tid + 1] = val.x;
581 sh_row[tid + 1 + (NTHREADS + 2)] = val.y;
582 sh_row[tid + 1 + 2 * (NTHREADS + 2)] = val.z;
586 val = row[max(x - 1, 1)];
588 sh_row[(NTHREADS + 2)] = val.y;
589 sh_row[2 * (NTHREADS + 2)] = val.z;
592 if (tid == gSizeX - 1)
594 val = row[min(x + 1, width - 2)];
595 sh_row[gSizeX + 1] = val.x;
596 sh_row[gSizeX + 1 + (NTHREADS + 2)] = val.y;
597 sh_row[gSizeX + 1 + 2 * (NTHREADS + 2)] = val.z;
600 barrier(CLK_LOCAL_MEM_FENCE);
603 float3 a = (float3) (sh_row[tid], sh_row[tid + (NTHREADS + 2)],
604 sh_row[tid + 2 * (NTHREADS + 2)]);
605 float3 b = (float3) (sh_row[tid + 2], sh_row[tid + 2 + (NTHREADS + 2)],
606 sh_row[tid + 2 + 2 * (NTHREADS + 2)]);
609 if (correct_gamma == 1)
610 dx = sqrt(b) - sqrt(a);
614 float3 dy = (float3) 0.f;
616 if (gidY > 0 && gidY < height - 1)
618 a = convert_float3(img[(gidY - 1) * img_step + x].xyz);
619 b = convert_float3(img[(gidY + 1) * img_step + x].xyz);
621 if (correct_gamma == 1)
622 dy = sqrt(b) - sqrt(a);
627 float best_dx = dx.x;
628 float best_dy = dy.x;
630 float mag0 = dx.x * dx.x + dy.x * dy.x;
631 float mag1 = dx.y * dx.y + dy.y * dy.y;
639 mag1 = dx.z * dx.z + dy.z * dy.z;
649 float ang = (atan2(best_dy, best_dx) + CV_PI_F) * angle_scale - 0.5f;
650 int hidx = (int)floor(ang);
652 hidx = (hidx + cnbins) % cnbins;
654 qangle[(gidY * qangle_step + x) << 1] = hidx;
655 qangle[((gidY * qangle_step + x) << 1) + 1] = (hidx + 1) % cnbins;
656 grad[(gidY * grad_quadstep + x) << 1] = mag0 * (1.f - ang);
657 grad[((gidY * grad_quadstep + x) << 1) + 1] = mag0 * ang;
661 __kernel void compute_gradients_8UC1_kernel(
662 const int height, const int width,
663 const int img_step, const int grad_quadstep, const int qangle_step,
664 __global const uchar * img, __global float * grad, __global uchar * qangle,
665 const float angle_scale, const char correct_gamma, const int cnbins)
667 const int x = get_global_id(0);
668 const int tid = get_local_id(0);
669 const int gSizeX = get_local_size(0);
670 const int gidX = get_group_id(0);
671 const int gidY = get_group_id(1);
673 __global const uchar* row = img + gidY * img_step;
675 __local float sh_row[NTHREADS + 2];
678 sh_row[tid + 1] = row[x];
680 sh_row[tid + 1] = row[width - 2];
683 sh_row[0] = row[max(x - 1, 1)];
685 if (tid == gSizeX - 1)
686 sh_row[gSizeX + 1] = row[min(x + 1, width - 2)];
688 barrier(CLK_LOCAL_MEM_FENCE);
693 if (correct_gamma == 1)
694 dx = sqrt(sh_row[tid + 2]) - sqrt(sh_row[tid]);
696 dx = sh_row[tid + 2] - sh_row[tid];
699 if (gidY > 0 && gidY < height - 1)
701 float a = (float) img[ (gidY + 1) * img_step + x ];
702 float b = (float) img[ (gidY - 1) * img_step + x ];
703 if (correct_gamma == 1)
704 dy = sqrt(a) - sqrt(b);
708 float mag = sqrt(dx * dx + dy * dy);
710 float ang = (atan2(dy, dx) + CV_PI_F) * angle_scale - 0.5f;
711 int hidx = (int)floor(ang);
713 hidx = (hidx + cnbins) % cnbins;
715 qangle[ (gidY * qangle_step + x) << 1 ] = hidx;
716 qangle[ ((gidY * qangle_step + x) << 1) + 1 ] = (hidx + 1) % cnbins;
717 grad[ (gidY * grad_quadstep + x) << 1 ] = mag * (1.f - ang);
718 grad[ ((gidY * grad_quadstep + x) << 1) + 1 ] = mag * ang;