PlanarVisualizationModel.cpp
Go to the documentation of this file.
00001 
00033 #include "VisualizationModel.h"
00034 #include "PlanarVisualizationModel.h"
00035 #include "ObjectModel.h"
00036 #include <cv.h>
00037 #include <highgui.h>
00038 #include <string>
00039 
00040 #include "DUtilsCV.h"
00041 
00042 using namespace std;
00043 
00044 // ----------------------------------------------------------------------------
00045 
00046 PlanarVisualizationModel::PlanarVisualizationModel
00047   (const std::vector<ObjectModel::Face> &faces, 
00048    const MetaFile::MetaData::tDimensions::tPlanar &dim)
00049 {
00050   m_face_images.resize(faces.size());
00051   m_face_images_bw.resize(faces.size());
00052   m_inv_A.resize(faces.size());
00053   
00054   m_dim = dim;
00055 
00056   for(unsigned int i = 0; i < faces.size(); ++i)
00057   {
00058     m_face_images[i] = faces[i].image.clone();
00059     if(m_face_images[i].channels() == 1)
00060       m_face_images_bw[i] = m_face_images[i];
00061     else
00062       cv::cvtColor(m_face_images[i], m_face_images_bw[i], CV_RGB2GRAY);
00063     
00064     if(faces[i].A.type() == CV_64F)
00065       m_inv_A[i] = faces[i].A.inv();
00066     else
00067     {
00068       cv::Mat AinvF = faces[i].A.inv();
00069       AinvF.convertTo(m_inv_A[i], CV_64F);
00070     }
00071   }
00072 
00073 }
00074 
00075 // ----------------------------------------------------------------------------
00076 
00077 void PlanarVisualizationModel::draw(cv::Mat &img, const cv::Mat &cTo,
00078   const cv::Mat &A, const cv::Mat &K) const
00079 {
00080   assert(cTo.type() == CV_64F);
00081   assert(img.type() == CV_8U || img.type() == CV_8UC3);
00082   
00083   // alpha channel of the object
00084   const float alpha = 0.35f;
00085   
00086   cv::Mat k;
00087   if(K.empty()) 
00088     k = cv::Mat::zeros(4,1,CV_32F);
00089   else
00090     k = K;
00091   
00092   // calculate face points in camera reference first
00093   vector<pair<float, int> > zvalues; // < min z, face idx >  
00094   zvalues.reserve(m_face_images.size());
00095   
00096   for(unsigned int i = 0; i < m_face_images.size(); ++i)
00097   {
00098     cv::Mat cTf = cTo * m_dim.Faces[i].oTf;
00099     // z value of the origin of the patch in the camera frame
00100     zvalues.push_back(make_pair
00101       (cTf.at<double>(2,3) / cTf.at<double>(3,3), i ));
00102   }
00103   
00104   // sort in ascending z
00105   sort(zvalues.begin(), zvalues.end());
00106   
00107   // print in descending z
00108   cv::Mat cRo;
00109   cv::Mat cto(3, 1, CV_64F);
00110   DUtilsCV::Transformations::decomposeRt(cTo, cRo, cto);
00111   
00112   vector<pair<float, int> >::reverse_iterator zit;
00113   for(zit = zvalues.rbegin(); zit != zvalues.rend(); ++zit)
00114   {
00115     int face_idx = zit->second;
00116     
00117     const cv::Mat& model_im = (img.channels() == 3 ? 
00118       m_face_images[face_idx] : m_face_images_bw[face_idx]);
00119     
00120     const float w =  m_dim.Faces[face_idx].Width/2.f;
00121     const float h = m_dim.Faces[face_idx].Height/2.f;
00122     cv::Mat fP = (cv::Mat_<double>(4, 4) <<
00123       -w,  w, w, -w,
00124       -h, -h, h,  h,
00125        0,  0, 0,  0,
00126        1,  1, 1,  1);
00127     
00128     cv::Mat oP = m_dim.Faces[face_idx].oTf * fP; // 4x4
00129     
00130     cv::Mat oP_4x3(oP.cols, 3, CV_32F);
00131 
00132     for(int c = 0; c < oP.cols; ++c)
00133       for(int r = 0; r < 3; ++r)
00134         oP_4x3.at<float>(c, r) = oP.at<double>(r, c) / oP.at<double>(3, c);
00135     
00136     vector<cv::Point2f> cam_pixels;
00137     cv::projectPoints(oP_4x3, cRo, cto, A, k, cam_pixels);
00138     
00139     cv::Mat camera_pixels(4, 2, CV_32F, &(cam_pixels[0].x));
00140     cv::Mat object_pixels = (cv::Mat_<float>(4, 2) <<
00141                   0,             0,
00142       model_im.cols,             0,
00143       model_im.cols, model_im.rows,
00144                   0, model_im.rows);
00145         
00146     cv::Mat cHo = cv::findHomography(object_pixels, camera_pixels, 0);
00147 
00148     if(!cHo.empty())
00149     {
00150       if(alpha < 1.f)
00151       {
00152         cv::Mat img_original = img.clone();
00153 
00154         // create warp image and copy on img
00155         cv::warpPerspective(model_im, img, cHo, img.size(), 
00156           cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00157 
00158         // this could be done better
00159         
00160         if(img.channels() == 3)
00161         {
00162           for(int y = 0; y < img.rows; ++y)
00163           {
00164             unsigned char *py = img.ptr<unsigned char>(y);
00165             const unsigned char *qy = img_original.ptr<unsigned char>(y);
00166             
00167             for(int x = 0; x < img.cols; ++x)
00168             {
00169               int x3 = x*3;
00170               py[x3] = (float)py[x3] * alpha + (1.f - alpha) * (float)qy[x3];
00171               py[x3+1] = (float)py[x3+1]*alpha + (1.f - alpha)*(float)qy[x3+1];
00172               py[x3+2] = (float)py[x3+2]*alpha + (1.f - alpha)*(float)qy[x3+2];
00173             }
00174           }
00175         }
00176         else
00177         {
00178           for(int y = 0; y < img.rows; ++y)
00179           {
00180             unsigned char *py = img.ptr<unsigned char>(y);
00181             const unsigned char *qy = img_original.ptr<unsigned char>(y);
00182             
00183             for(int x = 0; x < img.cols; ++x)
00184             {
00185               py[x] = (float)py[x]*alpha + (1.f - alpha)*(float)qy[x];
00186             }
00187           }
00188         }
00189         
00190       }
00191       else
00192       {
00193         // just warp the model on the image
00194         // create warp image and copy on img
00195         cv::warpPerspective(model_im, img, cHo, img.size(), 
00196           cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00197       }
00198 
00199       // draw a rectangle
00200       DUtilsCV::Drawing::drawBox(img, cHo, model_im.cols, model_im.rows);
00201           }
00202   } // for each face in descencing z
00203   
00204   // draw a reference system
00205   float length;
00206   float d[3] = {m_dim.Width, m_dim.Height, m_dim.Depth};
00207   sort(d, d+3); // ascending
00208 
00209   if(d[0] < d[2]/3.f)
00210   {
00211     // thin object
00212     length = 0.5f * d[1];
00213   }
00214   else
00215   {
00216     // almost a cube
00217     length = 0.5f * d[0];
00218   }
00219 
00220   DUtilsCV::Drawing::drawReferenceSystem(img, cRo, cto, A, k, length);
00221   
00222 }
00223 
00224 // ----------------------------------------------------------------------------
00225 
00226 void PlanarVisualizationModel::draw(cv::Mat &img, const cv::Mat &sHm,
00227   unsigned int face_idx) const
00228 {
00229   if(face_idx >=  m_face_images.size()) return;
00230   
00231   const cv::Mat& model_im = (img.channels() == 3 ? 
00232     m_face_images[face_idx] : m_face_images_bw[face_idx]);
00233   
00234   // create warp image and copy on img
00235   cv::warpPerspective(model_im, img, sHm, img.size(), 
00236     cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00237 
00238   // draw a rectangle
00239   DUtilsCV::Drawing::drawBox(img, sHm, model_im.cols, model_im.rows);
00240   
00241 }
00242 
00243 // ----------------------------------------------------------------------------
00244 
00245 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:08