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) 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.
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
21 // * Redistribution's of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
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.
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.
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.
44 #include "precomp.hpp"
45 #include "opencl_kernels_imgproc.hpp"
46 #include "opencv2/core/hal/intrin.hpp"
52 static void calcMinEigenVal( const Mat& _cov, Mat& _dst )
55 Size size = _cov.size();
57 bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
60 bool haveSimd = hasSIMD128();
63 if( _cov.isContinuous() && _dst.isContinuous() )
65 size.width *= size.height;
69 for( i = 0; i < size.height; i++ )
71 const float* cov = _cov.ptr<float>(i);
72 float* dst = _dst.ptr<float>(i);
75 j = calcMinEigenValLine_AVX(cov, dst, size.width);
83 v_float32x4 half = v_setall_f32(0.5f);
84 for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
86 v_float32x4 v_a, v_b, v_c, v_t;
87 v_load_deinterleave(cov + j*3, v_a, v_b, v_c);
91 v_t = v_muladd(v_b, v_b, (v_t * v_t));
92 v_store(dst + j, (v_a + v_c) - v_sqrt(v_t));
97 for( ; j < size.width; j++ )
99 float a = cov[j*3]*0.5f;
100 float b = cov[j*3+1];
101 float c = cov[j*3+2]*0.5f;
102 dst[j] = (float)((a + c) - std::sqrt((a - c)*(a - c) + b*b));
108 static void calcHarris( const Mat& _cov, Mat& _dst, double k )
111 Size size = _cov.size();
113 bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
116 bool haveSimd = hasSIMD128();
119 if( _cov.isContinuous() && _dst.isContinuous() )
121 size.width *= size.height;
125 for( i = 0; i < size.height; i++ )
127 const float* cov = _cov.ptr<float>(i);
128 float* dst = _dst.ptr<float>(i);
132 j = calcHarrisLine_AVX(cov, dst, k, size.width);
140 v_float32x4 v_k = v_setall_f32((float)k);
142 for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
144 v_float32x4 v_a, v_b, v_c;
145 v_load_deinterleave(cov + j * 3, v_a, v_b, v_c);
147 v_float32x4 v_ac_bb = v_a * v_c - v_b * v_b;
148 v_float32x4 v_ac = v_a + v_c;
149 v_float32x4 v_dst = v_ac_bb - v_k * v_ac * v_ac;
150 v_store(dst + j, v_dst);
155 for( ; j < size.width; j++ )
158 float b = cov[j*3+1];
159 float c = cov[j*3+2];
160 dst[j] = (float)(a*c - b*b - k*(a + c)*(a + c));
166 static void eigen2x2( const float* cov, float* dst, int n )
168 for( int j = 0; j < n; j++ )
171 double b = cov[j*3+1];
172 double c = cov[j*3+2];
174 double u = (a + c)*0.5;
175 double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
183 if( e + fabs(y) < 1e-4 )
188 if( e + fabs(y) < 1e-4 )
190 e = 1./(e + fabs(y) + FLT_EPSILON);
195 double d = 1./std::sqrt(x*x + y*y + DBL_EPSILON);
196 dst[6*j] = (float)l1;
197 dst[6*j + 2] = (float)(x*d);
198 dst[6*j + 3] = (float)(y*d);
204 if( e + fabs(y) < 1e-4 )
209 if( e + fabs(y) < 1e-4 )
211 e = 1./(e + fabs(y) + FLT_EPSILON);
216 d = 1./std::sqrt(x*x + y*y + DBL_EPSILON);
217 dst[6*j + 1] = (float)l2;
218 dst[6*j + 4] = (float)(x*d);
219 dst[6*j + 5] = (float)(y*d);
223 static void calcEigenValsVecs( const Mat& _cov, Mat& _dst )
225 Size size = _cov.size();
226 if( _cov.isContinuous() && _dst.isContinuous() )
228 size.width *= size.height;
232 for( int i = 0; i < size.height; i++ )
234 const float* cov = _cov.ptr<float>(i);
235 float* dst = _dst.ptr<float>(i);
237 eigen2x2(cov, dst, size.width);
242 enum { MINEIGENVAL=0, HARRIS=1, EIGENVALSVECS=2 };
246 cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size,
247 int aperture_size, int op_type, double k=0.,
248 int borderType=BORDER_DEFAULT )
251 bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
254 bool haveSimd = hasSIMD128();
257 int depth = src.depth();
258 double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
259 if( aperture_size < 0 )
265 CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
268 if( aperture_size > 0 )
270 Sobel( src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType );
271 Sobel( src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType );
275 Scharr( src, Dx, CV_32F, 1, 0, scale, 0, borderType );
276 Scharr( src, Dy, CV_32F, 0, 1, scale, 0, borderType );
279 Size size = src.size();
280 Mat cov( size, CV_32FC3 );
283 for( i = 0; i < size.height; i++ )
285 float* cov_data = cov.ptr<float>(i);
286 const float* dxdata = Dx.ptr<float>(i);
287 const float* dydata = Dy.ptr<float>(i);
291 j = cornerEigenValsVecsLine_AVX(dxdata, dydata, cov_data, size.width);
299 for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
301 v_float32x4 v_dx = v_load(dxdata + j);
302 v_float32x4 v_dy = v_load(dydata + j);
304 v_float32x4 v_dst0, v_dst1, v_dst2;
305 v_dst0 = v_dx * v_dx;
306 v_dst1 = v_dx * v_dy;
307 v_dst2 = v_dy * v_dy;
309 v_store_interleave(cov_data + j * 3, v_dst0, v_dst1, v_dst2);
314 for( ; j < size.width; j++ )
316 float dx = dxdata[j];
317 float dy = dydata[j];
319 cov_data[j*3] = dx*dx;
320 cov_data[j*3+1] = dx*dy;
321 cov_data[j*3+2] = dy*dy;
325 boxFilter(cov, cov, cov.depth(), Size(block_size, block_size),
326 Point(-1,-1), false, borderType );
328 if( op_type == MINEIGENVAL )
329 calcMinEigenVal( cov, eigenv );
330 else if( op_type == HARRIS )
331 calcHarris( cov, eigenv, k );
332 else if( op_type == EIGENVALSVECS )
333 calcEigenValsVecs( cov, eigenv );
338 static bool extractCovData(InputArray _src, UMat & Dx, UMat & Dy, int depth,
339 float scale, int aperture_size, int borderType)
341 UMat src = _src.getUMat();
345 src.locateROI(wholeSize, ofs);
347 const int sobel_lsz = 16;
348 if ((aperture_size == 3 || aperture_size == 5 || aperture_size == 7 || aperture_size == -1) &&
349 wholeSize.height > sobel_lsz + (aperture_size >> 1) &&
350 wholeSize.width > sobel_lsz + (aperture_size >> 1))
352 CV_Assert(depth == CV_8U || depth == CV_32F);
354 Dx.create(src.size(), CV_32FC1);
355 Dy.create(src.size(), CV_32FC1);
357 size_t localsize[2] = { (size_t)sobel_lsz, (size_t)sobel_lsz };
358 size_t globalsize[2] = { localsize[0] * (1 + (src.cols - 1) / localsize[0]),
359 localsize[1] * (1 + (src.rows - 1) / localsize[1]) };
361 int src_offset_x = (int)((src.offset % src.step) / src.elemSize());
362 int src_offset_y = (int)(src.offset / src.step);
364 const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
365 "BORDER_WRAP", "BORDER_REFLECT101" };
367 ocl::Kernel k(format("sobel%d", aperture_size).c_str(), ocl::imgproc::covardata_oclsrc,
368 cv::format("-D BLK_X=%d -D BLK_Y=%d -D %s -D SRCTYPE=%s%s",
369 (int)localsize[0], (int)localsize[1], borderTypes[borderType], ocl::typeToStr(depth),
370 aperture_size < 0 ? " -D SCHARR" : ""));
374 k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, src_offset_x, src_offset_y,
375 ocl::KernelArg::WriteOnlyNoSize(Dx), ocl::KernelArg::WriteOnly(Dy),
376 wholeSize.height, wholeSize.width, scale);
378 return k.run(2, globalsize, localsize, false);
382 if (aperture_size > 0)
384 Sobel(_src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType);
385 Sobel(_src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType);
389 Scharr(_src, Dx, CV_32F, 1, 0, scale, 0, borderType);
390 Scharr(_src, Dy, CV_32F, 0, 1, scale, 0, borderType);
397 static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size,
398 int aperture_size, double k, int borderType, int op_type)
400 CV_Assert(op_type == HARRIS || op_type == MINEIGENVAL);
402 if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE ||
403 borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) )
406 int type = _src.type(), depth = CV_MAT_DEPTH(type);
407 if ( !(type == CV_8UC1 || type == CV_32FC1) )
410 const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
411 "BORDER_WRAP", "BORDER_REFLECT101" };
412 const char * const cornerType[] = { "CORNER_MINEIGENVAL", "CORNER_HARRIS", 0 };
415 double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
416 if (aperture_size < 0)
423 if (!extractCovData(_src, Dx, Dy, depth, (float)scale, aperture_size, borderType))
426 ocl::Kernel cornelKernel("corner", ocl::imgproc::corner_oclsrc,
427 format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s -D %s",
428 block_size / 2, block_size / 2, block_size, block_size,
429 borderTypes[borderType], cornerType[op_type]));
430 if (cornelKernel.empty())
433 _dst.createSameSize(_src, CV_32FC1);
434 UMat dst = _dst.getUMat();
436 cornelKernel.args(ocl::KernelArg::ReadOnly(Dx), ocl::KernelArg::ReadOnly(Dy),
437 ocl::KernelArg::WriteOnly(dst), (float)k);
439 size_t blockSizeX = 256, blockSizeY = 1;
440 size_t gSize = blockSizeX - block_size / 2 * 2;
441 size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX;
442 size_t rows_per_thread = 2;
443 size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ?
444 ((Dx.rows + rows_per_thread - 1) / rows_per_thread) :
445 (((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY;
447 size_t globalsize[2] = { globalSizeX, globalSizeY }, localsize[2] = { blockSizeX, blockSizeY };
448 return cornelKernel.run(2, globalsize, localsize, false);
451 static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType, int depth )
453 UMat Dx, Dy, D2x, D2y, Dxy;
455 if (!extractCovData(_src, Dx, Dy, depth, 1, ksize, borderType))
458 Sobel( _src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );
459 Sobel( _src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );
460 Sobel( _src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );
462 _dst.create( _src.size(), CV_32FC1 );
463 UMat dst = _dst.getUMat();
465 double factor = 1 << (ksize - 1);
468 factor = 1./(factor * factor * factor);
470 ocl::Kernel k("preCornerDetect", ocl::imgproc::precornerdetect_oclsrc);
474 k.args(ocl::KernelArg::ReadOnlyNoSize(Dx), ocl::KernelArg::ReadOnlyNoSize(Dy),
475 ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y),
476 ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor);
478 size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows };
479 return k.run(2, globalsize, NULL, false);
486 #if defined(HAVE_IPP)
489 static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
491 #if IPP_VERSION_X100 >= 800
492 CV_INSTRUMENT_REGION_IPP()
494 Mat src = _src.getMat();
495 _dst.create( src.size(), CV_32FC1 );
496 Mat dst = _dst.getMat();
499 typedef IppStatus (CV_STDCALL * ippiMinEigenValGetBufferSize)(IppiSize, int, int, int*);
500 typedef IppStatus (CV_STDCALL * ippiMinEigenVal)(const void*, int, Ipp32f*, int, IppiSize, IppiKernelType, int, int, Ipp8u*);
501 IppiKernelType kerType;
505 kerType = ippKernelScharr;
509 kerType = ippKernelSobel;
511 bool isolated = (borderType & BORDER_ISOLATED) != 0;
512 int borderTypeNI = borderType & ~BORDER_ISOLATED;
513 if ((borderTypeNI == BORDER_REPLICATE && (!src.isSubmatrix() || isolated)) &&
514 (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5))
516 ippiMinEigenValGetBufferSize getBufferSizeFunc = 0;
517 ippiMinEigenVal ippiMinEigenVal_C1R = 0;
518 float norm_coef = 0.f;
520 if (src.type() == CV_8UC1)
522 getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_8u32f_C1R;
523 ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_8u32f_C1R;
524 norm_coef = 1.f / 255.f;
525 } else if (src.type() == CV_32FC1)
527 getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_32f_C1R;
528 ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_32f_C1R;
531 norm_coef = kerType == ippKernelSobel ? norm_coef : norm_coef / 2.45f;
533 if (getBufferSizeFunc && ippiMinEigenVal_C1R)
536 IppiSize srcRoi = { src.cols, src.rows };
537 IppStatus ok = getBufferSizeFunc(srcRoi, kerSize, blockSize, &bufferSize);
540 AutoBuffer<uchar> buffer(bufferSize);
541 ok = CV_INSTRUMENT_FUN_IPP(ippiMinEigenVal_C1R, src.ptr(), (int) src.step, dst.ptr<Ipp32f>(), (int) dst.step, srcRoi, kerType, kerSize, blockSize, buffer);
542 CV_SUPPRESS_DEPRECATED_START
543 if (ok >= 0) ok = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, norm_coef, dst.ptr<Ipp32f>(), (int) dst.step, srcRoi);
544 CV_SUPPRESS_DEPRECATED_END
547 CV_IMPL_ADD(CV_IMPL_IPP);
555 CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(blockSize); CV_UNUSED(borderType);
562 void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
564 CV_INSTRUMENT_REGION()
566 CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
567 ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL))
570 int kerSize = (ksize < 0)?3:ksize;
571 bool isolated = (borderType & BORDER_ISOLATED) != 0;
572 int borderTypeNI = borderType & ~BORDER_ISOLATED;
574 CV_IPP_RUN(((borderTypeNI == BORDER_REPLICATE && (!_src.isSubmatrix() || isolated)) &&
575 (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_X100 >= 800,
576 ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType ));
579 Mat src = _src.getMat();
580 _dst.create( src.size(), CV_32FC1 );
581 Mat dst = _dst.getMat();
583 cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType );
587 #if defined(HAVE_IPP)
590 static bool ipp_cornerHarris( Mat &src, Mat &dst, int blockSize, int ksize, double k, int borderType )
592 #if IPP_VERSION_X100 >= 810
593 CV_INSTRUMENT_REGION_IPP()
596 int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
597 int borderTypeNI = borderType & ~BORDER_ISOLATED;
598 bool isolated = (borderType & BORDER_ISOLATED) != 0;
600 if ( (ksize == 3 || ksize == 5) && (type == CV_8UC1 || type == CV_32FC1) &&
601 (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && cn == 1 && (!src.isSubmatrix() || isolated) )
603 IppiSize roisize = { src.cols, src.rows };
604 IppiMaskSize masksize = ksize == 5 ? ippMskSize5x5 : ippMskSize3x3;
605 IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp32f;
608 double scale = (double)(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;
613 scale = std::pow(scale, -4.0);
615 if (ippiHarrisCornerGetBufferSize(roisize, masksize, blockSize, datatype, cn, &bufsize) >= 0)
617 Ipp8u * buffer = (Ipp8u*)CV_IPP_MALLOC(bufsize);
618 IppiDifferentialKernel filterType = ksize > 0 ? ippFilterSobel : ippFilterScharr;
619 IppiBorderType borderTypeIpp = borderTypeNI == BORDER_CONSTANT ? ippBorderConst : ippBorderRepl;
620 IppStatus status = (IppStatus)-1;
623 status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_8u32f_C1R, (const Ipp8u *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,
624 filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);
625 else if (depth == CV_32F)
626 status = CV_INSTRUMENT_FUN_IPP(ippiHarrisCorner_32f_C1R, (const Ipp32f *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,
627 filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);
632 CV_IMPL_ADD(CV_IMPL_IPP);
639 CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(blockSize); CV_UNUSED(ksize); CV_UNUSED(k); CV_UNUSED(borderType);
646 void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType )
648 CV_INSTRUMENT_REGION()
650 CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
651 ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS))
653 Mat src = _src.getMat();
654 _dst.create( src.size(), CV_32FC1 );
655 Mat dst = _dst.getMat();
658 int borderTypeNI = borderType & ~BORDER_ISOLATED;
659 bool isolated = (borderType & BORDER_ISOLATED) != 0;
661 CV_IPP_RUN(((ksize == 3 || ksize == 5) && (_src.type() == CV_8UC1 || _src.type() == CV_32FC1) &&
662 (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && CV_MAT_CN(_src.type()) == 1 &&
663 (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 810, ipp_cornerHarris( src, dst, blockSize, ksize, k, borderType ));
665 cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType );
669 void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
671 CV_INSTRUMENT_REGION()
673 Mat src = _src.getMat();
674 Size dsz = _dst.size();
675 int dtype = _dst.type();
677 if( dsz.height != src.rows || dsz.width*CV_MAT_CN(dtype) != src.cols*6 || CV_MAT_DEPTH(dtype) != CV_32F )
678 _dst.create( src.size(), CV_32FC(6) );
679 Mat dst = _dst.getMat();
680 cornerEigenValsVecs( src, dst, blockSize, ksize, EIGENVALSVECS, 0, borderType );
684 void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType )
686 CV_INSTRUMENT_REGION()
688 int type = _src.type();
689 CV_Assert( type == CV_8UC1 || type == CV_32FC1 );
691 CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),
692 ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type)))
694 Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();
695 _dst.create( src.size(), CV_32FC1 );
696 Mat dst = _dst.getMat();
698 Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType );
699 Sobel( src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType );
700 Sobel( src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );
701 Sobel( src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );
702 Sobel( src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );
704 double factor = 1 << (ksize - 1);
705 if( src.depth() == CV_8U )
707 factor = 1./(factor * factor * factor);
709 float factor_f = (float)factor;
710 bool haveSimd = hasSIMD128();
711 v_float32x4 v_factor = v_setall_f32(factor_f), v_m2 = v_setall_f32(-2.0f);
714 Size size = src.size();
716 for( i = 0; i < size.height; i++ )
718 float* dstdata = dst.ptr<float>(i);
719 const float* dxdata = Dx.ptr<float>(i);
720 const float* dydata = Dy.ptr<float>(i);
721 const float* d2xdata = D2x.ptr<float>(i);
722 const float* d2ydata = D2y.ptr<float>(i);
723 const float* dxydata = Dxy.ptr<float>(i);
730 for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
732 v_float32x4 v_dx = v_load(dxdata + j);
733 v_float32x4 v_dy = v_load(dydata + j);
735 v_float32x4 v_s1 = (v_dx * v_dx) * v_load(d2ydata + j);
736 v_float32x4 v_s2 = v_muladd((v_dy * v_dy), v_load(d2xdata + j), v_s1);
737 v_float32x4 v_s3 = v_muladd((v_dy * v_dx) * v_load(dxydata + j), v_m2, v_s2);
739 v_store(dstdata + j, v_s3 * v_factor);
744 for( ; j < size.width; j++ )
746 float dx = dxdata[j];
747 float dy = dydata[j];
748 dstdata[j] = (float)(factor*(dx*dx*d2ydata[j] + dy*dy*d2xdata[j] - 2*dx*dy*dxydata[j]));
754 cvCornerMinEigenVal( const CvArr* srcarr, CvArr* dstarr,
755 int block_size, int aperture_size )
757 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
759 CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
760 cv::cornerMinEigenVal( src, dst, block_size, aperture_size, cv::BORDER_REPLICATE );
764 cvCornerHarris( const CvArr* srcarr, CvArr* dstarr,
765 int block_size, int aperture_size, double k )
767 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
769 CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
770 cv::cornerHarris( src, dst, block_size, aperture_size, k, cv::BORDER_REPLICATE );
775 cvCornerEigenValsAndVecs( const void* srcarr, void* dstarr,
776 int block_size, int aperture_size )
778 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
780 CV_Assert( src.rows == dst.rows && src.cols*6 == dst.cols*dst.channels() && dst.depth() == CV_32F );
781 cv::cornerEigenValsAndVecs( src, dst, block_size, aperture_size, cv::BORDER_REPLICATE );
786 cvPreCornerDetect( const void* srcarr, void* dstarr, int aperture_size )
788 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
790 CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
791 cv::preCornerDetect( src, dst, aperture_size, cv::BORDER_REPLICATE );