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 // Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43 
44 #include "precomp.hpp"
45 #include "opencl_kernels_imgproc.hpp"
46 #include "opencv2/core/hal/intrin.hpp"
47 #include "corner.hpp"
48 
49 namespace cv
50 {
51 
calcMinEigenVal(const Mat & _cov,Mat & _dst)52 static void calcMinEigenVal( const Mat& _cov, Mat& _dst )
53 {
54     int i, j;
55     Size size = _cov.size();
56 #if CV_TRY_AVX
57     bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
58 #endif
59 
60     if( _cov.isContinuous() && _dst.isContinuous() )
61     {
62         size.width *= size.height;
63         size.height = 1;
64     }
65 
66     for( i = 0; i < size.height; i++ )
67     {
68         const float* cov = _cov.ptr<float>(i);
69         float* dst = _dst.ptr<float>(i);
70 #if CV_TRY_AVX
71         if( haveAvx )
72             j = calcMinEigenValLine_AVX(cov, dst, size.width);
73         else
74 #endif // CV_TRY_AVX
75             j = 0;
76 
77 #if CV_SIMD128
78         {
79             v_float32x4 half = v_setall_f32(0.5f);
80             for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
81             {
82                 v_float32x4 v_a, v_b, v_c, v_t;
83                 v_load_deinterleave(cov + j*3, v_a, v_b, v_c);
84                 v_a *= half;
85                 v_c *= half;
86                 v_t = v_a - v_c;
87                 v_t = v_muladd(v_b, v_b, (v_t * v_t));
88                 v_store(dst + j, (v_a + v_c) - v_sqrt(v_t));
89             }
90         }
91 #endif // CV_SIMD128
92 
93         for( ; j < size.width; j++ )
94         {
95             float a = cov[j*3]*0.5f;
96             float b = cov[j*3+1];
97             float c = cov[j*3+2]*0.5f;
98             dst[j] = (float)((a + c) - std::sqrt((a - c)*(a - c) + b*b));
99         }
100     }
101 }
102 
103 
calcHarris(const Mat & _cov,Mat & _dst,double k)104 static void calcHarris( const Mat& _cov, Mat& _dst, double k )
105 {
106     int i, j;
107     Size size = _cov.size();
108 #if CV_TRY_AVX
109     bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
110 #endif
111 
112     if( _cov.isContinuous() && _dst.isContinuous() )
113     {
114         size.width *= size.height;
115         size.height = 1;
116     }
117 
118     for( i = 0; i < size.height; i++ )
119     {
120         const float* cov = _cov.ptr<float>(i);
121         float* dst = _dst.ptr<float>(i);
122 
123 #if CV_TRY_AVX
124         if( haveAvx )
125             j = calcHarrisLine_AVX(cov, dst, k, size.width);
126         else
127 #endif // CV_TRY_AVX
128             j = 0;
129 
130 #if CV_SIMD128
131         {
132             v_float32x4 v_k = v_setall_f32((float)k);
133 
134             for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
135             {
136                 v_float32x4 v_a, v_b, v_c;
137                 v_load_deinterleave(cov + j * 3, v_a, v_b, v_c);
138 
139                 v_float32x4 v_ac_bb = v_a * v_c - v_b * v_b;
140                 v_float32x4 v_ac = v_a + v_c;
141                 v_float32x4 v_dst = v_ac_bb - v_k * v_ac * v_ac;
142                 v_store(dst + j, v_dst);
143             }
144         }
145 #endif // CV_SIMD128
146 
147         for( ; j < size.width; j++ )
148         {
149             float a = cov[j*3];
150             float b = cov[j*3+1];
151             float c = cov[j*3+2];
152             dst[j] = (float)(a*c - b*b - k*(a + c)*(a + c));
153         }
154     }
155 }
156 
157 
eigen2x2(const float * cov,float * dst,int n)158 static void eigen2x2( const float* cov, float* dst, int n )
159 {
160     for( int j = 0; j < n; j++ )
161     {
162         double a = cov[j*3];
163         double b = cov[j*3+1];
164         double c = cov[j*3+2];
165 
166         double u = (a + c)*0.5;
167         double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
168         double l1 = u + v;
169         double l2 = u - v;
170 
171         double x = b;
172         double y = l1 - a;
173         double e = fabs(x);
174 
175         if( e + fabs(y) < 1e-4 )
176         {
177             y = b;
178             x = l1 - c;
179             e = fabs(x);
180             if( e + fabs(y) < 1e-4 )
181             {
182                 e = 1./(e + fabs(y) + FLT_EPSILON);
183                 x *= e, y *= e;
184             }
185         }
186 
187         double d = 1./std::sqrt(x*x + y*y + DBL_EPSILON);
188         dst[6*j] = (float)l1;
189         dst[6*j + 2] = (float)(x*d);
190         dst[6*j + 3] = (float)(y*d);
191 
192         x = b;
193         y = l2 - a;
194         e = fabs(x);
195 
196         if( e + fabs(y) < 1e-4 )
197         {
198             y = b;
199             x = l2 - c;
200             e = fabs(x);
201             if( e + fabs(y) < 1e-4 )
202             {
203                 e = 1./(e + fabs(y) + FLT_EPSILON);
204                 x *= e, y *= e;
205             }
206         }
207 
208         d = 1./std::sqrt(x*x + y*y + DBL_EPSILON);
209         dst[6*j + 1] = (float)l2;
210         dst[6*j + 4] = (float)(x*d);
211         dst[6*j + 5] = (float)(y*d);
212     }
213 }
214 
calcEigenValsVecs(const Mat & _cov,Mat & _dst)215 static void calcEigenValsVecs( const Mat& _cov, Mat& _dst )
216 {
217     Size size = _cov.size();
218     if( _cov.isContinuous() && _dst.isContinuous() )
219     {
220         size.width *= size.height;
221         size.height = 1;
222     }
223 
224     for( int i = 0; i < size.height; i++ )
225     {
226         const float* cov = _cov.ptr<float>(i);
227         float* dst = _dst.ptr<float>(i);
228 
229         eigen2x2(cov, dst, size.width);
230     }
231 }
232 
233 
234 enum { MINEIGENVAL=0, HARRIS=1, EIGENVALSVECS=2 };
235 
236 
237 static void
cornerEigenValsVecs(const Mat & src,Mat & eigenv,int block_size,int aperture_size,int op_type,double k=0.,int borderType=BORDER_DEFAULT)238 cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size,
239                      int aperture_size, int op_type, double k=0.,
240                      int borderType=BORDER_DEFAULT )
241 {
242 #if CV_TRY_AVX
243     bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
244 #endif
245 
246     int depth = src.depth();
247     double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
248     if( aperture_size < 0 )
249         scale *= 2.0;
250     if( depth == CV_8U )
251         scale *= 255.0;
252     scale = 1.0/scale;
253 
254     CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
255 
256     Mat Dx, Dy;
257     if( aperture_size > 0 )
258     {
259         Sobel( src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType );
260         Sobel( src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType );
261     }
262     else
263     {
264         Scharr( src, Dx, CV_32F, 1, 0, scale, 0, borderType );
265         Scharr( src, Dy, CV_32F, 0, 1, scale, 0, borderType );
266     }
267 
268     Size size = src.size();
269     Mat cov( size, CV_32FC3 );
270     int i, j;
271 
272     for( i = 0; i < size.height; i++ )
273     {
274         float* cov_data = cov.ptr<float>(i);
275         const float* dxdata = Dx.ptr<float>(i);
276         const float* dydata = Dy.ptr<float>(i);
277 
278 #if CV_TRY_AVX
279         if( haveAvx )
280             j = cornerEigenValsVecsLine_AVX(dxdata, dydata, cov_data, size.width);
281         else
282 #endif // CV_TRY_AVX
283             j = 0;
284 
285 #if CV_SIMD128
286         {
287             for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
288             {
289                 v_float32x4 v_dx = v_load(dxdata + j);
290                 v_float32x4 v_dy = v_load(dydata + j);
291 
292                 v_float32x4 v_dst0, v_dst1, v_dst2;
293                 v_dst0 = v_dx * v_dx;
294                 v_dst1 = v_dx * v_dy;
295                 v_dst2 = v_dy * v_dy;
296 
297                 v_store_interleave(cov_data + j * 3, v_dst0, v_dst1, v_dst2);
298             }
299         }
300 #endif // CV_SIMD128
301 
302         for( ; j < size.width; j++ )
303         {
304             float dx = dxdata[j];
305             float dy = dydata[j];
306 
307             cov_data[j*3] = dx*dx;
308             cov_data[j*3+1] = dx*dy;
309             cov_data[j*3+2] = dy*dy;
310         }
311     }
312 
313     boxFilter(cov, cov, cov.depth(), Size(block_size, block_size),
314         Point(-1,-1), false, borderType );
315 
316     if( op_type == MINEIGENVAL )
317         calcMinEigenVal( cov, eigenv );
318     else if( op_type == HARRIS )
319         calcHarris( cov, eigenv, k );
320     else if( op_type == EIGENVALSVECS )
321         calcEigenValsVecs( cov, eigenv );
322 }
323 
324 #ifdef HAVE_OPENCL
325 
extractCovData(InputArray _src,UMat & Dx,UMat & Dy,int depth,float scale,int aperture_size,int borderType)326 static bool extractCovData(InputArray _src, UMat & Dx, UMat & Dy, int depth,
327                            float scale, int aperture_size, int borderType)
328 {
329     UMat src = _src.getUMat();
330 
331     Size wholeSize;
332     Point ofs;
333     src.locateROI(wholeSize, ofs);
334 
335     const int sobel_lsz = 16;
336     if ((aperture_size == 3 || aperture_size == 5 || aperture_size == 7 || aperture_size == -1) &&
337         wholeSize.height > sobel_lsz + (aperture_size >> 1) &&
338         wholeSize.width > sobel_lsz + (aperture_size >> 1))
339     {
340         CV_Assert(depth == CV_8U || depth == CV_32F);
341 
342         Dx.create(src.size(), CV_32FC1);
343         Dy.create(src.size(), CV_32FC1);
344 
345         size_t localsize[2] = { (size_t)sobel_lsz, (size_t)sobel_lsz };
346         size_t globalsize[2] = { localsize[0] * (1 + (src.cols - 1) / localsize[0]),
347                                  localsize[1] * (1 + (src.rows - 1) / localsize[1]) };
348 
349         int src_offset_x = (int)((src.offset % src.step) / src.elemSize());
350         int src_offset_y = (int)(src.offset / src.step);
351 
352         const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
353                                              "BORDER_WRAP", "BORDER_REFLECT101" };
354 
355         ocl::Kernel k(format("sobel%d", aperture_size).c_str(), ocl::imgproc::covardata_oclsrc,
356                       cv::format("-D BLK_X=%d -D BLK_Y=%d -D %s -D SRCTYPE=%s%s",
357                                  (int)localsize[0], (int)localsize[1], borderTypes[borderType], ocl::typeToStr(depth),
358                                  aperture_size < 0 ? " -D SCHARR" : ""));
359         if (k.empty())
360             return false;
361 
362         k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, src_offset_x, src_offset_y,
363                ocl::KernelArg::WriteOnlyNoSize(Dx), ocl::KernelArg::WriteOnly(Dy),
364                wholeSize.height, wholeSize.width, scale);
365 
366         return k.run(2, globalsize, localsize, false);
367     }
368     else
369     {
370         if (aperture_size > 0)
371         {
372             Sobel(_src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType);
373             Sobel(_src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType);
374         }
375         else
376         {
377             Scharr(_src, Dx, CV_32F, 1, 0, scale, 0, borderType);
378             Scharr(_src, Dy, CV_32F, 0, 1, scale, 0, borderType);
379         }
380     }
381 
382     return true;
383 }
384 
ocl_cornerMinEigenValVecs(InputArray _src,OutputArray _dst,int block_size,int aperture_size,double k,int borderType,int op_type)385 static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size,
386                                       int aperture_size, double k, int borderType, int op_type)
387 {
388     CV_Assert(op_type == HARRIS || op_type == MINEIGENVAL);
389 
390     if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE ||
391            borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) )
392         return false;
393 
394     int type = _src.type(), depth = CV_MAT_DEPTH(type);
395     if ( !(type == CV_8UC1 || type == CV_32FC1) )
396         return false;
397 
398     const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
399                                          "BORDER_WRAP", "BORDER_REFLECT101" };
400     const char * const cornerType[] = { "CORNER_MINEIGENVAL", "CORNER_HARRIS", 0 };
401 
402 
403     double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
404     if (aperture_size < 0)
405         scale *= 2.0;
406     if (depth == CV_8U)
407         scale *= 255.0;
408     scale = 1.0 / scale;
409 
410     UMat Dx, Dy;
411     if (!extractCovData(_src, Dx, Dy, depth, (float)scale, aperture_size, borderType))
412         return false;
413 
414     ocl::Kernel cornelKernel("corner", ocl::imgproc::corner_oclsrc,
415                              format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s -D %s",
416                                     block_size / 2, block_size / 2, block_size, block_size,
417                                     borderTypes[borderType], cornerType[op_type]));
418     if (cornelKernel.empty())
419         return false;
420 
421     _dst.createSameSize(_src, CV_32FC1);
422     UMat dst = _dst.getUMat();
423 
424     cornelKernel.args(ocl::KernelArg::ReadOnly(Dx), ocl::KernelArg::ReadOnly(Dy),
425                       ocl::KernelArg::WriteOnly(dst), (float)k);
426 
427     size_t blockSizeX = 256, blockSizeY = 1;
428     size_t gSize = blockSizeX - block_size / 2 * 2;
429     size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX;
430     size_t rows_per_thread = 2;
431     size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ?
432                          ((Dx.rows + rows_per_thread - 1) / rows_per_thread) :
433                          (((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY;
434 
435     size_t globalsize[2] = { globalSizeX, globalSizeY }, localsize[2] = { blockSizeX, blockSizeY };
436     return cornelKernel.run(2, globalsize, localsize, false);
437 }
438 
ocl_preCornerDetect(InputArray _src,OutputArray _dst,int ksize,int borderType,int depth)439 static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType, int depth )
440 {
441     UMat Dx, Dy, D2x, D2y, Dxy;
442 
443     if (!extractCovData(_src, Dx, Dy, depth, 1, ksize, borderType))
444         return false;
445 
446     Sobel( _src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );
447     Sobel( _src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );
448     Sobel( _src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );
449 
450     _dst.create( _src.size(), CV_32FC1 );
451     UMat dst = _dst.getUMat();
452 
453     double factor = 1 << (ksize - 1);
454     if( depth == CV_8U )
455         factor *= 255;
456     factor = 1./(factor * factor * factor);
457 
458     ocl::Kernel k("preCornerDetect", ocl::imgproc::precornerdetect_oclsrc);
459     if (k.empty())
460         return false;
461 
462     k.args(ocl::KernelArg::ReadOnlyNoSize(Dx), ocl::KernelArg::ReadOnlyNoSize(Dy),
463            ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y),
464            ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor);
465 
466     size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows };
467     return k.run(2, globalsize, NULL, false);
468 }
469 
470 #endif
471 
472 }
473 
474 #if 0 //defined(HAVE_IPP)
475 namespace cv
476 {
477 static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
478 {
479 #if IPP_VERSION_X100 >= 800
480     CV_INSTRUMENT_REGION_IPP();
481 
482     Mat src = _src.getMat();
483     _dst.create( src.size(), CV_32FC1 );
484     Mat dst = _dst.getMat();
485 
486     {
487         typedef IppStatus (CV_STDCALL * ippiMinEigenValGetBufferSize)(IppiSize, int, int, int*);
488         typedef IppStatus (CV_STDCALL * ippiMinEigenVal)(const void*, int, Ipp32f*, int, IppiSize, IppiKernelType, int, int, Ipp8u*);
489         IppiKernelType kerType;
490         int kerSize = ksize;
491         if (ksize < 0)
492         {
493             kerType = ippKernelScharr;
494             kerSize = 3;
495         } else
496         {
497             kerType = ippKernelSobel;
498         }
499         bool isolated = (borderType & BORDER_ISOLATED) != 0;
500         int borderTypeNI = borderType & ~BORDER_ISOLATED;
501         if ((borderTypeNI == BORDER_REPLICATE && (!src.isSubmatrix() || isolated)) &&
502             (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5))
503         {
504             ippiMinEigenValGetBufferSize getBufferSizeFunc = 0;
505             ippiMinEigenVal ippiMinEigenVal_C1R = 0;
506             float norm_coef = 0.f;
507 
508             if (src.type() == CV_8UC1)
509             {
510                 getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_8u32f_C1R;
511                 ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_8u32f_C1R;
512                 norm_coef = 1.f / 255.f;
513             } else if (src.type() == CV_32FC1)
514             {
515                 getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_32f_C1R;
516                 ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_32f_C1R;
517                 norm_coef = 255.f;
518             }
519             norm_coef = kerType == ippKernelSobel ? norm_coef : norm_coef / 2.45f;
520 
521             if (getBufferSizeFunc && ippiMinEigenVal_C1R)
522             {
523                 int bufferSize;
524                 IppiSize srcRoi = { src.cols, src.rows };
525                 IppStatus ok = getBufferSizeFunc(srcRoi, kerSize, blockSize, &bufferSize);
526                 if (ok >= 0)
527                 {
528                     AutoBuffer<uchar> buffer(bufferSize);
529                     ok = CV_INSTRUMENT_FUN_IPP(ippiMinEigenVal_C1R, src.ptr(), (int) src.step, dst.ptr<Ipp32f>(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer.data());
530                     CV_SUPPRESS_DEPRECATED_START
531                     if (ok >= 0) ok = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, norm_coef, dst.ptr<Ipp32f>(), (int) dst.step, srcRoi);
532                     CV_SUPPRESS_DEPRECATED_END
533                     if (ok >= 0)
534                     {
535                         CV_IMPL_ADD(CV_IMPL_IPP);
536                         return true;
537                     }
538                 }
539             }
540         }
541     }
542 #else
543     CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(blockSize); CV_UNUSED(borderType);
544 #endif
545     return false;
546 }
547 }
548 #endif
549 
cornerMinEigenVal(InputArray _src,OutputArray _dst,int blockSize,int ksize,int borderType)550 void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
551 {
552     CV_INSTRUMENT_REGION();
553 
554     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
555                ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL))
556 
557 /*#ifdef HAVE_IPP
558     int kerSize = (ksize < 0)?3:ksize;
559     bool isolated = (borderType & BORDER_ISOLATED) != 0;
560     int borderTypeNI = borderType & ~BORDER_ISOLATED;
561 #endif
562     CV_IPP_RUN(((borderTypeNI == BORDER_REPLICATE && (!_src.isSubmatrix() || isolated)) &&
563             (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_X100 >= 800,
564         ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType ));
565     */
566 
567     Mat src = _src.getMat();
568     _dst.create( src.size(), CV_32FC1 );
569     Mat dst = _dst.getMat();
570 
571     cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType );
572 }
573 
574 
575 #if defined(HAVE_IPP)
576 namespace cv
577 {
ipp_cornerHarris(Mat & src,Mat & dst,int blockSize,int ksize,double k,int borderType)578 static bool ipp_cornerHarris( Mat &src, Mat &dst, int blockSize, int ksize, double k, int borderType )
579 {
580 #if IPP_VERSION_X100 >= 810
581     CV_INSTRUMENT_REGION_IPP();
582 
583     {
584         int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
585         int borderTypeNI = borderType & ~BORDER_ISOLATED;
586         bool isolated = (borderType & BORDER_ISOLATED) != 0;
587 
588         if ( (ksize == 3 || ksize == 5) && (type == CV_8UC1 || type == CV_32FC1) &&
589             (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && cn == 1 && (!src.isSubmatrix() || isolated) )
590         {
591             IppiSize roisize = { src.cols, src.rows };
592             IppiMaskSize masksize = ksize == 5 ? ippMskSize5x5 : ippMskSize3x3;
593             IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp32f;
594             Ipp32s bufsize = 0;
595 
596             double scale = (double)(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;
597             if (ksize < 0)
598                 scale *= 2.0;
599             if (depth == CV_8U)
600                 scale *= 255.0;
601             scale = std::pow(scale, -4.0);
602 
603             if (ippiHarrisCornerGetBufferSize(roisize, masksize, blockSize, datatype, cn, &bufsize) >= 0)
604             {
605                 Ipp8u * buffer = (Ipp8u*)CV_IPP_MALLOC(bufsize);
606                 IppiDifferentialKernel filterType = ksize > 0 ? ippFilterSobel : ippFilterScharr;
607                 IppiBorderType borderTypeIpp = borderTypeNI == BORDER_CONSTANT ? ippBorderConst : ippBorderRepl;
608                 IppStatus status = (IppStatus)-1;
609 
610                 if (depth == CV_8U)
611                     status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_8u32f_C1R, (const Ipp8u *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,
612                         filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);
613                 else if (depth == CV_32F)
614                     status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_32f_C1R, (const Ipp32f *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,
615                         filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);
616                 ippsFree(buffer);
617 
618                 if (status >= 0)
619                 {
620                     CV_IMPL_ADD(CV_IMPL_IPP);
621                     return true;
622                 }
623             }
624         }
625     }
626 #else
627     CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(blockSize);  CV_UNUSED(ksize); CV_UNUSED(k); CV_UNUSED(borderType);
628 #endif
629     return false;
630 }
631 }
632 #endif
633 
cornerHarris(InputArray _src,OutputArray _dst,int blockSize,int ksize,double k,int borderType)634 void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType )
635 {
636     CV_INSTRUMENT_REGION();
637 
638     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
639                ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS))
640 
641     Mat src = _src.getMat();
642     _dst.create( src.size(), CV_32FC1 );
643     Mat dst = _dst.getMat();
644 
645 #ifdef HAVE_IPP
646     int borderTypeNI = borderType & ~BORDER_ISOLATED;
647     bool isolated = (borderType & BORDER_ISOLATED) != 0;
648 #endif
649     CV_IPP_RUN(((ksize == 3 || ksize == 5) && (_src.type() == CV_8UC1 || _src.type() == CV_32FC1) &&
650         (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && CV_MAT_CN(_src.type()) == 1 &&
651         (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 810, ipp_cornerHarris( src, dst, blockSize, ksize, k, borderType ));
652 
653     cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType );
654 }
655 
656 
cornerEigenValsAndVecs(InputArray _src,OutputArray _dst,int blockSize,int ksize,int borderType)657 void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
658 {
659     CV_INSTRUMENT_REGION();
660 
661     Mat src = _src.getMat();
662     Size dsz = _dst.size();
663     int dtype = _dst.type();
664 
665     if( dsz.height != src.rows || dsz.width*CV_MAT_CN(dtype) != src.cols*6 || CV_MAT_DEPTH(dtype) != CV_32F )
666         _dst.create( src.size(), CV_32FC(6) );
667     Mat dst = _dst.getMat();
668     cornerEigenValsVecs( src, dst, blockSize, ksize, EIGENVALSVECS, 0, borderType );
669 }
670 
671 
preCornerDetect(InputArray _src,OutputArray _dst,int ksize,int borderType)672 void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType )
673 {
674     CV_INSTRUMENT_REGION();
675 
676     int type = _src.type();
677     CV_Assert( type == CV_8UC1 || type == CV_32FC1 );
678 
679     CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),
680                 ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type)))
681 
682     Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();
683     _dst.create( src.size(), CV_32FC1 );
684     Mat dst = _dst.getMat();
685 
686     Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType );
687     Sobel( src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType );
688     Sobel( src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );
689     Sobel( src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );
690     Sobel( src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );
691 
692     double factor = 1 << (ksize - 1);
693     if( src.depth() == CV_8U )
694         factor *= 255;
695     factor = 1./(factor * factor * factor);
696 #if CV_SIMD128
697     float factor_f = (float)factor;
698     v_float32x4 v_factor = v_setall_f32(factor_f), v_m2 = v_setall_f32(-2.0f);
699 #endif
700 
701     Size size = src.size();
702     int i, j;
703     for( i = 0; i < size.height; i++ )
704     {
705         float* dstdata = dst.ptr<float>(i);
706         const float* dxdata = Dx.ptr<float>(i);
707         const float* dydata = Dy.ptr<float>(i);
708         const float* d2xdata = D2x.ptr<float>(i);
709         const float* d2ydata = D2y.ptr<float>(i);
710         const float* dxydata = Dxy.ptr<float>(i);
711 
712         j = 0;
713 
714 #if CV_SIMD128
715         {
716             for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
717             {
718                 v_float32x4 v_dx = v_load(dxdata + j);
719                 v_float32x4 v_dy = v_load(dydata + j);
720 
721                 v_float32x4 v_s1 = (v_dx * v_dx) * v_load(d2ydata + j);
722                 v_float32x4 v_s2 = v_muladd((v_dy * v_dy),  v_load(d2xdata + j), v_s1);
723                 v_float32x4 v_s3 = v_muladd((v_dy * v_dx) * v_load(dxydata + j), v_m2, v_s2);
724 
725                 v_store(dstdata + j, v_s3 * v_factor);
726             }
727         }
728 #endif
729 
730         for( ; j < size.width; j++ )
731         {
732             float dx = dxdata[j];
733             float dy = dydata[j];
734             dstdata[j] = (float)(factor*(dx*dx*d2ydata[j] + dy*dy*d2xdata[j] - 2*dx*dy*dxydata[j]));
735         }
736     }
737 }
738 
739 CV_IMPL void
cvCornerMinEigenVal(const CvArr * srcarr,CvArr * dstarr,int block_size,int aperture_size)740 cvCornerMinEigenVal( const CvArr* srcarr, CvArr* dstarr,
741                      int block_size, int aperture_size )
742 {
743     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
744 
745     CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
746     cv::cornerMinEigenVal( src, dst, block_size, aperture_size, cv::BORDER_REPLICATE );
747 }
748 
749 CV_IMPL void
cvCornerHarris(const CvArr * srcarr,CvArr * dstarr,int block_size,int aperture_size,double k)750 cvCornerHarris( const CvArr* srcarr, CvArr* dstarr,
751                 int block_size, int aperture_size, double k )
752 {
753     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
754 
755     CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
756     cv::cornerHarris( src, dst, block_size, aperture_size, k, cv::BORDER_REPLICATE );
757 }
758 
759 
760 CV_IMPL void
cvCornerEigenValsAndVecs(const void * srcarr,void * dstarr,int block_size,int aperture_size)761 cvCornerEigenValsAndVecs( const void* srcarr, void* dstarr,
762                           int block_size, int aperture_size )
763 {
764     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
765 
766     CV_Assert( src.rows == dst.rows && src.cols*6 == dst.cols*dst.channels() && dst.depth() == CV_32F );
767     cv::cornerEigenValsAndVecs( src, dst, block_size, aperture_size, cv::BORDER_REPLICATE );
768 }
769 
770 
771 CV_IMPL void
cvPreCornerDetect(const void * srcarr,void * dstarr,int aperture_size)772 cvPreCornerDetect( const void* srcarr, void* dstarr, int aperture_size )
773 {
774     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
775 
776     CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
777     cv::preCornerDetect( src, dst, aperture_size, cv::BORDER_REPLICATE );
778 }
779 
780 /* End of file */
781