#include <iostream>
#include <opencv2/opencv.hpp>
/*
#include "precomp.hpp"
#include "fast.hpp"
#include "fast_score.hpp"
#include "opencl_kernels_features2d.hpp"
#include "hal_replacement.hpp"
#include "opencv2/core/hal/intrin.hpp"
//#include "opencv2/core/openvx/ovx_defs.hpp"
*/
/*
opencv 所实现的FAST算法与自实现的算法检测结果不同, opencv算法的特征点均匀性更好
自己重写的代码均匀性不好,集中在几个地方,需要好好看看
是不是与opencl, openvx等相关
*/
using namespace cv;
using namespace std;
Mat getHomographyMatrixWithOrb(Mat image1, Mat image2);
vector<KeyPoint> detectFastKeyPoints(Mat image);
template<int patternSize>
void detectFASTKeyPoints(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression);
template<int patternSize>
void detectFASTKeyPoints(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression, int windowHeight, int windowWidth);
template<int patternSize>
int cornerScore(const uchar* ptr, const int pixel[], int threshold);
void makeOffsets(int pixel[25], int rowStride, int patternSize);
void main() {
Mat image1 = imread("C:\\opencv_cpp\\imagecalibration\\imagestobedealed\\waterfalls1\\1.jpg");
Mat image2 = imread("C:\\opencv_cpp\\imagecalibration\\imagestobedealed\\waterfalls1\\2.jpg");
//if()
//getHomographyMatrixWithOrb(image1, image2);
double t_start_1 = getTickCount();
vector<KeyPoint> keyPoints1;
Ptr<FastFeatureDetector> fd = FastFeatureDetector::create(20, true, FastFeatureDetector::TYPE_9_16);
fd->detect(image1, keyPoints1, Mat());
cout << "keyPoints1.size: " << keyPoints1.size() << endl;
double t_stop_1 = getTickCount();
cout << "time consumed in opencv FAST: " << (t_stop_1 - t_start_1) / getTickFrequency() << "秒" << endl;
Mat image1WithKeyPoint1;
drawKeypoints(image1, keyPoints1, image1WithKeyPoint1, Scalar(0, 0, 255));
imwrite("image1WithKeyPoint1.jpg", image1WithKeyPoint1);
double t_start_2 = getTickCount();
vector<KeyPoint> keyPoints2;
keyPoints2 = detectFastKeyPoints(image1);
cout << "keyPoints2.size: " << keyPoints2.size() << endl;
double t_stop_2 = getTickCount();
cout << "time consumed in self-defined FAST: " << (t_stop_2 - t_start_2) / getTickFrequency() << "秒" << endl;
Mat image1WithKeyPoint2;
drawKeypoints(image1, keyPoints2, image1WithKeyPoint2, Scalar(0, 0, 255));
imwrite("image1WithKeyPoint2.jpg", image1WithKeyPoint2);
char c;
cin >> c;
}
Mat getHomographyMatrixWithOrb(Mat image1, Mat image2) {
Ptr<ORB> orb = ORB::create();
vector<KeyPoint> keyPoints1, keyPoints2;
Mat descriptor1, descriptor2;
orb->detectAndCompute(image1, Mat(), keyPoints1, descriptor1);
orb->detectAndCompute(image2, Mat(), keyPoints2, descriptor2);
Mat image1PlusKeyPoints, image2PlusKeyPoints;
drawKeypoints(image1, keyPoints1, image1PlusKeyPoints, Scalar(255, 0, 0));
drawKeypoints(image2, keyPoints2, image2PlusKeyPoints, Scalar(255, 0, 0));
imwrite("image1PlusKeyPoints.jpg", image1PlusKeyPoints);
imwrite("image2PlusKeyPoints.jpg", image2PlusKeyPoints);
//求取BF匹配
BFMatcher bfMatcher;
std::vector< DMatch > bfMatches;
bfMatcher.match(descriptor2, descriptor1, bfMatches);
Mat image2MatchToImage1;
drawMatches(image2, keyPoints2, image1, keyPoints1, bfMatches, image2MatchToImage1);
imwrite("image2MatchToImage1.jpg", image2MatchToImage1);
vector< DMatch > ransacMatches;
vector<Point2f> points1(bfMatches.size());
vector<Point2f> points2(bfMatches.size());
for (size_t i = 0; i < bfMatches.size(); i++)
{
points1[i] = keyPoints1[bfMatches[i].trainIdx].pt;
points2[i] = keyPoints2[bfMatches[i].queryIdx].pt;
}
//用RANSAC求取单应矩阵的方式去掉不可靠的BF匹配
vector<uchar> flag(bfMatches.size(), 0);
Mat H = findHomography(points2, points1, CV_RANSAC, 3.0, flag);
for (int i = 0; i < bfMatches.size(); i++) {
if (flag.at(i) != 0) {
DMatch dMatch(bfMatches.at(i).queryIdx, bfMatches.at(i).trainIdx, bfMatches.at(i).distance);
ransacMatches.push_back(dMatch);
}
}
Mat goodImage2MatchToImage1;
drawMatches(image2, keyPoints2, image1, keyPoints1, ransacMatches, goodImage2MatchToImage1);
imwrite("goodImage2MatchToImage1.jpg", goodImage2MatchToImage1);
cout << "ransacMatches.size: " << ransacMatches.size() << endl;
char a;
cin >> a;
return H;
}
//对于1920*1080像素的照片,在这里的处理是将其划分为60*60的区块
//及局部最大值抑制区的大小为32*18
vector<KeyPoint> detectFastKeyPoints(Mat image) {
vector<KeyPoint> keyPoints;
//detectFASTKeyPoints<16>(image, keyPoints, 20, true);
detectFASTKeyPoints<16>(image, keyPoints, 20, true, 32, 18);
return keyPoints;
}
template<int patternSize>
void detectFASTKeyPoints(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
{
Mat img = _img.getMat();
const int K = patternSize / 2, N = patternSize + K + 1;
int i, j, k, pixel[25];
makeOffsets(pixel, (int)img.step, patternSize);
#if CV_SIMD128
const int quarterPatternSize = patternSize / 4;
v_uint8x16 delta = v_setall_u8(0x80), t = v_setall_u8((char)threshold), K16 = v_setall_u8((char)K);
bool hasSimd = hasSIMD128();
#if CV_TRY_AVX2
Ptr<opt_AVX2::FAST_t_patternSize16_AVX2> fast_t_impl_avx2;
if (CV_CPU_HAS_SUPPORT_AVX2)
fast_t_impl_avx2 = opt_AVX2::FAST_t_patternSize16_AVX2::getImpl(img.cols, threshold, nonmax_suppression, pixel);
#endif
#endif
keypoints.clear();
threshold = std::min(std::max(threshold, 0), 255);
uchar threshold_tab[512];
for (i = -255; i <= 255; i++)
threshold_tab[i + 255] = (uchar)(i < -threshold ? 1 : i > threshold ? 2 : 0);
AutoBuffer<uchar> _buf((img.cols + 16) * 3 * (sizeof(int) + sizeof(uchar)) + 128);
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);
for (i = 3; i < img.rows - 2; i++)
{
const uchar* ptr = img.ptr<uchar>(i) + 3;
uchar* curr = buf[(i - 3) % 3];
int* cornerpos = cpbuf[(i - 3) % 3];
memset(curr, 0, img.cols);
int ncorners = 0;
if (i < img.rows - 3)
{
j = 3;
#if CV_SIMD128
if (hasSimd)
{
if (patternSize == 16)
{
#if CV_TRY_AVX2
if (fast_t_impl_avx2)
fast_t_impl_avx2->process(j, ptr, curr, cornerpos, ncorners);
#endif
//vz if (j <= (img.cols - 27)) //it doesn't make sense using vectors for less than 8 elements
{
for (; j < img.cols - 16 - 3; j += 16, ptr += 16)
{
v_uint8x16 v = v_load(ptr);
v_int8x16 v0 = v_reinterpret_as_s8((v + t) ^ delta);
v_int8x16 v1 = v_reinterpret_as_s8((v - t) ^ delta);
v_int8x16 x0 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[0]), delta));
v_int8x16 x1 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[quarterPatternSize]), delta));
v_int8x16 x2 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[2 * quarterPatternSize]), delta));
v_int8x16 x3 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[3 * quarterPatternSize]), delta));
v_int8x16 m0, m1;
m0 = (v0 < x0) & (v0 < x1);
m1 = (x0 < v1) & (x1 < v1);
m0 = m0 | ((v0 < x1) & (v0 < x2));
m1 = m1 | ((x1 < v1) & (x2 < v1));
m0 = m0 | ((v0 < x2) & (v0 < x3));
m1 = m1 | ((x2 < v1) & (x3 < v1));
m0 = m0 | ((v0 < x3) & (v0 < x0));
m1 = m1 | ((x3 < v1) & (x0 < v1));
m0 = m0 | m1;
int mask = v_signmask(m0);
if (mask == 0)
continue;
if ((mask & 255) == 0)
{
j -= 8;
ptr -= 8;
continue;
}
v_int8x16 c0 = v_setzero_s8();
v_int8x16 c1 = v_setzero_s8();
v_uint8x16 max0 = v_setzero_u8();
v_uint8x16 max1 = v_setzero_u8();
for (k = 0; k < N; k++)
{
v_int8x16 x = v_reinterpret_as_s8(v_load((ptr + pixel[k])) ^ delta);
m0 = v0 < x;
m1 = x < v1;
c0 = v_sub_wrap(c0, m0) & m0;
c1 = v_sub_wrap(c1, m1) & m1;
max0 = v_max(max0, v_reinterpret_as_u8(c0));
max1 = v_max(max1, v_reinterpret_as_u8(c1));
}
max0 = v_max(max0, max1);
int m = v_signmask(K16 < max0);
for (k = 0; m > 0 && k < 16; k++, m >>= 1)
{
if (m & 1)
{
cornerpos[ncorners++] = j + k;
if (nonmax_suppression)
curr[j + k] = (uchar)cornerScore<patternSize>(ptr + k, pixel, threshold);
}
}
}
}
}
}
#endif
for (; j < img.cols - 3; j++, ptr++)
{
int v = ptr[0];
const uchar* tab = &threshold_tab[0] - v + 255;
int d = tab[ptr[pixel[0]]] | tab[ptr[pixel[8]]];
if (d == 0)
continue;
d &= tab[ptr[pixel[2]]] | tab[ptr[pixel[10]]];
d &= tab[ptr[pixel[4]]] | tab[ptr[pixel[12]]];
d &= tab[ptr[pixel[6]]] | tab[ptr[pixel[14]]];
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]]];
if (d & 1)
{
int vt = v - threshold, count = 0;
for (k = 0; k < N; k++)
{
int x = ptr[pixel[k]];
if (x < vt)
{
if (++count > K)
{
cornerpos[ncorners++] = j;
if (nonmax_suppression)
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
break;
}
}
else
count = 0;
}
}
if (d & 2)
{
int vt = v + threshold, count = 0;
for (k = 0; k < N; k++)
{
int x = ptr[pixel[k]];
if (x > vt)
{
if (++count > K)
{
cornerpos[ncorners++] = j;
if (nonmax_suppression)
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
break;
}
}
else
count = 0;
}
}
}
}
cornerpos[-1] = ncorners;
if (i == 3)
continue;
const uchar* prev = buf[(i - 4 + 3) % 3];
const uchar* pprev = buf[(i - 5 + 3) % 3];
cornerpos = cpbuf[(i - 4 + 3) % 3];
ncorners = cornerpos[-1];
for (k = 0; k < ncorners; k++)
{
j = cornerpos[k];
int score = prev[j];
if (!nonmax_suppression ||
(score > prev[j + 1] && score > prev[j - 1] &&
score > pprev[j - 1] && score > pprev[j] && score > pprev[j + 1] &&
score > curr[j - 1] && score > curr[j] && score > curr[j + 1]))
{
keypoints.push_back(KeyPoint((float)j, (float)(i - 1), 7.f, -1, (float)score));
}
}
}
}
//自己加上窗口,按照上面的假设将图片切割为60*60大小,那么需要窗口设置为32*18
template<int patternSize>
void detectFASTKeyPoints(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression, int windowHeight, int windowWidth)
{
Mat img = _img.getMat();
const int K = patternSize / 2, N = patternSize + K + 1;
int i, j, k, pixel[25];
makeOffsets(pixel, (int)img.step, patternSize);
#if CV_SIMD128
const int quarterPatternSize = patternSize / 4;
v_uint8x16 delta = v_setall_u8(0x80), t = v_setall_u8((char)threshold), K16 = v_setall_u8((char)K);
bool hasSimd = hasSIMD128();
#if CV_TRY_AVX2
Ptr<opt_AVX2::FAST_t_patternSize16_AVX2> fast_t_impl_avx2;
if (CV_CPU_HAS_SUPPORT_AVX2)
fast_t_impl_avx2 = opt_AVX2::FAST_t_patternSize16_AVX2::getImpl(img.cols, threshold, nonmax_suppression, pixel);
#endif
#endif
keypoints.clear();
threshold = std::min(std::max(threshold, 0), 255);
uchar threshold_tab[512];
for (i = -255; i <= 255; i++)
threshold_tab[i + 255] = (uchar)(i < -threshold ? 1 : i > threshold ? 2 : 0);
AutoBuffer<uchar> _buf((img.cols + 16) * windowHeight * (sizeof(int) + sizeof(uchar)) + 128);
//change it
uchar** buf = new uchar*[windowHeight];
//uchar* buf[windowHeight];
for (int i = 0; i < windowHeight; i++) {
buf[i] = _buf + i * img.cols;
}
//buf[0] = _buf; buf[1] = buf[0] + img.cols; buf[2] = buf[1] + img.cols;
//int* cpbuf[windowHeight];
int** cpbuf = new int*[windowHeight];
cpbuf[0] = (int*)alignPtr(buf[2] + img.cols, sizeof(int)) + 1;
for (int i = 0; i < windowHeight; i++) {
cpbuf[i] = cpbuf[0] + i * (img.cols + 1);
}
//change it
//cpbuf[1] = cpbuf[0] + img.cols + 1;
//cpbuf[2] = cpbuf[1] + img.cols + 1;
//memset(buf[0], 0, img.cols * 3);
memset(buf[0], 0, img.cols * windowHeight);
for (i = 3; i < img.rows - 2; i++)
{
const uchar* ptr = img.ptr<uchar>(i) + 3;
uchar* curr = buf[(i - 3) % windowHeight];
int* cornerpos = cpbuf[(i - 3) % windowHeight];
memset(curr, 0, img.cols);
int ncorners = 0;
if (i < img.rows - 3)
{
j = 3;
#if CV_SIMD128
if (hasSimd)
{
if (patternSize == 16)
{
#if CV_TRY_AVX2
if (fast_t_impl_avx2)
fast_t_impl_avx2->process(j, ptr, curr, cornerpos, ncorners);
#endif
//vz if (j <= (img.cols - 27)) //it doesn't make sense using vectors for less than 8 elements
{
for (; j < img.cols - 16 - 3; j += 16, ptr += 16)
{
v_uint8x16 v = v_load(ptr);
v_int8x16 v0 = v_reinterpret_as_s8((v + t) ^ delta);
v_int8x16 v1 = v_reinterpret_as_s8((v - t) ^ delta);
v_int8x16 x0 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[0]), delta));
v_int8x16 x1 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[quarterPatternSize]), delta));
v_int8x16 x2 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[2 * quarterPatternSize]), delta));
v_int8x16 x3 = v_reinterpret_as_s8(v_sub_wrap(v_load(ptr + pixel[3 * quarterPatternSize]), delta));
v_int8x16 m0, m1;
m0 = (v0 < x0) & (v0 < x1);
m1 = (x0 < v1) & (x1 < v1);
m0 = m0 | ((v0 < x1) & (v0 < x2));
m1 = m1 | ((x1 < v1) & (x2 < v1));
m0 = m0 | ((v0 < x2) & (v0 < x3));
m1 = m1 | ((x2 < v1) & (x3 < v1));
m0 = m0 | ((v0 < x3) & (v0 < x0));
m1 = m1 | ((x3 < v1) & (x0 < v1));
m0 = m0 | m1;
int mask = v_signmask(m0);
if (mask == 0)
continue;
if ((mask & 255) == 0)
{
j -= 8;
ptr -= 8;
continue;
}
v_int8x16 c0 = v_setzero_s8();
v_int8x16 c1 = v_setzero_s8();
v_uint8x16 max0 = v_setzero_u8();
v_uint8x16 max1 = v_setzero_u8();
for (k = 0; k < N; k++)
{
v_int8x16 x = v_reinterpret_as_s8(v_load((ptr + pixel[k])) ^ delta);
m0 = v0 < x;
m1 = x < v1;
c0 = v_sub_wrap(c0, m0) & m0;
c1 = v_sub_wrap(c1, m1) & m1;
max0 = v_max(max0, v_reinterpret_as_u8(c0));
max1 = v_max(max1, v_reinterpret_as_u8(c1));
}
max0 = v_max(max0, max1);
int m = v_signmask(K16 < max0);
for (k = 0; m > 0 && k < 16; k++, m >>= 1)
{
if (m & 1)
{
cornerpos[ncorners++] = j + k;
if (nonmax_suppression)
curr[j + k] = (uchar)cornerScore<patternSize>(ptr + k, pixel, threshold);
}
}
}
}
}
}
#endif
for (; j < img.cols - 3; j++, ptr++)
{
int v = ptr[0];
const uchar* tab = &threshold_tab[0] - v + 255;
int d = tab[ptr[pixel[0]]] | tab[ptr[pixel[8]]];
if (d == 0)
continue;
d &= tab[ptr[pixel[2]]] | tab[ptr[pixel[10]]];
d &= tab[ptr[pixel[4]]] | tab[ptr[pixel[12]]];
d &= tab[ptr[pixel[6]]] | tab[ptr[pixel[14]]];
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]]];
if (d & 1)
{
int vt = v - threshold, count = 0;
for (k = 0; k < N; k++)
{
int x = ptr[pixel[k]];
if (x < vt)
{
if (++count > K)
{
cornerpos[ncorners++] = j;
if (nonmax_suppression)
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
break;
}
}
else
count = 0;
}
}
if (d & 2)
{
int vt = v + threshold, count = 0;
for (k = 0; k < N; k++)
{
int x = ptr[pixel[k]];
if (x > vt)
{
if (++count > K)
{
cornerpos[ncorners++] = j;
if (nonmax_suppression)
curr[j] = (uchar)cornerScore<patternSize>(ptr, pixel, threshold);
break;
}
}
else
count = 0;
}
}
}
}
cornerpos[-1] = ncorners;
//change it
//if (i == 3)
// continue;
if (i < (3 + (windowHeight / 2))) {
continue;
}
uchar** prev = new uchar*[windowHeight - 1];
for (int m = 0; m < windowHeight - 1; m++) {
prev[m] = buf[(i - (3 + windowHeight / 2) - m + windowHeight) % windowHeight];
}
cornerpos = cpbuf[(i - (3 + windowHeight / 2) + windowHeight) % windowHeight];
//const uchar* prev = buf[(i - 4 + 3) % 3];
//const uchar* pprev = buf[(i - 5 + 3) % 3];
//cornerpos = cpbuf[(i - 4 + 3) % 3];
ncorners = cornerpos[-1];
for (k = 0; k < ncorners; k++)
{
j = cornerpos[k];
//change it
//int score = prev[j];
int score = prev[windowHeight/2 - 1][j];
if (!nonmax_suppression || whetherRecieve(prev, curr, score, j, windowHeight, windowWidth))
{
keypoints.push_back(KeyPoint((float)j, (float)(i - 1), 7.f, -1, (float)score));
}
}
delete[] prev;
}
delete[] buf;
delete[] cpbuf;
}
bool whetherRecieve(uchar* prev[], uchar* curr, int score, int position, int windowHeight, int windowWidth){
for (int i = 0; i < windowHeight - 1; i++) {
for (int j = -windowWidth / 2; j < (windowWidth + 1) / 2; j++) {
int position_2 = (position + j) > 0 ? (position + j) : 0;
if (score <= prev[i][position_2]) {
return false;
}
}
}
for (int j = -windowWidth / 2; j < (windowWidth + 1) / 2; j++) {
int position_2 = (position + j) > 0 ? (position + j) : 0;
if (score <= curr[position_2]) {
return false;
}
}
return true;
}
void makeOffsets(int pixel[25], int rowStride, int patternSize)
{
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 }
};
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 }
};
static const int offsets8[][2] =
{
{ 0, 1 },{ 1, 1 },{ 1, 0 },{ 1, -1 },
{ 0, -1 },{ -1, -1 },{ -1, 0 },{ -1, 1 }
};
const int(*offsets)[2] = patternSize == 16 ? offsets16 :
patternSize == 12 ? offsets12 :
patternSize == 8 ? offsets8 : 0;
CV_Assert(pixel && offsets);
int k = 0;
for (; k < patternSize; k++)
pixel[k] = offsets[k][0] + offsets[k][1] * rowStride;
for (; k < 25; k++)
pixel[k] = pixel[k - patternSize];
}
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_SIMD128
if (hasSIMD128())
{
v_int16x8 q0 = v_setall_s16(-1000), q1 = v_setall_s16(1000);
for (k = 0; k < 16; k += 8)
{
v_int16x8 v0 = v_load(d + k + 1);
v_int16x8 v1 = v_load(d + k + 2);
v_int16x8 a = v_min(v0, v1);
v_int16x8 b = v_max(v0, v1);
v0 = v_load(d + k + 3);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 4);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 5);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 6);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 7);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 8);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k);
q0 = v_max(q0, v_min(a, v0));
q1 = v_min(q1, v_max(b, v0));
v0 = v_load(d + k + 9);
q0 = v_max(q0, v_min(a, v0));
q1 = v_min(q1, v_max(b, v0));
}
q0 = v_max(q0, v_setzero_s16() - q1);
threshold = v_reduce_max(q0) - 1;
}
else
#endif
{
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;
}
#if VERIFY_CORNERS
testCorner(ptr, pixel, K, N, threshold);
#endif
return threshold;
}
template<>
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_SIMD128
for (k = 0; k < 4; k++)
d[N + k] = d[k];
#endif
#if CV_SIMD128
if (hasSIMD128())
{
v_int16x8 q0 = v_setall_s16(-1000), q1 = v_setall_s16(1000);
for (k = 0; k < 16; k += 8)
{
v_int16x8 v0 = v_load(d + k + 1);
v_int16x8 v1 = v_load(d + k + 2);
v_int16x8 a = v_min(v0, v1);
v_int16x8 b = v_max(v0, v1);
v0 = v_load(d + k + 3);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 4);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 5);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k + 6);
a = v_min(a, v0);
b = v_max(b, v0);
v0 = v_load(d + k);
q0 = v_max(q0, v_min(a, v0));
q1 = v_min(q1, v_max(b, v0));
v0 = v_load(d + k + 7);
q0 = v_max(q0, v_min(a, v0));
q1 = v_min(q1, v_max(b, v0));
}
q0 = v_max(q0, v_setzero_s16() - q1);
threshold = v_reduce_max(q0) - 1;
}
else
#endif
{
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;
for (k = 0; k < 12; 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]);
if (b >= b0)
continue;
b = std::max(b, (int)d[k + 5]);
b = std::max(b, (int)d[k + 6]);
b0 = std::min(b0, std::max(b, (int)d[k]));
b0 = std::min(b0, std::max(b, (int)d[k + 7]));
}
threshold = -b0 - 1;
}
#if VERIFY_CORNERS
testCorner(ptr, pixel, K, N, threshold);
#endif
return threshold;
}
modifiedOrbRegistration
最新推荐文章于 2022-07-22 11:36:49 发布