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
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
00093 vector<pair<float, int> > zvalues;
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
00100 zvalues.push_back(make_pair
00101 (cTf.at<double>(2,3) / cTf.at<double>(3,3), i ));
00102 }
00103
00104
00105 sort(zvalues.begin(), zvalues.end());
00106
00107
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;
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
00155 cv::warpPerspective(model_im, img, cHo, img.size(),
00156 cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00157
00158
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
00194
00195 cv::warpPerspective(model_im, img, cHo, img.size(),
00196 cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00197 }
00198
00199
00200 DUtilsCV::Drawing::drawBox(img, cHo, model_im.cols, model_im.rows);
00201 }
00202 }
00203
00204
00205 float length;
00206 float d[3] = {m_dim.Width, m_dim.Height, m_dim.Depth};
00207 sort(d, d+3);
00208
00209 if(d[0] < d[2]/3.f)
00210 {
00211
00212 length = 0.5f * d[1];
00213 }
00214 else
00215 {
00216
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
00235 cv::warpPerspective(model_im, img, sHm, img.size(),
00236 cv::INTER_AREA, cv::BORDER_TRANSPARENT);
00237
00238
00239 DUtilsCV::Drawing::drawBox(img, sHm, model_im.cols, model_im.rows);
00240
00241 }
00242
00243
00244
00245