lucid.cpp 5.59 KB
Newer Older
Str3iber's avatar
Str3iber committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// This implementation of, and any deviation from, the original algorithm as
// proposed by Ziegler et al. is not endorsed by Ziegler et al. nor does it
// claim to represent their definition of locally uniform comparison image
// descriptor. The original LUCID algorithm as proposed by Ziegler et al. remains
// the property of its respective authors. This implementation is an adaptation of
// said algorithm and contributed to OpenCV by Str3iber.

// References:
// Ziegler, Andrew, Eric Christiansen, David Kriegman, and Serge J. Belongie.
// "Locally uniform comparison image descriptor." In Advances in Neural Information
// Processing Systems, pp. 1-9. 2012.

/*
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
                       (3-clause BSD License)

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

  * Redistributions 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.

  * Neither the names of the copyright holders nor the names of the contributors
    may 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 copyright holders 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.
*/

#include "precomp.hpp"

namespace cv {
    namespace xfeatures2d {
Str3iber's avatar
Str3iber committed
53 54 55
        /*!
         LUCID implementation
         */
Str3iber's avatar
Str3iber committed
56 57
        class LUCIDImpl : public LUCID {
            public:
Str3iber's avatar
Str3iber committed
58 59 60 61
                /** Constructor
                 * @param lucid_kernel kernel for descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth
                 * @param blur_kernel kernel for blurring image prior to descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth
                 */
Str3iber's avatar
Str3iber committed
62 63
                LUCIDImpl(const int lucid_kernel = 1, const int blur_kernel = 2);

Str3iber's avatar
Str3iber committed
64
                /** returns the descriptor length */
Str3iber's avatar
Str3iber committed
65
                virtual int descriptorSize() const;
Str3iber's avatar
Str3iber committed
66 67

                /** returns the descriptor type */
Str3iber's avatar
Str3iber committed
68
                virtual int descriptorType() const;
Str3iber's avatar
Str3iber committed
69 70

                /** returns the default norm type */
Str3iber's avatar
Str3iber committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84
                virtual int defaultNorm() const;

                virtual void compute(InputArray _src, std::vector<KeyPoint> &keypoints, OutputArray _desc);

            protected:
                int l_kernel, b_kernel;
        };

        Ptr<LUCID> LUCID::create(const int lucid_kernel, const int blur_kernel) {
            return makePtr<LUCIDImpl>(lucid_kernel, blur_kernel);
        }

        LUCIDImpl::LUCIDImpl(const int lucid_kernel, const int blur_kernel) {
            l_kernel = lucid_kernel;
Str3iber's avatar
Str3iber committed
85
            b_kernel = blur_kernel*2+1;
Str3iber's avatar
Str3iber committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        }

        int LUCIDImpl::descriptorSize() const {
            return (l_kernel*2+1)*(l_kernel*2+1)*3;
        }

        int LUCIDImpl::descriptorType() const {
            return CV_8UC1;
        }

        int LUCIDImpl::defaultNorm() const {
            return NORM_HAMMING;
        }

        // gliese581h suggested filling a cv::Mat with descriptors to enable BFmatcher compatibility
        // speed-ups and enhancements by gliese581h
        void LUCIDImpl::compute(InputArray _src, std::vector<KeyPoint> &keypoints, OutputArray _desc) {
            if (_src.getMat().empty())
                return;

            Mat_<Vec3b> src;

Str3iber's avatar
Str3iber committed
108
            blur(_src.getMat(), src, cv::Size(b_kernel, b_kernel));
Str3iber's avatar
Str3iber committed
109 110 111

            int x, y, j, d, p, m = (l_kernel*2+1)*(l_kernel*2+1)*3, width = src.cols, height = src.rows, r, c;

Str3iber's avatar
Str3iber committed
112
            Mat_<uchar> desc(static_cast<int>(keypoints.size()), m);
Str3iber's avatar
Str3iber committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

            for (std::size_t i = 0; i < keypoints.size(); ++i) {
                x = static_cast<int>(keypoints[i].pt.x)-l_kernel, y = static_cast<int>(keypoints[i].pt.y)-l_kernel, d = x+2*l_kernel, p = y+2*l_kernel, j = x, r = static_cast<int>(i), c = 0;

                while (x <= d) {
                    Vec3b &pix = src((y < 0 ? height+y : y >= height ? y-height : y), (x < 0 ? width+x : x >= width ? x-width : x));

                    desc(r, c++) = pix[0];
                    desc(r, c++) = pix[1];
                    desc(r, c++) = pix[2];

                    ++x;
                    if (x > d) {
                        if (y < p) {
                            ++y;
                            x = j;
                        }
                        else
                            break;
                    }
                }
            }

            if (_desc.needed())
                sort(desc, _desc, SORT_EVERY_ROW | SORT_ASCENDING);
        }
    }
Str3iber's avatar
Str3iber committed
140
} // END NAMESPACE CV