1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 //
45 // NVIDIA CUDA implementation of Viola-Jones Object Detection Framework
46 //
47 // The algorithm and code are explained in the upcoming GPU Computing Gems
48 // chapter in detail:
49 //
50 //   Anton Obukhov, "Haar Classifiers for Object Detection with CUDA"
51 //   PDF URL placeholder
52 //   email: aobukhov@nvidia.com, devsupport@nvidia.com
53 //
54 // Credits for help with the code to:
55 // Alexey Mendelenko, Cyril Crassin, and Mikhail Smirnov.
56 //
57 ////////////////////////////////////////////////////////////////////////////////
58 
59 #ifndef _ncvhaarobjectdetection_hpp_
60 #define _ncvhaarobjectdetection_hpp_
61 
62 #include "opencv2/cudalegacy/NCV.hpp"
63 
64 //! @addtogroup cudalegacy
65 //! @{
66 
67 //==============================================================================
68 //
69 // Guaranteed size cross-platform classifier structures
70 //
71 //==============================================================================
72 #if defined __GNUC__ && __GNUC__ > 2 && __GNUC_MINOR__  > 4
73 typedef Ncv32f __attribute__((__may_alias__)) Ncv32f_a;
74 #else
75 typedef Ncv32f Ncv32f_a;
76 #endif
77 
78 struct HaarFeature64
79 {
80     uint2 _ui2;
81 
82 #define HaarFeature64_CreateCheck_MaxRectField                  0xFF
83 
setRectHaarFeature6484     __host__ NCVStatus setRect(Ncv32u rectX, Ncv32u rectY, Ncv32u rectWidth, Ncv32u rectHeight, Ncv32u /*clsWidth*/, Ncv32u /*clsHeight*/)
85     {
86         ncvAssertReturn(rectWidth <= HaarFeature64_CreateCheck_MaxRectField && rectHeight <= HaarFeature64_CreateCheck_MaxRectField, NCV_HAAR_TOO_LARGE_FEATURES);
87         ((NcvRect8u*)&(this->_ui2.x))->x = (Ncv8u)rectX;
88         ((NcvRect8u*)&(this->_ui2.x))->y = (Ncv8u)rectY;
89         ((NcvRect8u*)&(this->_ui2.x))->width = (Ncv8u)rectWidth;
90         ((NcvRect8u*)&(this->_ui2.x))->height = (Ncv8u)rectHeight;
91         return NCV_SUCCESS;
92     }
93 
setWeightHaarFeature6494     __host__ NCVStatus setWeight(Ncv32f weight)
95     {
96         ((Ncv32f_a*)&(this->_ui2.y))[0] = weight;
97         return NCV_SUCCESS;
98     }
99 
getRectHaarFeature64100     __device__ __host__ void getRect(Ncv32u *rectX, Ncv32u *rectY, Ncv32u *rectWidth, Ncv32u *rectHeight)
101     {
102         NcvRect8u tmpRect = *(NcvRect8u*)(&this->_ui2.x);
103         *rectX = tmpRect.x;
104         *rectY = tmpRect.y;
105         *rectWidth = tmpRect.width;
106         *rectHeight = tmpRect.height;
107     }
108 
getWeightHaarFeature64109     __device__ __host__ Ncv32f getWeight(void)
110     {
111         return *(Ncv32f_a*)(&this->_ui2.y);
112     }
113 };
114 
115 
116 struct HaarFeatureDescriptor32
117 {
118 private:
119 
120 #define HaarFeatureDescriptor32_Interpret_MaskFlagTilted        0x80000000
121 #define HaarFeatureDescriptor32_Interpret_MaskFlagLeftNodeLeaf  0x40000000
122 #define HaarFeatureDescriptor32_Interpret_MaskFlagRightNodeLeaf 0x20000000
123 #define HaarFeatureDescriptor32_CreateCheck_MaxNumFeatures      0x1F
124 #define HaarFeatureDescriptor32_NumFeatures_Shift               24
125 #define HaarFeatureDescriptor32_CreateCheck_MaxFeatureOffset    0x00FFFFFF
126 
127     Ncv32u desc;
128 
129 public:
130 
createHaarFeatureDescriptor32131     __host__ NCVStatus create(NcvBool bTilted, NcvBool bLeftLeaf, NcvBool bRightLeaf,
132                               Ncv32u numFeatures, Ncv32u offsetFeatures)
133     {
134         if (numFeatures > HaarFeatureDescriptor32_CreateCheck_MaxNumFeatures)
135         {
136             return NCV_HAAR_TOO_MANY_FEATURES_IN_CLASSIFIER;
137         }
138         if (offsetFeatures > HaarFeatureDescriptor32_CreateCheck_MaxFeatureOffset)
139         {
140             return NCV_HAAR_TOO_MANY_FEATURES_IN_CASCADE;
141         }
142         this->desc = 0;
143         this->desc |= (bTilted ? HaarFeatureDescriptor32_Interpret_MaskFlagTilted : 0);
144         this->desc |= (bLeftLeaf ? HaarFeatureDescriptor32_Interpret_MaskFlagLeftNodeLeaf : 0);
145         this->desc |= (bRightLeaf ? HaarFeatureDescriptor32_Interpret_MaskFlagRightNodeLeaf : 0);
146         this->desc |= (numFeatures << HaarFeatureDescriptor32_NumFeatures_Shift);
147         this->desc |= offsetFeatures;
148         return NCV_SUCCESS;
149     }
150 
isTiltedHaarFeatureDescriptor32151     __device__ __host__ NcvBool isTilted(void)
152     {
153         return (this->desc & HaarFeatureDescriptor32_Interpret_MaskFlagTilted) != 0;
154     }
155 
isLeftNodeLeafHaarFeatureDescriptor32156     __device__ __host__ NcvBool isLeftNodeLeaf(void)
157     {
158         return (this->desc & HaarFeatureDescriptor32_Interpret_MaskFlagLeftNodeLeaf) != 0;
159     }
160 
isRightNodeLeafHaarFeatureDescriptor32161     __device__ __host__ NcvBool isRightNodeLeaf(void)
162     {
163         return (this->desc & HaarFeatureDescriptor32_Interpret_MaskFlagRightNodeLeaf) != 0;
164     }
165 
getNumFeaturesHaarFeatureDescriptor32166     __device__ __host__ Ncv32u getNumFeatures(void)
167     {
168         return (this->desc >> HaarFeatureDescriptor32_NumFeatures_Shift) & HaarFeatureDescriptor32_CreateCheck_MaxNumFeatures;
169     }
170 
getFeaturesOffsetHaarFeatureDescriptor32171     __device__ __host__ Ncv32u getFeaturesOffset(void)
172     {
173         return this->desc & HaarFeatureDescriptor32_CreateCheck_MaxFeatureOffset;
174     }
175 };
176 
177 struct HaarClassifierNodeDescriptor32
178 {
179     uint1 _ui1;
180 
createHaarClassifierNodeDescriptor32181     __host__ NCVStatus create(Ncv32f leafValue)
182     {
183         *(Ncv32f_a *)&this->_ui1 = leafValue;
184         return NCV_SUCCESS;
185     }
186 
createHaarClassifierNodeDescriptor32187     __host__ NCVStatus create(Ncv32u offsetHaarClassifierNode)
188     {
189         this->_ui1.x = offsetHaarClassifierNode;
190         return NCV_SUCCESS;
191     }
192 
getLeafValueHostHaarClassifierNodeDescriptor32193     __host__ Ncv32f getLeafValueHost(void)
194     {
195         return *(Ncv32f_a *)&this->_ui1.x;
196     }
197 
198 #ifdef __CUDACC__
getLeafValueHaarClassifierNodeDescriptor32199     __device__ Ncv32f getLeafValue(void)
200     {
201         return __int_as_float(this->_ui1.x);
202     }
203 #endif
204 
getNextNodeOffsetHaarClassifierNodeDescriptor32205     __device__ __host__ Ncv32u getNextNodeOffset(void)
206     {
207         return this->_ui1.x;
208     }
209 };
210 
211 #if defined __GNUC__ && __GNUC__ > 2 && __GNUC_MINOR__  > 4
212 typedef Ncv32u __attribute__((__may_alias__)) Ncv32u_a;
213 #else
214 typedef Ncv32u Ncv32u_a;
215 #endif
216 
217 struct HaarClassifierNode128
218 {
219     uint4 _ui4;
220 
setFeatureDescHaarClassifierNode128221     __host__ NCVStatus setFeatureDesc(HaarFeatureDescriptor32 f)
222     {
223         this->_ui4.x = *(Ncv32u *)&f;
224         return NCV_SUCCESS;
225     }
226 
setThresholdHaarClassifierNode128227     __host__ NCVStatus setThreshold(Ncv32f t)
228     {
229         this->_ui4.y = *(Ncv32u_a *)&t;
230         return NCV_SUCCESS;
231     }
232 
setLeftNodeDescHaarClassifierNode128233     __host__ NCVStatus setLeftNodeDesc(HaarClassifierNodeDescriptor32 nl)
234     {
235         this->_ui4.z = *(Ncv32u_a *)&nl;
236         return NCV_SUCCESS;
237     }
238 
setRightNodeDescHaarClassifierNode128239     __host__ NCVStatus setRightNodeDesc(HaarClassifierNodeDescriptor32 nr)
240     {
241         this->_ui4.w = *(Ncv32u_a *)&nr;
242         return NCV_SUCCESS;
243     }
244 
getFeatureDescHaarClassifierNode128245     __host__ __device__ HaarFeatureDescriptor32 getFeatureDesc(void)
246     {
247         return *(HaarFeatureDescriptor32 *)&this->_ui4.x;
248     }
249 
getThresholdHaarClassifierNode128250     __host__ __device__ Ncv32f getThreshold(void)
251     {
252         return *(Ncv32f_a*)&this->_ui4.y;
253     }
254 
getLeftNodeDescHaarClassifierNode128255     __host__ __device__ HaarClassifierNodeDescriptor32 getLeftNodeDesc(void)
256     {
257         return *(HaarClassifierNodeDescriptor32 *)&this->_ui4.z;
258     }
259 
getRightNodeDescHaarClassifierNode128260     __host__ __device__ HaarClassifierNodeDescriptor32 getRightNodeDesc(void)
261     {
262         return *(HaarClassifierNodeDescriptor32 *)&this->_ui4.w;
263     }
264 };
265 
266 
267 struct HaarStage64
268 {
269 #define HaarStage64_Interpret_MaskRootNodes         0x0000FFFF
270 #define HaarStage64_Interpret_MaskRootNodeOffset    0xFFFF0000
271 #define HaarStage64_Interpret_ShiftRootNodeOffset   16
272 
273     uint2 _ui2;
274 
setStageThresholdHaarStage64275     __host__ NCVStatus setStageThreshold(Ncv32f t)
276     {
277         this->_ui2.x = *(Ncv32u_a *)&t;
278         return NCV_SUCCESS;
279     }
280 
setStartClassifierRootNodeOffsetHaarStage64281     __host__ NCVStatus setStartClassifierRootNodeOffset(Ncv32u val)
282     {
283         if (val > (HaarStage64_Interpret_MaskRootNodeOffset >> HaarStage64_Interpret_ShiftRootNodeOffset))
284         {
285             return NCV_HAAR_XML_LOADING_EXCEPTION;
286         }
287         this->_ui2.y = (val << HaarStage64_Interpret_ShiftRootNodeOffset) | (this->_ui2.y & HaarStage64_Interpret_MaskRootNodes);
288         return NCV_SUCCESS;
289     }
290 
setNumClassifierRootNodesHaarStage64291     __host__ NCVStatus setNumClassifierRootNodes(Ncv32u val)
292     {
293         if (val > HaarStage64_Interpret_MaskRootNodes)
294         {
295             return NCV_HAAR_XML_LOADING_EXCEPTION;
296         }
297         this->_ui2.y = val | (this->_ui2.y & HaarStage64_Interpret_MaskRootNodeOffset);
298         return NCV_SUCCESS;
299     }
300 
getStageThresholdHaarStage64301     __host__ __device__ Ncv32f getStageThreshold(void)
302     {
303         return *(Ncv32f_a*)&this->_ui2.x;
304     }
305 
getStartClassifierRootNodeOffsetHaarStage64306     __host__ __device__ Ncv32u getStartClassifierRootNodeOffset(void)
307     {
308         return (this->_ui2.y >> HaarStage64_Interpret_ShiftRootNodeOffset);
309     }
310 
getNumClassifierRootNodesHaarStage64311     __host__ __device__ Ncv32u getNumClassifierRootNodes(void)
312     {
313         return (this->_ui2.y & HaarStage64_Interpret_MaskRootNodes);
314     }
315 };
316 
317 
318 NCV_CT_ASSERT(sizeof(HaarFeature64) == 8);
319 NCV_CT_ASSERT(sizeof(HaarFeatureDescriptor32) == 4);
320 NCV_CT_ASSERT(sizeof(HaarClassifierNodeDescriptor32) == 4);
321 NCV_CT_ASSERT(sizeof(HaarClassifierNode128) == 16);
322 NCV_CT_ASSERT(sizeof(HaarStage64) == 8);
323 
324 
325 //==============================================================================
326 //
327 // Classifier cascade descriptor
328 //
329 //==============================================================================
330 
331 
332 struct HaarClassifierCascadeDescriptor
333 {
334     Ncv32u NumStages;
335     Ncv32u NumClassifierRootNodes;
336     Ncv32u NumClassifierTotalNodes;
337     Ncv32u NumFeatures;
338     NcvSize32u ClassifierSize;
339     NcvBool bNeedsTiltedII;
340     NcvBool bHasStumpsOnly;
341 };
342 
343 
344 //==============================================================================
345 //
346 // Functional interface
347 //
348 //==============================================================================
349 
350 
351 enum
352 {
353     NCVPipeObjDet_Default               = 0x000,
354     NCVPipeObjDet_UseFairImageScaling   = 0x001,
355     NCVPipeObjDet_FindLargestObject     = 0x002,
356     NCVPipeObjDet_VisualizeInPlace      = 0x004,
357 };
358 
359 
360 CV_EXPORTS NCVStatus ncvDetectObjectsMultiScale_device(NCVMatrix<Ncv8u> &d_srcImg,
361                                                         NcvSize32u srcRoi,
362                                                         NCVVector<NcvRect32u> &d_dstRects,
363                                                         Ncv32u &dstNumRects,
364 
365                                                         HaarClassifierCascadeDescriptor &haar,
366                                                         NCVVector<HaarStage64> &h_HaarStages,
367                                                         NCVVector<HaarStage64> &d_HaarStages,
368                                                         NCVVector<HaarClassifierNode128> &d_HaarNodes,
369                                                         NCVVector<HaarFeature64> &d_HaarFeatures,
370 
371                                                         NcvSize32u minObjSize,
372                                                         Ncv32u minNeighbors,      //default 4
373                                                         Ncv32f scaleStep,         //default 1.2f
374                                                         Ncv32u pixelStep,         //default 1
375                                                         Ncv32u flags,             //default NCVPipeObjDet_Default
376 
377                                                         INCVMemAllocator &gpuAllocator,
378                                                         INCVMemAllocator &cpuAllocator,
379                                                         cudaDeviceProp &devProp,
380                                                         cudaStream_t cuStream);
381 
382 
383 #define OBJDET_MASK_ELEMENT_INVALID_32U     0xFFFFFFFF
384 #define HAAR_STDDEV_BORDER                  1
385 
386 
387 CV_EXPORTS NCVStatus ncvApplyHaarClassifierCascade_device(NCVMatrix<Ncv32u> &d_integralImage,
388                                                            NCVMatrix<Ncv32f> &d_weights,
389                                                            NCVMatrixAlloc<Ncv32u> &d_pixelMask,
390                                                            Ncv32u &numDetections,
391                                                            HaarClassifierCascadeDescriptor &haar,
392                                                            NCVVector<HaarStage64> &h_HaarStages,
393                                                            NCVVector<HaarStage64> &d_HaarStages,
394                                                            NCVVector<HaarClassifierNode128> &d_HaarNodes,
395                                                            NCVVector<HaarFeature64> &d_HaarFeatures,
396                                                            NcvBool bMaskElements,
397                                                            NcvSize32u anchorsRoi,
398                                                            Ncv32u pixelStep,
399                                                            Ncv32f scaleArea,
400                                                            INCVMemAllocator &gpuAllocator,
401                                                            INCVMemAllocator &cpuAllocator,
402                                                            cudaDeviceProp &devProp,
403                                                            cudaStream_t cuStream);
404 
405 
406 CV_EXPORTS NCVStatus ncvApplyHaarClassifierCascade_host(NCVMatrix<Ncv32u> &h_integralImage,
407                                                          NCVMatrix<Ncv32f> &h_weights,
408                                                          NCVMatrixAlloc<Ncv32u> &h_pixelMask,
409                                                          Ncv32u &numDetections,
410                                                          HaarClassifierCascadeDescriptor &haar,
411                                                          NCVVector<HaarStage64> &h_HaarStages,
412                                                          NCVVector<HaarClassifierNode128> &h_HaarNodes,
413                                                          NCVVector<HaarFeature64> &h_HaarFeatures,
414                                                          NcvBool bMaskElements,
415                                                          NcvSize32u anchorsRoi,
416                                                          Ncv32u pixelStep,
417                                                          Ncv32f scaleArea);
418 
419 
420 #define RECT_SIMILARITY_PROPORTION      0.2f
421 
422 
423 CV_EXPORTS NCVStatus ncvGrowDetectionsVector_device(NCVVector<Ncv32u> &pixelMask,
424                                                      Ncv32u numPixelMaskDetections,
425                                                      NCVVector<NcvRect32u> &hypotheses,
426                                                      Ncv32u &totalDetections,
427                                                      Ncv32u totalMaxDetections,
428                                                      Ncv32u rectWidth,
429                                                      Ncv32u rectHeight,
430                                                      Ncv32f curScale,
431                                                      cudaStream_t cuStream);
432 
433 
434 CV_EXPORTS NCVStatus ncvGrowDetectionsVector_host(NCVVector<Ncv32u> &pixelMask,
435                                                    Ncv32u numPixelMaskDetections,
436                                                    NCVVector<NcvRect32u> &hypotheses,
437                                                    Ncv32u &totalDetections,
438                                                    Ncv32u totalMaxDetections,
439                                                    Ncv32u rectWidth,
440                                                    Ncv32u rectHeight,
441                                                    Ncv32f curScale);
442 
443 
444 CV_EXPORTS NCVStatus ncvHaarGetClassifierSize(const cv::String &filename, Ncv32u &numStages,
445                                                Ncv32u &numNodes, Ncv32u &numFeatures);
446 
447 
448 CV_EXPORTS NCVStatus ncvHaarLoadFromFile_host(const cv::String &filename,
449                                                HaarClassifierCascadeDescriptor &haar,
450                                                NCVVector<HaarStage64> &h_HaarStages,
451                                                NCVVector<HaarClassifierNode128> &h_HaarNodes,
452                                                NCVVector<HaarFeature64> &h_HaarFeatures);
453 
454 
455 CV_EXPORTS NCVStatus ncvHaarStoreNVBIN_host(const cv::String &filename,
456                                              HaarClassifierCascadeDescriptor haar,
457                                              NCVVector<HaarStage64> &h_HaarStages,
458                                              NCVVector<HaarClassifierNode128> &h_HaarNodes,
459                                              NCVVector<HaarFeature64> &h_HaarFeatures);
460 
461 //! @}
462 
463 #endif // _ncvhaarobjectdetection_hpp_
464