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
00029
00030
00031
00032
00033 if((_descriptor_len - 1) % 16 == 0) {
00034 _descriptor_len -= 1;
00035 }
00036
00037
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
00043
00044
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
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
00087
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
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
00106
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
00116 int desc_mean = std::accumulate(desc, desc + _descriptor_len, 0)/_descriptor_len;
00117
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 }