Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgproc/src/corner.cpp
16354 views
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
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
#if CV_SIMD128
60
bool haveSimd = hasSIMD128();
61
#endif
62
63
if( _cov.isContinuous() && _dst.isContinuous() )
64
{
65
size.width *= size.height;
66
size.height = 1;
67
}
68
69
for( i = 0; i < size.height; i++ )
70
{
71
const float* cov = _cov.ptr<float>(i);
72
float* dst = _dst.ptr<float>(i);
73
#if CV_TRY_AVX
74
if( haveAvx )
75
j = calcMinEigenValLine_AVX(cov, dst, size.width);
76
else
77
#endif // CV_TRY_AVX
78
j = 0;
79
80
#if CV_SIMD128
81
if( haveSimd )
82
{
83
v_float32x4 half = v_setall_f32(0.5f);
84
for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
85
{
86
v_float32x4 v_a, v_b, v_c, v_t;
87
v_load_deinterleave(cov + j*3, v_a, v_b, v_c);
88
v_a *= half;
89
v_c *= half;
90
v_t = v_a - 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));
93
}
94
}
95
#endif // CV_SIMD128
96
97
for( ; j < size.width; j++ )
98
{
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));
103
}
104
}
105
}
106
107
108
static void calcHarris( const Mat& _cov, Mat& _dst, double k )
109
{
110
int i, j;
111
Size size = _cov.size();
112
#if CV_TRY_AVX
113
bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
114
#endif
115
#if CV_SIMD128
116
bool haveSimd = hasSIMD128();
117
#endif
118
119
if( _cov.isContinuous() && _dst.isContinuous() )
120
{
121
size.width *= size.height;
122
size.height = 1;
123
}
124
125
for( i = 0; i < size.height; i++ )
126
{
127
const float* cov = _cov.ptr<float>(i);
128
float* dst = _dst.ptr<float>(i);
129
130
#if CV_TRY_AVX
131
if( haveAvx )
132
j = calcHarrisLine_AVX(cov, dst, k, size.width);
133
else
134
#endif // CV_TRY_AVX
135
j = 0;
136
137
#if CV_SIMD128
138
if( haveSimd )
139
{
140
v_float32x4 v_k = v_setall_f32((float)k);
141
142
for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
143
{
144
v_float32x4 v_a, v_b, v_c;
145
v_load_deinterleave(cov + j * 3, v_a, v_b, v_c);
146
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);
151
}
152
}
153
#endif // CV_SIMD128
154
155
for( ; j < size.width; j++ )
156
{
157
float a = cov[j*3];
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));
161
}
162
}
163
}
164
165
166
static void eigen2x2( const float* cov, float* dst, int n )
167
{
168
for( int j = 0; j < n; j++ )
169
{
170
double a = cov[j*3];
171
double b = cov[j*3+1];
172
double c = cov[j*3+2];
173
174
double u = (a + c)*0.5;
175
double v = std::sqrt((a - c)*(a - c)*0.25 + b*b);
176
double l1 = u + v;
177
double l2 = u - v;
178
179
double x = b;
180
double y = l1 - a;
181
double e = fabs(x);
182
183
if( e + fabs(y) < 1e-4 )
184
{
185
y = b;
186
x = l1 - c;
187
e = fabs(x);
188
if( e + fabs(y) < 1e-4 )
189
{
190
e = 1./(e + fabs(y) + FLT_EPSILON);
191
x *= e, y *= e;
192
}
193
}
194
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);
199
200
x = b;
201
y = l2 - a;
202
e = fabs(x);
203
204
if( e + fabs(y) < 1e-4 )
205
{
206
y = b;
207
x = l2 - c;
208
e = fabs(x);
209
if( e + fabs(y) < 1e-4 )
210
{
211
e = 1./(e + fabs(y) + FLT_EPSILON);
212
x *= e, y *= e;
213
}
214
}
215
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);
220
}
221
}
222
223
static void calcEigenValsVecs( const Mat& _cov, Mat& _dst )
224
{
225
Size size = _cov.size();
226
if( _cov.isContinuous() && _dst.isContinuous() )
227
{
228
size.width *= size.height;
229
size.height = 1;
230
}
231
232
for( int i = 0; i < size.height; i++ )
233
{
234
const float* cov = _cov.ptr<float>(i);
235
float* dst = _dst.ptr<float>(i);
236
237
eigen2x2(cov, dst, size.width);
238
}
239
}
240
241
242
enum { MINEIGENVAL=0, HARRIS=1, EIGENVALSVECS=2 };
243
244
245
static void
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 )
249
{
250
#if CV_TRY_AVX
251
bool haveAvx = CV_CPU_HAS_SUPPORT_AVX;
252
#endif
253
#if CV_SIMD128
254
bool haveSimd = hasSIMD128();
255
#endif
256
257
int depth = src.depth();
258
double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
259
if( aperture_size < 0 )
260
scale *= 2.0;
261
if( depth == CV_8U )
262
scale *= 255.0;
263
scale = 1.0/scale;
264
265
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
266
267
Mat Dx, Dy;
268
if( aperture_size > 0 )
269
{
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 );
272
}
273
else
274
{
275
Scharr( src, Dx, CV_32F, 1, 0, scale, 0, borderType );
276
Scharr( src, Dy, CV_32F, 0, 1, scale, 0, borderType );
277
}
278
279
Size size = src.size();
280
Mat cov( size, CV_32FC3 );
281
int i, j;
282
283
for( i = 0; i < size.height; i++ )
284
{
285
float* cov_data = cov.ptr<float>(i);
286
const float* dxdata = Dx.ptr<float>(i);
287
const float* dydata = Dy.ptr<float>(i);
288
289
#if CV_TRY_AVX
290
if( haveAvx )
291
j = cornerEigenValsVecsLine_AVX(dxdata, dydata, cov_data, size.width);
292
else
293
#endif // CV_TRY_AVX
294
j = 0;
295
296
#if CV_SIMD128
297
if( haveSimd )
298
{
299
for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
300
{
301
v_float32x4 v_dx = v_load(dxdata + j);
302
v_float32x4 v_dy = v_load(dydata + j);
303
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;
308
309
v_store_interleave(cov_data + j * 3, v_dst0, v_dst1, v_dst2);
310
}
311
}
312
#endif // CV_SIMD128
313
314
for( ; j < size.width; j++ )
315
{
316
float dx = dxdata[j];
317
float dy = dydata[j];
318
319
cov_data[j*3] = dx*dx;
320
cov_data[j*3+1] = dx*dy;
321
cov_data[j*3+2] = dy*dy;
322
}
323
}
324
325
boxFilter(cov, cov, cov.depth(), Size(block_size, block_size),
326
Point(-1,-1), false, borderType );
327
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 );
334
}
335
336
#ifdef HAVE_OPENCL
337
338
static bool extractCovData(InputArray _src, UMat & Dx, UMat & Dy, int depth,
339
float scale, int aperture_size, int borderType)
340
{
341
UMat src = _src.getUMat();
342
343
Size wholeSize;
344
Point ofs;
345
src.locateROI(wholeSize, ofs);
346
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))
351
{
352
CV_Assert(depth == CV_8U || depth == CV_32F);
353
354
Dx.create(src.size(), CV_32FC1);
355
Dy.create(src.size(), CV_32FC1);
356
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]) };
360
361
int src_offset_x = (int)((src.offset % src.step) / src.elemSize());
362
int src_offset_y = (int)(src.offset / src.step);
363
364
const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
365
"BORDER_WRAP", "BORDER_REFLECT101" };
366
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" : ""));
371
if (k.empty())
372
return false;
373
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);
377
378
return k.run(2, globalsize, localsize, false);
379
}
380
else
381
{
382
if (aperture_size > 0)
383
{
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);
386
}
387
else
388
{
389
Scharr(_src, Dx, CV_32F, 1, 0, scale, 0, borderType);
390
Scharr(_src, Dy, CV_32F, 0, 1, scale, 0, borderType);
391
}
392
}
393
394
return true;
395
}
396
397
static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size,
398
int aperture_size, double k, int borderType, int op_type)
399
{
400
CV_Assert(op_type == HARRIS || op_type == MINEIGENVAL);
401
402
if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE ||
403
borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) )
404
return false;
405
406
int type = _src.type(), depth = CV_MAT_DEPTH(type);
407
if ( !(type == CV_8UC1 || type == CV_32FC1) )
408
return false;
409
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 };
413
414
415
double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
416
if (aperture_size < 0)
417
scale *= 2.0;
418
if (depth == CV_8U)
419
scale *= 255.0;
420
scale = 1.0 / scale;
421
422
UMat Dx, Dy;
423
if (!extractCovData(_src, Dx, Dy, depth, (float)scale, aperture_size, borderType))
424
return false;
425
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())
431
return false;
432
433
_dst.createSameSize(_src, CV_32FC1);
434
UMat dst = _dst.getUMat();
435
436
cornelKernel.args(ocl::KernelArg::ReadOnly(Dx), ocl::KernelArg::ReadOnly(Dy),
437
ocl::KernelArg::WriteOnly(dst), (float)k);
438
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;
446
447
size_t globalsize[2] = { globalSizeX, globalSizeY }, localsize[2] = { blockSizeX, blockSizeY };
448
return cornelKernel.run(2, globalsize, localsize, false);
449
}
450
451
static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType, int depth )
452
{
453
UMat Dx, Dy, D2x, D2y, Dxy;
454
455
if (!extractCovData(_src, Dx, Dy, depth, 1, ksize, borderType))
456
return false;
457
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 );
461
462
_dst.create( _src.size(), CV_32FC1 );
463
UMat dst = _dst.getUMat();
464
465
double factor = 1 << (ksize - 1);
466
if( depth == CV_8U )
467
factor *= 255;
468
factor = 1./(factor * factor * factor);
469
470
ocl::Kernel k("preCornerDetect", ocl::imgproc::precornerdetect_oclsrc);
471
if (k.empty())
472
return false;
473
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);
477
478
size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows };
479
return k.run(2, globalsize, NULL, false);
480
}
481
482
#endif
483
484
}
485
486
#if defined(HAVE_IPP)
487
namespace cv
488
{
489
static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
490
{
491
#if IPP_VERSION_X100 >= 800
492
CV_INSTRUMENT_REGION_IPP();
493
494
Mat src = _src.getMat();
495
_dst.create( src.size(), CV_32FC1 );
496
Mat dst = _dst.getMat();
497
498
{
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;
502
int kerSize = ksize;
503
if (ksize < 0)
504
{
505
kerType = ippKernelScharr;
506
kerSize = 3;
507
} else
508
{
509
kerType = ippKernelSobel;
510
}
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))
515
{
516
ippiMinEigenValGetBufferSize getBufferSizeFunc = 0;
517
ippiMinEigenVal ippiMinEigenVal_C1R = 0;
518
float norm_coef = 0.f;
519
520
if (src.type() == CV_8UC1)
521
{
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)
526
{
527
getBufferSizeFunc = (ippiMinEigenValGetBufferSize) ippiMinEigenValGetBufferSize_32f_C1R;
528
ippiMinEigenVal_C1R = (ippiMinEigenVal) ippiMinEigenVal_32f_C1R;
529
norm_coef = 255.f;
530
}
531
norm_coef = kerType == ippKernelSobel ? norm_coef : norm_coef / 2.45f;
532
533
if (getBufferSizeFunc && ippiMinEigenVal_C1R)
534
{
535
int bufferSize;
536
IppiSize srcRoi = { src.cols, src.rows };
537
IppStatus ok = getBufferSizeFunc(srcRoi, kerSize, blockSize, &bufferSize);
538
if (ok >= 0)
539
{
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.data());
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
545
if (ok >= 0)
546
{
547
CV_IMPL_ADD(CV_IMPL_IPP);
548
return true;
549
}
550
}
551
}
552
}
553
}
554
#else
555
CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(blockSize); CV_UNUSED(borderType);
556
#endif
557
return false;
558
}
559
}
560
#endif
561
562
void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
563
{
564
CV_INSTRUMENT_REGION();
565
566
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
567
ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL))
568
569
#ifdef HAVE_IPP
570
int kerSize = (ksize < 0)?3:ksize;
571
bool isolated = (borderType & BORDER_ISOLATED) != 0;
572
int borderTypeNI = borderType & ~BORDER_ISOLATED;
573
#endif
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 ));
577
578
579
Mat src = _src.getMat();
580
_dst.create( src.size(), CV_32FC1 );
581
Mat dst = _dst.getMat();
582
583
cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType );
584
}
585
586
587
#if defined(HAVE_IPP)
588
namespace cv
589
{
590
static bool ipp_cornerHarris( Mat &src, Mat &dst, int blockSize, int ksize, double k, int borderType )
591
{
592
#if IPP_VERSION_X100 >= 810
593
CV_INSTRUMENT_REGION_IPP();
594
595
{
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;
599
600
if ( (ksize == 3 || ksize == 5) && (type == CV_8UC1 || type == CV_32FC1) &&
601
(borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && cn == 1 && (!src.isSubmatrix() || isolated) )
602
{
603
IppiSize roisize = { src.cols, src.rows };
604
IppiMaskSize masksize = ksize == 5 ? ippMskSize5x5 : ippMskSize3x3;
605
IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp32f;
606
Ipp32s bufsize = 0;
607
608
double scale = (double)(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;
609
if (ksize < 0)
610
scale *= 2.0;
611
if (depth == CV_8U)
612
scale *= 255.0;
613
scale = std::pow(scale, -4.0);
614
615
if (ippiHarrisCornerGetBufferSize(roisize, masksize, blockSize, datatype, cn, &bufsize) >= 0)
616
{
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;
621
622
if (depth == CV_8U)
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);
628
ippsFree(buffer);
629
630
if (status >= 0)
631
{
632
CV_IMPL_ADD(CV_IMPL_IPP);
633
return true;
634
}
635
}
636
}
637
}
638
#else
639
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(blockSize); CV_UNUSED(ksize); CV_UNUSED(k); CV_UNUSED(borderType);
640
#endif
641
return false;
642
}
643
}
644
#endif
645
646
void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType )
647
{
648
CV_INSTRUMENT_REGION();
649
650
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
651
ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS))
652
653
Mat src = _src.getMat();
654
_dst.create( src.size(), CV_32FC1 );
655
Mat dst = _dst.getMat();
656
657
#ifdef HAVE_IPP
658
int borderTypeNI = borderType & ~BORDER_ISOLATED;
659
bool isolated = (borderType & BORDER_ISOLATED) != 0;
660
#endif
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 ));
664
665
cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType );
666
}
667
668
669
void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
670
{
671
CV_INSTRUMENT_REGION();
672
673
Mat src = _src.getMat();
674
Size dsz = _dst.size();
675
int dtype = _dst.type();
676
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 );
681
}
682
683
684
void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType )
685
{
686
CV_INSTRUMENT_REGION();
687
688
int type = _src.type();
689
CV_Assert( type == CV_8UC1 || type == CV_32FC1 );
690
691
CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),
692
ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type)))
693
694
Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();
695
_dst.create( src.size(), CV_32FC1 );
696
Mat dst = _dst.getMat();
697
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 );
703
704
double factor = 1 << (ksize - 1);
705
if( src.depth() == CV_8U )
706
factor *= 255;
707
factor = 1./(factor * factor * factor);
708
#if CV_SIMD128
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);
712
#endif
713
714
Size size = src.size();
715
int i, j;
716
for( i = 0; i < size.height; i++ )
717
{
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);
724
725
j = 0;
726
727
#if CV_SIMD128
728
if (haveSimd)
729
{
730
for( ; j <= size.width - v_float32x4::nlanes; j += v_float32x4::nlanes )
731
{
732
v_float32x4 v_dx = v_load(dxdata + j);
733
v_float32x4 v_dy = v_load(dydata + j);
734
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);
738
739
v_store(dstdata + j, v_s3 * v_factor);
740
}
741
}
742
#endif
743
744
for( ; j < size.width; j++ )
745
{
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]));
749
}
750
}
751
}
752
753
CV_IMPL void
754
cvCornerMinEigenVal( const CvArr* srcarr, CvArr* dstarr,
755
int block_size, int aperture_size )
756
{
757
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
758
759
CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
760
cv::cornerMinEigenVal( src, dst, block_size, aperture_size, cv::BORDER_REPLICATE );
761
}
762
763
CV_IMPL void
764
cvCornerHarris( const CvArr* srcarr, CvArr* dstarr,
765
int block_size, int aperture_size, double k )
766
{
767
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
768
769
CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
770
cv::cornerHarris( src, dst, block_size, aperture_size, k, cv::BORDER_REPLICATE );
771
}
772
773
774
CV_IMPL void
775
cvCornerEigenValsAndVecs( const void* srcarr, void* dstarr,
776
int block_size, int aperture_size )
777
{
778
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
779
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 );
782
}
783
784
785
CV_IMPL void
786
cvPreCornerDetect( const void* srcarr, void* dstarr, int aperture_size )
787
{
788
cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
789
790
CV_Assert( src.size() == dst.size() && dst.type() == CV_32FC1 );
791
cv::preCornerDetect( src, dst, aperture_size, cv::BORDER_REPLICATE );
792
}
793
794
/* End of file */
795
796