00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, AASS Research Center, Orebro University. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of AASS Research Center nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 */ 00035 #ifndef NDTFRAMETOOLS_HH 00036 #define NDTFRAMETOOLS_HH 00037 00038 //#include <ndt_feature_reg/NDTFrame.hh> 00039 #include <pcl/point_types.h> 00040 00041 namespace ndt_feature_reg 00042 { 00043 template<class T> std::string toString (const T& x) 00044 { 00045 std::ostringstream o; 00046 00047 if (!(o << x)) 00048 throw std::runtime_error ("::toString()"); 00049 00050 return o.str (); 00051 } 00052 00053 inline void scaleKeyPointSize(std::vector<cv::KeyPoint> &keypoints, const float &factor) 00054 { 00055 for( std::vector<cv::KeyPoint>::iterator i = keypoints.begin(), ie = keypoints.end(); i != ie; ++i ) 00056 { 00057 i->size *= factor; 00058 } 00059 } 00060 00061 inline void scaleKeyPointPosition(std::vector<cv::KeyPoint> &keypoints, const float &factor) 00062 { 00063 for( std::vector<cv::KeyPoint>::iterator i = keypoints.begin(), ie = keypoints.end(); i != ie; ++i ) 00064 { 00065 i->pt.x *= factor; 00066 i->pt.y *= factor; 00067 } 00068 } 00069 00070 /* 00071 inline void convertMatches(const std::vector<cv::DMatch> &in, std::vector<std::pair<int,int> > &out) 00072 { 00073 out.resize(in.size()); 00074 for (size_t i = 0; i < in.size(); i++) 00075 { 00076 out[i].first = in[i].queryIdx; 00077 out[i].second = in[i].trainIdx; 00078 } 00079 } 00080 00081 inline std::vector<std::pair<int,int> > convertMatches(const std::vector<cv::DMatch> &in) 00082 { 00083 std::vector<std::pair<int,int> > out; 00084 convertMatches(in,out); 00085 return out; 00086 } 00087 00088 inline pcl::PointXYZRGB getPCLColor(int r, int g, int b) 00089 { 00090 pcl::PointXYZRGB ret; 00091 ret.r = r; 00092 ret.g = g; 00093 ret.b = b; 00094 return ret; 00095 } 00096 00097 inline pcl::PointXYZRGB getPCLColor(size_t i) 00098 { 00099 pcl::PointXYZRGB ret; 00100 00101 switch (i) 00102 { 00103 case 0: 00104 ret.r = 255; ret.g = 0; ret.b = 0; 00105 return ret; 00106 case 1: 00107 ret.r = 0; ret.g = 255; ret.b = 0; 00108 return ret; 00109 case 2: 00110 ret.r = 0; ret.g = 0; ret.b = 255; 00111 return ret; 00112 default: 00113 ret.r = 0; ret.g = 0; ret.b = 0; 00114 } 00115 return ret; 00116 } 00117 00118 inline cv::Mat getCameraMatrix(double fx, double fy, double cx, double cy) 00119 { 00120 cv::Mat ret = cv::Mat::zeros(3,3, CV_64F); 00121 ret.at<double>(0,0) = fx; 00122 ret.at<double>(1,1) = fy; 00123 ret.at<double>(0,2) = cx; 00124 ret.at<double>(1,2) = cy; 00125 ret.at<double>(2,2) = 1.; 00126 return ret; 00127 } 00128 00129 inline cv::Mat getDistVector(double d0, double d1, double d2, double d3, double d4) 00130 { 00131 cv::Mat ret = cv::Mat(5,1, CV_64F); 00132 ret.at<double>(0) = d0; 00133 ret.at<double>(1) = d1; 00134 ret.at<double>(2) = d2; 00135 ret.at<double>(3) = d3; 00136 ret.at<double>(4) = d4; 00137 return ret; 00138 } 00139 00140 inline cv::Mat getDepthPointCloudLookUpTable(const cv::Size &size, const cv::Mat &camMat, const cv::Mat &distVec, const double &dsFactor) 00141 { 00142 cv::Mat pixels = cv::Mat(size.height * size.width,1, CV_64FC2); 00143 // Fill the tmp values simply with the image coordinates 00144 00145 { 00146 cv::Mat_<cv::Vec2d> _I = pixels; 00147 size_t iter = 0; 00148 for (int y = 0; y < size.height; y++) 00149 { 00150 for (int x = 0; x < size.width; x++) 00151 { 00152 _I(iter)[0] = x; 00153 _I(iter)[1] = y; 00154 iter++; 00155 } 00156 } 00157 } 00158 cv::Mat normpixels = cv::Mat(pixels.size(), CV_64FC2); // normalized undistorted pixels 00159 cv::undistortPoints(pixels, normpixels, camMat, distVec); 00160 00161 cv::Mat ret = cv::Mat(normpixels.size(), CV_64FC3); // "normpixelsxyz" 00162 { 00163 cv::Mat_<cv::Vec2d> _J = normpixels; 00164 cv::Mat_<cv::Vec3d> _I = ret; 00165 size_t iter = 0; 00166 for (int y = 0; y < size.height; y++) 00167 { 00168 for (int x = 0; x < size.width; x++) 00169 { 00170 _I(iter)[0] = _J(iter)[0]*dsFactor; 00171 _I(iter)[1] = _J(iter)[1]*dsFactor; 00172 _I(iter)[2] = dsFactor; 00173 iter++; 00174 } 00175 } 00176 } 00177 return ret; 00178 } 00179 00180 inline void colorKeyPointsInPointCloud(pcl::PointCloud<pcl::PointXYZRGB> &pc, const std::vector<std::vector<size_t> > &kptsIndices, const pcl::PointXYZRGB &color) 00181 { 00182 for (size_t i = 0; i < kptsIndices.size(); i++) 00183 { 00184 for (size_t j = 0; j < kptsIndices[i].size(); j++) 00185 { 00186 pcl::PointXYZRGB& pt = (pc)[kptsIndices[i][j]]; 00187 pt.rgb = color.rgb; 00188 } 00189 } 00190 } 00191 00192 inline void createColoredPointCloud(const cv::Mat &img, const pcl::PointCloud<pcl::PointXYZ> &pc, pcl::PointCloud<pcl::PointXYZRGB> &out) 00193 { 00194 // Assume 1 to 1 mapping... 00195 size_t width = pc.width; 00196 size_t height = pc.height; 00197 size_t size = pc.size(); 00198 out.resize(size); 00199 out.width = width; 00200 out.height = height; 00201 out.is_dense = pc.is_dense; 00202 00203 // cv::Mat_<cv::Vec3b> _I = img; 00204 if (img.channels() == 1) 00205 { 00206 for (size_t i = 0; i < size; i++) 00207 { 00208 out[i].x = pc[i].x; 00209 out[i].y = pc[i].y; 00210 out[i].z = pc[i].z; 00211 out[i].r = img.data[i]; 00212 out[i].g = img.data[i]; 00213 out[i].b = img.data[i]; 00214 } 00215 } 00216 if (img.channels() == 3) 00217 { 00218 for (size_t i = 0; i < size; i++) 00219 { 00220 out[i].x = pc[i].x; 00221 out[i].y = pc[i].y; 00222 out[i].z = pc[i].z; 00223 out[i].r = img.data[3*i]; 00224 out[i].g = img.data[3*i+1]; 00225 out[i].b = img.data[3*i+2]; 00226 } 00227 } 00228 } 00229 */ 00230 00231 /* 00232 inline size_t convertDepthImageToPointCloud(const cv::Mat &depthImg, const cv::Mat &lookUpTable, pcl::PointCloud<pcl::PointXYZ> &pc) 00233 { 00234 if (depthImg.depth() != CV_16U) 00235 return 0; 00236 size_t width = depthImg.size().width; 00237 size_t height = depthImg.size().height; 00238 size_t size = width*height; 00239 if (pc.size() != size || pc.width != width || pc.height != height || pc.is_dense != true) 00240 { 00241 pc.resize(size); 00242 pc.is_dense = true; 00243 pc.width = width; 00244 pc.height = height; 00245 } 00246 00247 cv::Mat_<cv::Vec3d> _I = lookUpTable; 00248 00249 const double* plt = lookUpTable.ptr<double>(0); 00250 const unsigned short* pd = depthImg.ptr<unsigned short>(0); 00251 for (size_t i = 0; i < size; i++) 00252 { 00253 if (*pd == 0) 00254 { 00255 float nan = std::numeric_limits<float>::quiet_NaN(); 00256 pc[i] = pcl::PointXYZ(nan,nan,nan); 00257 } 00258 else 00259 { 00260 double depth = *pd; 00261 pc[i] = pcl::PointXYZ(depth * _I(i)[0], 00262 depth * _I(i)[1], 00263 depth * _I(i)[2]); 00264 } 00265 pd++; 00266 plt += 3; 00267 } 00268 return size; 00269 } 00270 00271 00272 inline bool insideBoarder(const cv::KeyPoint &keyPoint, const pcl::PointCloud<pcl::PointXYZ> &in, int boarderSize) 00273 { 00274 int u = static_cast<int>(keyPoint.pt.x+0.5); 00275 int v = static_cast<int>(keyPoint.pt.y+0.5); 00276 if ((u >= boarderSize) && 00277 (u < (int)in.width-boarderSize) && 00278 (v >= boarderSize) && v < 00279 ((int)in.height-boarderSize)) 00280 { 00281 return true; 00282 } 00283 return false; 00284 00285 } 00286 00287 inline void selectIndicesAroundKeyPoint(const cv::KeyPoint &keyPoint, const pcl::PointCloud<pcl::PointXYZ> &in, int nbPoints, std::vector<size_t> &out) 00288 { 00289 int u = static_cast<int>(keyPoint.pt.x+0.5); 00290 int v = static_cast<int>(keyPoint.pt.y+0.5); 00291 int index = v * in.width + u; 00292 out.push_back(index); 00293 switch (nbPoints) 00294 { 00295 case 21: 00296 { 00297 if (insideBoarder(keyPoint, in, 3)) 00298 { 00299 out.push_back(index-3); 00300 out.push_back(index+3); 00301 out.push_back(index+3*in.width); 00302 out.push_back(index-3*in.width); 00303 } 00304 } 00305 case 17: 00306 { 00307 if (insideBoarder(keyPoint, in, 2)) 00308 { 00309 out.push_back(index-in.width-2); 00310 out.push_back(index-in.width+2); 00311 out.push_back(index+in.width-2); 00312 out.push_back(index+in.width+2); 00313 } 00314 } 00315 case 13: 00316 { 00317 if (insideBoarder(keyPoint, in, 2)) 00318 { 00319 out.push_back(index-2); 00320 out.push_back(index+2); 00321 out.push_back(index+2*in.width); 00322 out.push_back(index-2*in.width); 00323 } 00324 } 00325 case 9: 00326 { 00327 if (insideBoarder(keyPoint, in, 1)) 00328 { 00329 out.push_back(index-in.width-1); 00330 out.push_back(index-in.width+1); 00331 out.push_back(index+in.width-1); 00332 out.push_back(index+in.width+1); 00333 } 00334 } 00335 case 5: 00336 { 00337 if (insideBoarder(keyPoint, in, 1)) 00338 { 00339 out.push_back(index-1); 00340 out.push_back(index+1); 00341 out.push_back(index+in.width); 00342 out.push_back(index-in.width); 00343 } 00344 } 00345 default: 00346 // Nothing 00347 break; 00348 } 00349 } 00350 */ 00351 } // namespace 00352 00353 #endif