Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv_contrib
Commits
7e46ea16
Commit
7e46ea16
authored
Sep 29, 2017
by
Vitaly Tuzov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Removed helper functions from header.
Updated module license text.
parent
1c580151
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
384 additions
and
421 deletions
+384
-421
xfeatures2d.hpp
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
+0
-6
fast.cpp
modules/xfeatures2d/src/fast.cpp
+384
-415
No files found.
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
View file @
7e46ea16
...
@@ -279,12 +279,6 @@ CV_EXPORTS void FASTForPointSet( InputArray image, CV_IN_OUT std::vector<KeyPoin
...
@@ -279,12 +279,6 @@ CV_EXPORTS void FASTForPointSet( InputArray image, CV_IN_OUT std::vector<KeyPoin
int
threshold
,
bool
nonmaxSuppression
=
true
,
int
type
=
FastFeatureDetector
::
TYPE_9_16
);
int
threshold
,
bool
nonmaxSuppression
=
true
,
int
type
=
FastFeatureDetector
::
TYPE_9_16
);
void
makeOffsets
(
int
pixel
[
25
],
int
row_stride
,
int
patternSize
);
template
<
int
patternSize
>
int
cornerScore
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
);
//! @}
//! @}
}
}
...
...
modules/xfeatures2d/src/fast.cpp
View file @
7e46ea16
/*M///////////////////////////////////////////////////////////////////////////////////////
// This file is part of OpenCV project.
//
// It is subject to the license terms in the LICENSE file found in the top-level directory
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
// of this distribution and at http://opencv.org/license.html.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d.hpp>
...
@@ -46,449 +8,455 @@
...
@@ -46,449 +8,455 @@
#define VERIFY_CORNERS 0
#define VERIFY_CORNERS 0
#endif
#endif
namespace
cv
{
namespace
{
namespace
xfeatures2d
{
using
namespace
cv
;
#if VERIFY_CORNERS
void
testCorner
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
K
,
int
N
,
int
threshold
)
{
// check that with the computed "threshold" the pixel is still a corner
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
for
(
int
delta
=
0
;
delta
<=
1
;
delta
++
)
{
int
v0
=
std
::
min
(
ptr
[
0
]
+
threshold
+
delta
,
255
);
int
v1
=
std
::
max
(
ptr
[
0
]
-
threshold
-
delta
,
0
);
int
c0
=
0
,
c1
=
0
;
#if VERIFY_CORNERS
for
(
int
k
=
0
;
k
<
N
;
k
++
)
static
void
testCorner
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
K
,
int
N
,
int
threshold
)
{
// check that with the computed "threshold" the pixel is still a corner
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
for
(
int
delta
=
0
;
delta
<=
1
;
delta
++
)
{
{
int
v0
=
std
::
min
(
ptr
[
0
]
+
threshold
+
delta
,
255
);
int
x
=
ptr
[
pixel
[
k
]];
int
v1
=
std
::
max
(
ptr
[
0
]
-
threshold
-
delta
,
0
);
if
(
x
>
v0
)
int
c0
=
0
,
c1
=
0
;
for
(
int
k
=
0
;
k
<
N
;
k
++
)
{
{
int
x
=
ptr
[
pixel
[
k
]];
if
(
++
c0
>
K
)
if
(
x
>
v0
)
break
;
{
c1
=
0
;
if
(
++
c0
>
K
)
}
break
;
else
if
(
x
<
v1
)
c1
=
0
;
{
}
if
(
++
c1
>
K
)
else
if
(
x
<
v1
)
break
;
{
c0
=
0
;
if
(
++
c1
>
K
)
}
break
;
else
c0
=
0
;
{
}
c0
=
c1
=
0
;
else
{
c0
=
c1
=
0
;
}
}
}
CV_Assert
(
(
delta
==
0
&&
std
::
max
(
c0
,
c1
)
>
K
)
||
(
delta
==
1
&&
std
::
max
(
c0
,
c1
)
<=
K
)
);
}
}
CV_Assert
(
(
delta
==
0
&&
std
::
max
(
c0
,
c1
)
>
K
)
||
(
delta
==
1
&&
std
::
max
(
c0
,
c1
)
<=
K
)
);
}
}
#endif
}
#endif
template
<>
int
cornerScore
<
16
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
template
<
int
patternSize
>
int
cornerScore
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
);
template
<>
int
cornerScore
<
16
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
{
const
int
K
=
8
,
N
=
K
*
3
+
1
;
int
k
,
v
=
ptr
[
0
];
short
d
[
N
];
for
(
k
=
0
;
k
<
N
;
k
++
)
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
#if CV_SSE2
__m128i
q0
=
_mm_set1_epi16
(
-
1000
),
q1
=
_mm_set1_epi16
(
1000
);
for
(
k
=
0
;
k
<
16
;
k
+=
8
)
{
{
const
int
K
=
8
,
N
=
K
*
3
+
1
;
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
1
));
int
k
,
v
=
ptr
[
0
];
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
2
));
short
d
[
N
];
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
for
(
k
=
0
;
k
<
N
;
k
++
)
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
3
));
a
=
_mm_min_epi16
(
a
,
v0
);
#if CV_SSE2
b
=
_mm_max_epi16
(
b
,
v0
);
__m128i
q0
=
_mm_set1_epi16
(
-
1000
),
q1
=
_mm_set1_epi16
(
1000
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
4
));
for
(
k
=
0
;
k
<
16
;
k
+=
8
)
a
=
_mm_min_epi16
(
a
,
v0
);
{
b
=
_mm_max_epi16
(
b
,
v0
);
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
1
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
5
));
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
2
));
a
=
_mm_min_epi16
(
a
,
v0
);
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
b
=
_mm_max_epi16
(
b
,
v0
);
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
6
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
3
));
a
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
7
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
4
));
a
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
8
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
5
));
a
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
6
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
a
=
_mm_min_epi16
(
a
,
v0
);
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
9
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
7
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
a
=
_mm_min_epi16
(
a
,
v0
);
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
8
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
9
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
}
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
#else
int
a0
=
threshold
;
for
(
k
=
0
;
k
<
16
;
k
+=
2
)
{
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
if
(
a
<=
a0
)
continue
;
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
6
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
7
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
8
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
9
]));
}
int
b0
=
-
a0
;
for
(
k
=
0
;
k
<
16
;
k
+=
2
)
{
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]);
if
(
b
>=
b0
)
continue
;
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
6
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
7
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
8
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
9
]));
}
threshold
=
-
b0
-
1
;
#endif
#if VERIFY_CORNERS
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
#endif
return
threshold
;
}
}
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
template
<>
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
int
cornerScore
<
12
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
#else
int
a0
=
threshold
;
for
(
k
=
0
;
k
<
16
;
k
+=
2
)
{
{
const
int
K
=
6
,
N
=
K
*
3
+
1
;
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
int
k
,
v
=
ptr
[
0
];
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
short
d
[
N
+
4
];
if
(
a
<=
a0
)
for
(
k
=
0
;
k
<
N
;
k
++
)
continue
;
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
#if CV_SSE2
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]);
for
(
k
=
0
;
k
<
4
;
k
++
)
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
6
]);
d
[
N
+
k
]
=
d
[
k
];
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
7
]);
#endif
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
8
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
#if CV_SSE2
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
9
]));
__m128i
q0
=
_mm_set1_epi16
(
-
1000
),
q1
=
_mm_set1_epi16
(
1000
);
}
for
(
k
=
0
;
k
<
16
;
k
+=
8
)
{
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
1
));
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
2
));
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
3
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
4
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
5
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
6
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
7
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
}
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
#else
int
a0
=
threshold
;
for
(
k
=
0
;
k
<
12
;
k
+=
2
)
{
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
if
(
a
<=
a0
)
continue
;
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
6
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
7
]));
}
int
b0
=
-
a0
;
int
b0
=
-
a0
;
for
(
k
=
0
;
k
<
12
;
k
+=
2
)
for
(
k
=
0
;
k
<
16
;
k
+=
2
)
{
{
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
if
(
b
>=
b0
)
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]);
continue
;
if
(
b
>=
b0
)
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]);
continue
;
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
6
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
6
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
7
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
8
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
7
]));
}
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
9
]));
}
threshold
=
-
b0
-
1
;
threshold
=
-
b0
-
1
;
#endif
#endif
#if VERIFY_CORNERS
#if VERIFY_CORNERS
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
#endif
#endif
return
threshold
;
return
threshold
;
}
}
template
<>
template
<>
int
cornerScore
<
8
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
int
cornerScore
<
12
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
{
const
int
K
=
6
,
N
=
K
*
3
+
1
;
int
k
,
v
=
ptr
[
0
];
short
d
[
N
+
4
];
for
(
k
=
0
;
k
<
N
;
k
++
)
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
#if CV_SSE2
for
(
k
=
0
;
k
<
4
;
k
++
)
d
[
N
+
k
]
=
d
[
k
];
#endif
#if CV_SSE2
__m128i
q0
=
_mm_set1_epi16
(
-
1000
),
q1
=
_mm_set1_epi16
(
1000
);
for
(
k
=
0
;
k
<
16
;
k
+=
8
)
{
{
const
int
K
=
4
,
N
=
K
*
3
+
1
;
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
1
));
int
k
,
v
=
ptr
[
0
];
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
2
));
short
d
[
N
];
for
(
k
=
0
;
k
<
N
;
k
++
)
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
#if CV_SSE2
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
1
));
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
2
));
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
3
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
3
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
4
));
a
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
4
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
5
));
a
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
6
));
__m128i
q0
=
_mm_min_epi16
(
a
,
v0
);
a
=
_mm_min_epi16
(
a
,
v0
);
__m128i
q1
=
_mm_max_epi16
(
b
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
5
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
k
+
7
));
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
}
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
#else
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
int
a0
=
threshold
;
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
for
(
k
=
0
;
k
<
8
;
k
+=
2
)
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
{
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
#else
if
(
a
<=
a0
)
int
a0
=
threshold
;
continue
;
for
(
k
=
0
;
k
<
12
;
k
+=
2
)
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
{
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
if
(
a
<=
a0
)
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]));
continue
;
}
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
6
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
7
]));
}
int
b0
=
-
a0
;
int
b0
=
-
a0
;
for
(
k
=
0
;
k
<
8
;
k
+=
2
)
for
(
k
=
0
;
k
<
12
;
k
+=
2
)
{
{
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
if
(
b
>=
b0
)
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
continue
;
if
(
b
>=
b0
)
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
continue
;
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
6
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]));
}
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
7
]));
}
threshold
=
-
b0
-
1
;
threshold
=
-
b0
-
1
;
#endif
#endif
#if VERIFY_CORNERS
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
#endif
return
threshold
;
}
#if VERIFY_CORNERS
template
<>
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
int
cornerScore
<
8
>
(
const
uchar
*
ptr
,
const
int
pixel
[],
int
threshold
)
#endif
{
return
threshold
;
const
int
K
=
4
,
N
=
K
*
3
+
1
;
int
k
,
v
=
ptr
[
0
];
short
d
[
N
];
for
(
k
=
0
;
k
<
N
;
k
++
)
d
[
k
]
=
(
short
)(
v
-
ptr
[
pixel
[
k
]]);
#if CV_SSE2
__m128i
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
1
));
__m128i
v1
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
2
));
__m128i
a
=
_mm_min_epi16
(
v0
,
v1
);
__m128i
b
=
_mm_max_epi16
(
v0
,
v1
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
3
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
4
));
a
=
_mm_min_epi16
(
a
,
v0
);
b
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
));
__m128i
q0
=
_mm_min_epi16
(
a
,
v0
);
__m128i
q1
=
_mm_max_epi16
(
b
,
v0
);
v0
=
_mm_loadu_si128
((
__m128i
*
)(
d
+
5
));
q0
=
_mm_max_epi16
(
q0
,
_mm_min_epi16
(
a
,
v0
));
q1
=
_mm_min_epi16
(
q1
,
_mm_max_epi16
(
b
,
v0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_sub_epi16
(
_mm_setzero_si128
(),
q1
));
q0
=
_mm_max_epi16
(
q0
,
_mm_unpackhi_epi64
(
q0
,
q0
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
4
));
q0
=
_mm_max_epi16
(
q0
,
_mm_srli_si128
(
q0
,
2
));
threshold
=
(
short
)
_mm_cvtsi128_si32
(
q0
)
-
1
;
#else
int
a0
=
threshold
;
for
(
k
=
0
;
k
<
8
;
k
+=
2
)
{
int
a
=
std
::
min
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
if
(
a
<=
a0
)
continue
;
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
3
]);
a
=
std
::
min
(
a
,
(
int
)
d
[
k
+
4
]);
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
]));
a0
=
std
::
max
(
a0
,
std
::
min
(
a
,
(
int
)
d
[
k
+
5
]));
}
}
void
makeOffsets
(
int
pixel
[
25
],
int
rowStride
,
int
patternSize
)
int
b0
=
-
a0
;
for
(
k
=
0
;
k
<
8
;
k
+=
2
)
{
{
static
const
int
offsets16
[][
2
]
=
int
b
=
std
::
max
((
int
)
d
[
k
+
1
],
(
int
)
d
[
k
+
2
]);
{
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
3
]);
{
0
,
3
},
{
1
,
3
},
{
2
,
2
},
{
3
,
1
},
{
3
,
0
},
{
3
,
-
1
},
{
2
,
-
2
},
{
1
,
-
3
},
if
(
b
>=
b0
)
{
0
,
-
3
},
{
-
1
,
-
3
},
{
-
2
,
-
2
},
{
-
3
,
-
1
},
{
-
3
,
0
},
{
-
3
,
1
},
{
-
2
,
2
},
{
-
1
,
3
}
continue
;
};
b
=
std
::
max
(
b
,
(
int
)
d
[
k
+
4
]);
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
]));
b0
=
std
::
min
(
b0
,
std
::
max
(
b
,
(
int
)
d
[
k
+
5
]));
}
static
const
int
offsets12
[][
2
]
=
threshold
=
-
b0
-
1
;
{
#endif
{
0
,
2
},
{
1
,
2
},
{
2
,
1
},
{
2
,
0
},
{
2
,
-
1
},
{
1
,
-
2
},
{
0
,
-
2
},
{
-
1
,
-
2
},
{
-
2
,
-
1
},
{
-
2
,
0
},
{
-
2
,
1
},
{
-
1
,
2
}
};
static
const
int
offsets8
[][
2
]
=
#if VERIFY_CORNERS
{
testCorner
(
ptr
,
pixel
,
K
,
N
,
threshold
);
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,
-
1
},
#endif
{
0
,
-
1
},
{
-
1
,
-
1
},
{
-
1
,
0
},
{
-
1
,
1
}
return
threshold
;
};
}
const
int
(
*
offsets
)[
2
]
=
patternSize
==
16
?
offsets16
:
void
makeOffsets
(
int
pixel
[
25
],
int
rowStride
,
int
patternSize
)
patternSize
==
12
?
offsets12
:
{
patternSize
==
8
?
offsets8
:
0
;
static
const
int
offsets16
[][
2
]
=
{
{
0
,
3
},
{
1
,
3
},
{
2
,
2
},
{
3
,
1
},
{
3
,
0
},
{
3
,
-
1
},
{
2
,
-
2
},
{
1
,
-
3
},
{
0
,
-
3
},
{
-
1
,
-
3
},
{
-
2
,
-
2
},
{
-
3
,
-
1
},
{
-
3
,
0
},
{
-
3
,
1
},
{
-
2
,
2
},
{
-
1
,
3
}
};
CV_Assert
(
pixel
&&
offsets
);
static
const
int
offsets12
[][
2
]
=
{
{
0
,
2
},
{
1
,
2
},
{
2
,
1
},
{
2
,
0
},
{
2
,
-
1
},
{
1
,
-
2
},
{
0
,
-
2
},
{
-
1
,
-
2
},
{
-
2
,
-
1
},
{
-
2
,
0
},
{
-
2
,
1
},
{
-
1
,
2
}
};
int
k
=
0
;
static
const
int
offsets8
[][
2
]
=
for
(
;
k
<
patternSize
;
k
++
)
{
pixel
[
k
]
=
offsets
[
k
][
0
]
+
offsets
[
k
][
1
]
*
rowStride
;
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,
-
1
},
for
(
;
k
<
25
;
k
++
)
{
0
,
-
1
},
{
-
1
,
-
1
},
{
-
1
,
0
},
{
-
1
,
1
}
pixel
[
k
]
=
pixel
[
k
-
patternSize
];
};
}
template
<
int
patternSize
>
const
int
(
*
offsets
)[
2
]
=
patternSize
==
16
?
offsets16
:
void
FASTForPointSet_t
(
InputArray
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
int
threshold
,
bool
nonmaxSuppression
)
{
patternSize
==
12
?
offsets12
:
patternSize
==
8
?
offsets8
:
0
;
Mat
img
=
image
.
getMat
();
CV_Assert
(
pixel
&&
offsets
);
const
int
K
=
patternSize
/
2
,
N
=
patternSize
+
K
+
1
;
int
i
,
k
,
pixel
[
25
];
int
k
=
0
;
makeOffsets
(
pixel
,
(
int
)
img
.
step
,
patternSize
);
for
(
;
k
<
patternSize
;
k
++
)
pixel
[
k
]
=
offsets
[
k
][
0
]
+
offsets
[
k
][
1
]
*
rowStride
;
for
(
;
k
<
25
;
k
++
)
pixel
[
k
]
=
pixel
[
k
-
patternSize
];
}
keypoints
.
clear
();
template
<
int
patternSize
>
void
FASTForPointSet_t
(
InputArray
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
int
threshold
,
bool
nonmaxSuppression
)
{
threshold
=
std
::
min
(
std
::
max
(
threshold
,
0
),
255
);
Mat
img
=
image
.
getMat
();
const
int
K
=
patternSize
/
2
,
N
=
patternSize
+
K
+
1
;
uchar
threshold_tab
[
512
];
int
i
,
k
,
pixel
[
25
];
for
(
i
=
-
255
;
i
<=
255
;
i
++
)
makeOffsets
(
pixel
,
(
int
)
img
.
step
,
patternSize
);
threshold_tab
[
i
+
255
]
=
(
uchar
)(
i
<
-
threshold
?
1
:
i
>
threshold
?
2
:
0
);
AutoBuffer
<
uchar
>
_buf
((
img
.
cols
+
16
)
*
3
*
(
sizeof
(
int
)
+
sizeof
(
uchar
))
+
128
);
keypoints
.
clear
();
uchar
*
buf
[
3
];
buf
[
0
]
=
_buf
;
buf
[
1
]
=
buf
[
0
]
+
img
.
cols
;
buf
[
2
]
=
buf
[
1
]
+
img
.
cols
;
int
*
cpbuf
[
3
];
cpbuf
[
0
]
=
(
int
*
)
alignPtr
(
buf
[
2
]
+
img
.
cols
,
sizeof
(
int
))
+
1
;
cpbuf
[
1
]
=
cpbuf
[
0
]
+
img
.
cols
+
1
;
cpbuf
[
2
]
=
cpbuf
[
1
]
+
img
.
cols
+
1
;
memset
(
buf
[
0
],
0
,
img
.
cols
*
3
);
// Calculate threshold for the keypoints
threshold
=
std
::
min
(
std
::
max
(
threshold
,
0
),
255
);
for
(
size_t
keyPointIdx
=
0
;
keyPointIdx
<
keypoints
.
size
();
keyPointIdx
++
)
{
// Set response to -1:
// All keypoints with response <= 0 will be removed afterwards
keypoints
[
keyPointIdx
].
response
=
-
1
;
// Poiter to keyPoint in image
uchar
threshold_tab
[
512
];
Point
keyPoint
=
keypoints
[
keyPointIdx
].
pt
;
for
(
i
=
-
255
;
i
<=
255
;
i
++
)
const
uchar
*
ptr
=
img
.
ptr
<
uchar
>
(
keyPoint
.
y
,
keyPoint
.
x
);
threshold_tab
[
i
+
255
]
=
(
uchar
)(
i
<
-
threshold
?
1
:
i
>
threshold
?
2
:
0
);
// value of the pixel at certain position
AutoBuffer
<
uchar
>
_buf
((
img
.
cols
+
16
)
*
3
*
(
sizeof
(
int
)
+
sizeof
(
uchar
))
+
128
);
int
v
=
ptr
[
0
];
uchar
*
buf
[
3
];
buf
[
0
]
=
_buf
;
buf
[
1
]
=
buf
[
0
]
+
img
.
cols
;
buf
[
2
]
=
buf
[
1
]
+
img
.
cols
;
int
*
cpbuf
[
3
];
cpbuf
[
0
]
=
(
int
*
)
alignPtr
(
buf
[
2
]
+
img
.
cols
,
sizeof
(
int
))
+
1
;
cpbuf
[
1
]
=
cpbuf
[
0
]
+
img
.
cols
+
1
;
cpbuf
[
2
]
=
cpbuf
[
1
]
+
img
.
cols
+
1
;
memset
(
buf
[
0
],
0
,
img
.
cols
*
3
);
// Initialize Lookup table
// Calculate threshold for the keypoints
// If k=v --> tab[k] is at the center of the thrshold table
for
(
size_t
keyPointIdx
=
0
;
keyPointIdx
<
keypoints
.
size
();
keyPointIdx
++
)
{
// The threshold table is made as follows:
// Set response to -1:
// -255 -threshold 0 +threshold 255
// All keypoints with response <= 0 will be removed afterwards
// 111111111111111111|0000000000000|0000000000000|222222222222222
keypoints
[
keyPointIdx
].
response
=
-
1
;
const
uchar
*
tab
=
&
threshold_tab
[
0
]
-
v
+
255
;
// Calculate the fast value
// Poiter to keyPoint in image
int
d
=
tab
[
ptr
[
pixel
[
0
]]]
|
tab
[
ptr
[
pixel
[
8
]]];
Point
keyPoint
=
keypoints
[
keyPointIdx
].
pt
;
const
uchar
*
ptr
=
img
.
ptr
<
uchar
>
(
keyPoint
.
y
,
keyPoint
.
x
);
if
(
d
==
0
)
// value of the pixel at certain position
continue
;
int
v
=
ptr
[
0
]
;
d
&=
tab
[
ptr
[
pixel
[
2
]]]
|
tab
[
ptr
[
pixel
[
10
]]];
// Initialize Lookup table
d
&=
tab
[
ptr
[
pixel
[
4
]]]
|
tab
[
ptr
[
pixel
[
12
]]];
// If k=v --> tab[k] is at the center of the thrshold table
d
&=
tab
[
ptr
[
pixel
[
6
]]]
|
tab
[
ptr
[
pixel
[
14
]]];
// The threshold table is made as follows:
// -255 -threshold 0 +threshold 255
// 111111111111111111|0000000000000|0000000000000|222222222222222
const
uchar
*
tab
=
&
threshold_tab
[
0
]
-
v
+
255
;
if
(
d
==
0
)
// Calculate the fast value
continue
;
int
d
=
tab
[
ptr
[
pixel
[
0
]]]
|
tab
[
ptr
[
pixel
[
8
]]]
;
d
&=
tab
[
ptr
[
pixel
[
1
]]]
|
tab
[
ptr
[
pixel
[
9
]]];
if
(
d
==
0
)
d
&=
tab
[
ptr
[
pixel
[
3
]]]
|
tab
[
ptr
[
pixel
[
11
]]];
continue
;
d
&=
tab
[
ptr
[
pixel
[
5
]]]
|
tab
[
ptr
[
pixel
[
13
]]];
d
&=
tab
[
ptr
[
pixel
[
7
]]]
|
tab
[
ptr
[
pixel
[
15
]]];
// For at least half pixels darker than v count the number
d
&=
tab
[
ptr
[
pixel
[
2
]]]
|
tab
[
ptr
[
pixel
[
10
]]];
if
(
d
&
1
)
d
&=
tab
[
ptr
[
pixel
[
4
]]]
|
tab
[
ptr
[
pixel
[
12
]]];
{
d
&=
tab
[
ptr
[
pixel
[
6
]]]
|
tab
[
ptr
[
pixel
[
14
]]];
int
vt
=
v
-
threshold
,
count
=
0
;
if
(
d
==
0
)
continue
;
d
&=
tab
[
ptr
[
pixel
[
1
]]]
|
tab
[
ptr
[
pixel
[
9
]]];
d
&=
tab
[
ptr
[
pixel
[
3
]]]
|
tab
[
ptr
[
pixel
[
11
]]];
d
&=
tab
[
ptr
[
pixel
[
5
]]]
|
tab
[
ptr
[
pixel
[
13
]]];
d
&=
tab
[
ptr
[
pixel
[
7
]]]
|
tab
[
ptr
[
pixel
[
15
]]];
for
(
k
=
0
;
k
<
N
;
k
++
)
// For at least half pixels darker than v count the number
if
(
d
&
1
)
{
int
vt
=
v
-
threshold
,
count
=
0
;
for
(
k
=
0
;
k
<
N
;
k
++
)
{
int
x
=
ptr
[
pixel
[
k
]];
if
(
x
<
vt
)
{
{
int
x
=
ptr
[
pixel
[
k
]];
if
(
++
count
>
K
)
if
(
x
<
vt
)
{
{
if
(
++
count
>
K
)
// Calculate score
{
keypoints
[
keyPointIdx
].
response
=
(
uchar
)
cornerScore
<
patternSize
>
(
ptr
,
pixel
,
threshold
);
// Calculate score
// Non Maxima Supression I
keypoints
[
keyPointIdx
].
response
=
(
uchar
)
cornerScore
<
patternSize
>
(
ptr
,
pixel
,
threshold
);
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
<
keypoints
[
keyPointIdx
].
response
)
{
// Non Maxima Supression I
keypoints
[
keyPointIdx
-
1
].
response
=
-
1
;
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
<
keypoints
[
keyPointIdx
].
response
)
{
keypoints
[
keyPointIdx
-
1
].
response
=
-
1
;
}
break
;
}
}
break
;
}
}
else
count
=
0
;
}
}
else
count
=
0
;
}
}
}
// For at least half pixels brighter than v count the number
// For at least half pixels brighter than v count the number
if
(
d
&
2
)
if
(
d
&
2
)
{
{
int
vt
=
v
+
threshold
,
count
=
0
;
int
vt
=
v
+
threshold
,
count
=
0
;
for
(
k
=
0
;
k
<
N
;
k
++
)
for
(
k
=
0
;
k
<
N
;
k
++
)
{
int
x
=
ptr
[
pixel
[
k
]];
if
(
x
>
vt
)
{
{
int
x
=
ptr
[
pixel
[
k
]];
if
(
++
count
>
K
)
if
(
x
>
vt
)
{
{
if
(
++
count
>
K
)
// Calculate score
{
keypoints
[
keyPointIdx
].
response
=
(
uchar
)
cornerScore
<
patternSize
>
(
ptr
,
pixel
,
threshold
);
// Calculate score
// Non Maxima Suppression I
keypoints
[
keyPointIdx
].
response
=
(
uchar
)
cornerScore
<
patternSize
>
(
ptr
,
pixel
,
threshold
);
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
<
keypoints
[
keyPointIdx
].
response
)
{
// Non Maxima Suppression I
keypoints
[
keyPointIdx
-
1
].
response
=
-
1
;
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
<
keypoints
[
keyPointIdx
].
response
)
{
keypoints
[
keyPointIdx
-
1
].
response
=
-
1
;
}
break
;
}
}
break
;
}
}
else
count
=
0
;
}
}
else
count
=
0
;
}
}
}
}
// Remove unused Keypoints
}
size_t
maxKeypointSize
=
keypoints
.
size
();
for
(
size_t
keyPointIdx
=
maxKeypointSize
;
keyPointIdx
>
0
;)
{
// Remove unused Keypoints
keyPointIdx
--
;
size_t
maxKeypointSize
=
keypoints
.
size
();
if
(
keypoints
[
keyPointIdx
].
response
<=
0
)
{
for
(
size_t
keyPointIdx
=
maxKeypointSize
;
keyPointIdx
>
0
;)
{
keypoints
.
erase
(
keypoints
.
begin
()
+
keyPointIdx
);
keyPointIdx
--
;
}
else
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
>
keypoints
[
keyPointIdx
].
response
)
{
if
(
keypoints
[
keyPointIdx
].
response
<=
0
)
{
// Non Maxima Suppression II
keypoints
.
erase
(
keypoints
.
begin
()
+
keyPointIdx
);
keypoints
.
erase
(
keypoints
.
begin
()
+
keyPointIdx
);
}
else
if
(
nonmaxSuppression
&&
keyPointIdx
>
0
&&
keypoints
[
keyPointIdx
-
1
].
response
>
keypoints
[
keyPointIdx
].
response
)
{
}
// Non Maxima Suppression II
keypoints
.
erase
(
keypoints
.
begin
()
+
keyPointIdx
);
}
}
}
}
}
}
namespace
cv
{
namespace
xfeatures2d
{
void
FASTForPointSet
(
InputArray
_img
,
std
::
vector
<
KeyPoint
>&
keypoints
,
int
threshold
,
bool
nonmax_suppression
,
int
type
)
void
FASTForPointSet
(
InputArray
_img
,
std
::
vector
<
KeyPoint
>&
keypoints
,
int
threshold
,
bool
nonmax_suppression
,
int
type
)
{
{
...
@@ -509,5 +477,6 @@ namespace cv {
...
@@ -509,5 +477,6 @@ namespace cv {
break
;
break
;
}
}
}
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment