intensity_descriptor.cpp
Go to the documentation of this file.
00001 #include "intensity_descriptor.hpp"
00002 
00003 #include <assert.h>
00004 #include <stdio.h>
00005 #include <string.h>
00006 
00007 #include <iostream>
00008 #include <algorithm>
00009 #include <numeric>
00010 
00011 #ifdef FOVIS_USE_SSE
00012 #include <emmintrin.h>
00013 #endif
00014 
00015 #ifndef ALIGNMENT
00016 #define ALIGNMENT 16
00017 #endif
00018 
00019 #include "keypoint.hpp"
00020 #include "internal_utils.hpp"
00021 
00022 namespace fovis
00023 {
00024 
00025 void
00026 IntensityDescriptorExtractor::initialize() {
00027   _descriptor_len = _feature_window_size * _feature_window_size;
00028   // omit a pixel from the descriptor where doing so results in a descriptor
00029   // length that's a multiple of 16 (e.g., feature window sizes 7, 9, etc.)
00030   // This makes for faster descriptor comparisons.  If using other feature
00031   // window sizes (e.g., 8, 10) then there's no significant advantage for
00032   // omitting that pixel.
00033   if((_descriptor_len - 1) % 16 == 0) {
00034     _descriptor_len -= 1;
00035   }
00036 
00037   // descriptor properties
00038   _descriptor_stride = round_up_to_multiple(_descriptor_len, ALIGNMENT);
00039   _brightess_offset_num_sse_ops = _descriptor_stride / 16;
00040   _num_descriptor_pad_bytes = _descriptor_stride - _descriptor_len;
00041 
00042   // populate the descriptor offset vector.  This vector stores the index
00043   // offsets of descriptor pixels for a descriptor centered around a given
00044   // pixel.
00045   _descriptor_index_offsets = new int[_descriptor_len];
00046   int i=0;
00047   int dr = (_feature_window_size - 1) / 2;
00048   for(int y_offset = -dr; y_offset<=dr; y_offset++) {
00049     for(int x_offset = -dr; x_offset<=dr && i<_descriptor_len; x_offset++) {
00050       _descriptor_index_offsets[i] = y_offset * _raw_gray_stride + x_offset;
00051       i++;
00052     }
00053   }
00054   assert(i == _descriptor_len);
00055 
00056   if(0 != posix_memalign((void**)&_descriptor_brightness_offset, ALIGNMENT, 16))
00057       fprintf(stderr, "error allocating descriptor brightness offset\n");
00058 }
00059 
00060 void
00061 IntensityDescriptorExtractor::populateDescriptorInterp(uint8_t *raw_gray,
00062                                                        float x, float y,
00063                                                        uint8_t* descriptor) const
00064 {
00065   int u = static_cast<int>(x);
00066   int v = static_cast<int>(y);
00067   float wright  = (x - u);
00068   float wbottom = (y - v);
00069   float wa = (1. - wright) * (1. - wbottom);
00070   float wb = wright        * (1. - wbottom);
00071   float wc = (1. - wright) * wbottom;
00072   float wd = wright        * wbottom;
00073   int initial_index = v * _raw_gray_stride + u;
00074   for(int i=0; i<_descriptor_len; i++) {
00075     int k = initial_index + _descriptor_index_offsets[i];
00076 #ifndef NDEBUG
00077 //    assert(k >= 0 && k < _width*_height);
00078 #endif
00079     descriptor[i] = (uint8_t)(wa * raw_gray[k] +
00080         wb * raw_gray[k + 1] +
00081         wc * raw_gray[k + _raw_gray_stride] +
00082         wd * raw_gray[k + _raw_gray_stride + 1]);
00083   }
00084   normalizeDescriptor(descriptor);
00085 
00086   // zero out some pad bytes of the descriptor so that SIMD
00087   // operations can be simpler
00088   memset(descriptor + _descriptor_len, 0, _num_descriptor_pad_bytes);
00089 }
00090 
00091 void
00092 IntensityDescriptorExtractor::populateDescriptorAligned(uint8_t *raw_gray,
00093                                                         int x, int y,
00094                                                         uint8_t* descriptor) const
00095 {
00096   // require that the descriptor be 16-byte aligned
00097   assert(FOVIS_IS_ALIGNED16(descriptor));
00098 
00099   int start = y * _raw_gray_stride + x;
00100   for (int i=0; i<_descriptor_len; i++) {
00101     descriptor[i] = raw_gray[start + _descriptor_index_offsets[i]];
00102   }
00103   normalizeDescriptor(descriptor);
00104 
00105   // zero out some pad bytes of the descriptor so that SIMD
00106   // operations can be simpler
00107   memset(descriptor + _descriptor_len, 0, _num_descriptor_pad_bytes);
00108 }
00109 
00110 void
00111 IntensityDescriptorExtractor::normalizeDescriptor(uint8_t* desc) const
00112 {
00113   assert(FOVIS_IS_ALIGNED16(_descriptor_brightness_offset));
00114 
00115   // get mean of patch
00116   int desc_mean = std::accumulate(desc, desc + _descriptor_len, 0)/_descriptor_len;
00117   // subtract mean, adding offset so 0 -> 128
00118 #ifdef FOVIS_USE_SSE
00119   if(desc_mean < 128) {
00120     std::fill(_descriptor_brightness_offset, _descriptor_brightness_offset+16, 128-desc_mean);
00121     for(int op=0; op<_brightess_offset_num_sse_ops; op++) {
00122       ((__m128i*)desc)[op] = _mm_adds_epu8(((__m128i*)desc)[op],
00123         *(__m128i*)_descriptor_brightness_offset);
00124     }
00125   } else if (desc_mean > 128){
00126     std::fill(_descriptor_brightness_offset, _descriptor_brightness_offset+16, desc_mean-128);
00127     for(int op=0; op<_brightess_offset_num_sse_ops; op++) {
00128       ((__m128i*)desc)[op] = _mm_subs_epu8(((__m128i*)desc)[op],
00129         *(__m128i*)_descriptor_brightness_offset);
00130     }
00131   }
00132 #else
00133   if(desc_mean < 128) {
00134     for(int i=0; i<_descriptor_len; i++)
00135       desc[i] += std::min(255, desc_mean);
00136   } else if (desc_mean > 128) {
00137     for(int i=0; i<_descriptor_len; i++)
00138       desc[i] += std::max(0, desc_mean);
00139   }
00140 #endif
00141 }
00142 
00143 void
00144 IntensityDescriptorExtractor::populateDescriptorsInterp(uint8_t* image,
00145                                                         const KeypointData* keypoints,
00146                                                         int num_keypoints,
00147                                                         uint8_t* descriptors) const
00148 {
00149   for (int n=0; n<num_keypoints; ++n) {
00150     const KeypointData& kp_data(keypoints[n]);
00151     uint8_t* descriptor = descriptors + n*_descriptor_stride;
00152     populateDescriptorInterp(image, kp_data.kp.u, kp_data.kp.v, descriptor);
00153     normalizeDescriptor(descriptor);
00154   }
00155 }
00156 
00157 void
00158 IntensityDescriptorExtractor::populateDescriptorsAligned(uint8_t* image,
00159                                                          const KeypointData* keypoints,
00160                                                          int num_keypoints,
00161                                                          uint8_t* descriptors) const
00162 {
00163   for (int n=0; n<num_keypoints; ++n) {
00164     const KeypointData& kp_data(keypoints[n]);
00165     uint8_t* descriptor = descriptors + n*_descriptor_stride;
00166     populateDescriptorAligned(image,
00167                               static_cast<int>(kp_data.kp.u),
00168                               static_cast<int>(kp_data.kp.v),
00169                               descriptor);
00170     normalizeDescriptor(descriptor);
00171   }
00172 }
00173 
00174 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12