modifiedOrbRegistration

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值