planar.cpp
Go to the documentation of this file.
00001 /*
00002  *  planar.cpp
00003  *  outlet_model
00004  *
00005  *  Created by Victor  Eruhimov on 1/16/09.
00006  *  Copyright 2009 Argus Corp. All rights reserved.
00007  *
00008  */
00009 
00010 //*****************************************************************************************
00011 // Warning: this is research code with poor architecture, performance and no documentation!
00012 //*****************************************************************************************
00013 
00014 #include <time.h>
00015 
00016 #include "outlet_pose_estimation/detail/planar.h"
00017 #include <highgui.h>
00018 #include <stdio.h>
00019 
00020 #include <limits>
00021 
00022 void gen_3x3_matrix(CvMat* in, CvMat* out)
00023 {
00024         for(int r = 0; r < 2; r++)
00025         {
00026                 for(int c = 0; c < 3; c++)
00027                 {
00028                         float value = cvmGet(in, r, c);
00029                         cvmSet(out, r, c, value);
00030                 }
00031         }
00032 
00033         cvmSet(out, 2, 0, 0.0f);
00034         cvmSet(out, 2, 1, 0.0f);
00035         cvmSet(out, 2, 2, 1.0f);
00036 }
00037 
00038 CvPoint2D32f apply_mat(CvMat* mat, CvPoint2D32f vec)
00039 {
00040         CvPoint2D32f res = cvPoint2D32f(cvmGet(mat, 0, 0)*vec.x + cvmGet(mat, 0, 1)*vec.y,
00041                                                                         cvmGet(mat, 1, 0)*vec.x + cvmGet(mat, 1, 1)*vec.y);
00042         return(res);
00043 }
00044 
00045 CvRect calc_mapped_rectangle(CvMat* mat, CvRect roi)
00046 {
00047         CvPoint2D32f p[4];
00048         p[0] = cvPoint2D32f(roi.x, roi.y);
00049         p[1] = cvPoint2D32f(roi.x + roi.width, roi.y);
00050         p[2] = cvPoint2D32f(roi.x + roi.width, roi.y + roi.height);
00051         p[3] = cvPoint2D32f(roi.x, roi.y + roi.height);
00052         
00053         CvPoint2D32f r[4];
00054         for(int i = 0; i < 4; i++)
00055         {
00056                 r[i] = apply_mat(mat, p[i]);
00057         }
00058         
00059         float xmin = FLT_MAX, xmax = -FLT_MAX, ymin = FLT_MAX, ymax = -FLT_MAX;
00060         for(int i = 0; i < 4; i++)
00061         {
00062                 xmin = MIN(xmin, r[i].x);
00063                 xmax = MAX(xmax, r[i].x);
00064                 ymin = MIN(ymin, r[i].y);
00065                 ymax = MAX(ymax, r[i].y);
00066         }
00067         
00068         return(cvRect(xmin, ymin, xmax - xmin, ymax - ymin));
00069 }
00070 
00071 void copy_cols(CvMat* src, CvMat* dst, int start_col, int end_col)
00072 {
00073         for(int r = 0; r < src->rows; r++)
00074         {
00075                 for(int c = start_col; c < end_col; c++)
00076                 {
00077                         float val = cvmGet(src, r, c);
00078                         cvmSet(dst, r, c, val);
00079                 }
00080         }
00081 }
00082 
00083 // generates a 2x3 affine transform 
00084 CvSize gen_random_homog_transform(CvRect roi, CvMat* mat)
00085 {
00086         CvMat* rt = cvCreateMat(2, 2, CV_32FC1);
00087         CvMat* rp = cvCreateMat(2, 2, CV_32FC1);
00088         CvMat* rpi = cvCreateMat(2, 2, CV_32FC1);
00089         CvMat* s = cvCreateMat(2, 2, CV_32FC1);
00090         CvMat* final = cvCreateMat(2, 2, CV_32FC1);
00091         
00092         CvMat* temp = cvCreateMat(2, 3, CV_32FC1);
00093                 
00094         float phi = (float(rand())/RAND_MAX*2 - 1)*60;
00095         cv2DRotationMatrix(cvPoint2D32f(0, 0), phi, 1, temp);
00096         copy_cols(temp, rp, 0, 2);
00097 
00098         cv2DRotationMatrix(cvPoint2D32f(0, 0), -phi, 1, temp);
00099         copy_cols(temp, rpi, 0, 2);
00100         
00101         const float max_angle = 30;
00102         float theta = (float(rand())/RAND_MAX*2 - 1)*max_angle;
00103         cv2DRotationMatrix(cvPoint2D32f(0, 0), theta, 1, temp);
00104         copy_cols(temp, rt, 0, 2);
00105         
00106         const float smin = 0.8f;
00107         const float smax = 1.3f;
00108         float l1 = float(rand())/RAND_MAX*(smax - smin) + smin;
00109         float l2 = float(rand())/RAND_MAX*(smax - smin) + smin;
00110         cvmSet(s, 0, 0, l1);
00111         cvmSet(s, 0, 1, 0.0f);
00112         cvmSet(s, 1, 0, 0.0f);
00113         cvmSet(s, 1, 1, l2);
00114         
00115         cvMatMul(rt, rpi, final);
00116         cvMatMul(final, s, final);
00117         cvMatMul(final, rp, final);
00118         
00119         CvRect bound = calc_mapped_rectangle(final, roi);
00120         
00121         for(int r = 0; r < 2; r++)
00122         {
00123                 for(int c = 0; c < 2; c++)
00124                 {
00125                         float value = cvmGet(final, r, c);
00126                         cvmSet(mat, r, c, value);
00127                 }
00128         }
00129         
00130         int length = MAX(bound.width, bound.height);
00131         bound.x -= (length - bound.width)/2;
00132         bound.y -= (length - bound.height)/2;
00133         
00134         cvmSet(mat, 0, 2, -bound.x);
00135         cvmSet(mat, 1, 2, -bound.y);
00136         
00137         cvReleaseMat(&rt);
00138         cvReleaseMat(&rp);
00139         cvReleaseMat(&s);
00140         cvReleaseMat(&rpi);
00141         cvReleaseMat(&temp);
00142         cvReleaseMat(&final);
00143         
00144         
00145         return cvSize(length, length);
00146 }
00147 
00148 void gen_random_homog_patches(IplImage* src, int count, IplImage** dst)
00149 {
00150         srand(clock());
00151         
00152         CvRect roi = cvGetImageROI(src);
00153         cvResetImageROI(src);
00154         
00155         CvMat* transform = cvCreateMat(2, 3, CV_32FC1);
00156         for(int i = 0; i < count; i++)
00157         {
00158                 CvSize size = gen_random_homog_transform(roi, transform);
00159                 dst[i] = cvCreateImage(size, IPL_DEPTH_8U, 1);
00160                 cvWarpAffine(src, dst[i], transform);
00161                 cvEqualizeHist(dst[i], dst[i]);
00162         }
00163         cvSetImageROI(src, roi);
00164         
00165         cvReleaseMat(&transform);
00166 }
00167 
00168 void save_image_array(const char* folder, const char* filename, int count, IplImage** images)
00169 {
00170         for(int i = 0; i < count; i++)
00171         {
00172                 char buf[1024];
00173                 sprintf(buf, "%s/%s_%d.jpg", folder, filename, i);
00174                 cvSaveImage(buf, images[i]);
00175         }
00176 }
00177 
00178 void release_image_array(int count, IplImage** images)
00179 {
00180         for(int i = 0; i < count; i++)
00181         {
00182                 cvReleaseImage(&images[i]);
00183         }
00184 }
00185 void test_homog_transform(IplImage* src)
00186 {
00187         const int count = 30;
00188         IplImage* images[count];
00189         gen_random_homog_patches(src, count, images);
00190         save_image_array("../../patches", "", count, images);
00191         release_image_array(count, images);
00192 }
00193 
00194 namespace cv{
00195     
00196     
00197 // Algorithm:
00198 // plane equation: P*N + c = 0
00199 // we find point rays in 3D from image points and camera parameters
00200 // then we fit c by minimizing average L2 distance between rotated and translated object points
00201 // and points found by crossing point rays with plane. We use the fact that center of mass 
00202 // of object points and fitted points should coincide.
00203 void findPlanarObjectPose(const Mat& object_points, const Mat& image_points, const Point3f& normal, 
00204                               const Mat& intrinsic_matrix, const Mat& distortion_coeffs, std::vector<Point3f>& object_points_crf)
00205 {
00206     vector<Point2f> _rays;
00207     undistortPoints(image_points, _rays, intrinsic_matrix, distortion_coeffs);
00208     
00209     // filter rays that are parallel to the plane
00210     vector<Point3f> rays;
00211     for(size_t i = 0; i < _rays.size(); i++)
00212     {
00213         double proj = rays[i].dot(normal);
00214         if(fabs(proj) > std::numeric_limits<double>::epsilon())
00215         {
00216             rays.push_back(Point3f(_rays[i].x, _rays[i].y, 1.0f));
00217         }
00218     }
00219     
00220     Point3f pm(0.0f, 0.0f, 0.0f);
00221     for(size_t i = 0; i < rays.size(); i++)
00222     {
00223         pm = pm + rays[i]*(1.0/rays[i].dot(normal));
00224     }
00225     
00226     pm = -pm*(1.0/rays.size());
00227     
00228     double dev = 0.0;
00229     for(size_t i = 0; i < rays.size(); i++)
00230     {
00231         Point3f pdev = rays[i]*(1.0/rays[i].dot(normal)) - pm;
00232         dev += pdev.dot(pdev);
00233     }
00234     
00235     double C = -1.0/sqrt(dev);
00236     
00237     object_points_crf.resize(rays.size());
00238     for(size_t i = 0; i < rays.size(); i++)
00239     {
00240         object_points_crf[i] = -rays[i]*(C/rays[i].dot(normal));
00241     }
00242 }
00243 
00244 };


outlet_pose_estimation
Author(s): Patrick Mihelich
autogenerated on Mon Dec 2 2013 13:21:50