diff options
Diffstat (limited to 'meowpp/gra')
-rw-r--r-- | meowpp/gra/Bitmap.h | 87 | ||||
-rw-r--r-- | meowpp/gra/BundleAdjustment.h | 54 | ||||
-rw-r--r-- | meowpp/gra/BundleAdjustment_LM.h | 375 | ||||
-rw-r--r-- | meowpp/gra/Camera.h | 367 | ||||
-rw-r--r-- | meowpp/gra/Eye.h | 174 | ||||
-rw-r--r-- | meowpp/gra/FeaturePoint.h | 79 | ||||
-rw-r--r-- | meowpp/gra/FeaturePointsDetector.h | 4 | ||||
-rw-r--r-- | meowpp/gra/FeaturePointsDetector_Harris.h | 59 | ||||
-rw-r--r-- | meowpp/gra/FeaturePointsMatch.h | 25 | ||||
-rw-r--r-- | meowpp/gra/FeaturePointsMatch_K_Match.h | 38 | ||||
-rw-r--r-- | meowpp/gra/IdentityPoints.h | 140 | ||||
-rw-r--r-- | meowpp/gra/Photo.h | 78 | ||||
-rw-r--r-- | meowpp/gra/WatchBall.h | 11 |
13 files changed, 966 insertions, 525 deletions
diff --git a/meowpp/gra/Bitmap.h b/meowpp/gra/Bitmap.h index c4ed4e0..59136c2 100644 --- a/meowpp/gra/Bitmap.h +++ b/meowpp/gra/Bitmap.h @@ -1,9 +1,6 @@ #ifndef gra_Bitmap_H__ #define gra_Bitmap_H__ - -#include "../Self.h" - #include "../math/utility.h" #include "../math/Matrix.h" @@ -15,7 +12,7 @@ #include <typeinfo> #include <cstdlib> -namespace meow{ +namespace meow { /*! * @brief 二維點陣資料 @@ -26,7 +23,8 @@ template<class Pixel> class Bitmap: public ObjBase { private: Matrix<Pixel> matrix_; - // + + //! 回傳高斯模糊的權重 static std::vector<double> gaussianFactor1(double sigma) { double sigma2 = squ(sigma); size_t width = std::max(ceil((double)(sigma * 2)), 0.0); @@ -38,6 +36,8 @@ private: factor[width] = 1.0; return factor; } + + //! 回傳gradiance的權重 static std::vector<double> gradianceFactor1(double sigma) { double sigma2 = squ(sigma), ss = sigma * 2; size_t width = std::max(ceil(ss), 1.0); @@ -49,6 +49,8 @@ private: factor[width] = 0.0; return factor; } + + //! 針對某一方向用某種權重模糊 Bitmap xyBlur(std::vector<double> const& factor, ssize_t dx, ssize_t dy) const { Bitmap ret(*this); @@ -128,7 +130,7 @@ public: void reset(size_t h, size_t w, Pixel const& p) { matrix_.reset(h, w, p); } - + /*! * @brief 清除資料, 寬高階規零 */ @@ -233,6 +235,28 @@ public: } /*! + * @brief 回傳矩陣形式 + */ + Matrix<Pixel> const& matrix() const { + return matrix_; + } + + /*! + * @brief 回傳矩陣形式 (non-constant form) + */ + Matrix<Pixel>& matrixGet() { + return matrix_; + } + + /*! + * @brief 直接設定 + */ + Matrix<Pixel> const& matrix(Matrix<Pixel> const& p) { + matrix_.copyFrom(p); + return matrix(); + } + + /*! * @brief 回傳高斯模糊 * * @param [in] radiusY 高斯模糊的Y軸方向的sigma @@ -278,7 +302,7 @@ public: Bitmap<Pixel>& gradiancedX(double radiusY, double radiusX) { return copyFrom(gradianceX(radiusY, radiusX)); } - + /*! * @brief 回傳對y偏微分 * @@ -322,48 +346,42 @@ public: Pixel const& operator()(size_t y, size_t x, Pixel const& p) const { return pixel(y, x, p); } - + /*! @brief 將資料寫入檔案 * * @note 未完成, 輸入參數 fg 無用 */ bool write(FILE* f, bool bin, unsigned int fg) const { - size_t w = width(), h = height(); + if (fg & 1) + return false; if (bin) { - if (fwrite(&h, sizeof(size_t), 1, f) < 1) return false; - if (fwrite(&w, sizeof(size_t), 1, f) < 1) return false; + long tmp; + if (fwrite(&(tmp = matrix_.cols()), sizeof(tmp), 1, f) < 1) return false; + if (fwrite(&(tmp = matrix_.rows()), sizeof(tmp), 1, f) < 1) return false; } else { - if (fprintf(f, "%lu %lu\n", h, w) < 2) return false; - } - if (fg) { - // TODO - return false; + if (fprintf(f, "%ld %ld\n", (long)matrix_.cols(), (long)matrix_.rows()) + < 2) return false; } return true; - //return propertyWrite(__f, __bin, __fg); } - + /*! @brief 將資料讀入 * * @note 未完成, 輸入參數 fg 無用 */ bool read(FILE* f, bool bin, unsigned int fg) { - size_t w, h; - if (bin) { - if (fread(&h, sizeof(size_t), 1, f) < 1) return false; - if (fread(&w, sizeof(size_t), 1, f) < 1) return false; - } - else { - if (fscanf(f, "%lu %lu\n", &h, &w) < 2) return false; - } - if (fg) { - // TODO + if (fg & 1) return false; + long tmp1, tmp2; + if (bin) { + if (fread(&tmp1, sizeof(tmp1), 1, f) < 1) return false; + if (fread(&tmp2, sizeof(tmp2), 1, f) < 1) return false; } else { - reset(h, w, Pixel(0)); + if (fscanf(f, "%ld %ld", &tmp1, &tmp2) < 2) return false; } + matrix_.size(tmp1, tmp2, Pixel(0)); return true; } @@ -374,7 +392,7 @@ public: ObjBase* create() const { return new Bitmap(); } - + /*! @brief 複製資料 * * 輸入型別是 \c ObjBase \c const* @@ -387,16 +405,15 @@ public: ObjBase* copyFrom(ObjBase const* b) { return &(copyFrom(*(Bitmap*)b)); } - + /*! @brief 回傳class的type * * @return \c char \c const\c * 形式的typename */ char const* ctype() const{ - static char const* ptr = typeid(*this).name(); - return ptr; + return typeid(*this).name(); } - + /*! @brief 回傳class的type * * @return \c std::string 形式的typename @@ -406,6 +423,6 @@ public: } }; -} +} // meow #endif // gra_Bitmap_H__ diff --git a/meowpp/gra/BundleAdjustment.h b/meowpp/gra/BundleAdjustment.h new file mode 100644 index 0000000..9dd01b7 --- /dev/null +++ b/meowpp/gra/BundleAdjustment.h @@ -0,0 +1,54 @@ +#ifndef BundleAdjustment_H__ +#define BundleAdjustment_H__ + +#include "Eye.h" + +#include "../oo/ObjBase.h" + +namespace meow { + +enum SceneInfoFlags { + CAN_OFFSET = 0x01, + CAN_ROTATE = 0x02, + CAN_ZOOM = 0x04 +}; + +template<class Pixel> +struct SceneInfo { + Eye<Pixel>* eye; + unsigned long flag; + + SceneInfo(): eye(NULL), flag(0) { + } + + SceneInfo(Eye<Pixel>* e, unsigned long f): eye(e), flag(f) { + } + + SceneInfo(SceneInfo const& si): eye(si.eye), flag(si.flag) { + } + + ~SceneInfo() { + } +}; + +template<class Pixel> +class BundleAdjustment: public ObjBase { +protected: + BundleAdjustment() { + } +public: + virtual ~BundleAdjustment() { + } + + virtual bool adjustEye(std::vector<SceneInfo<Pixel> >* seq) const { + return false; + } + + virtual bool adjustFixedPoint(std::vector<SceneInfo<Pixel> >* seq) const { + return false; + } +}; + +} // meow + +#endif // BundleAdjustment_H__ diff --git a/meowpp/gra/BundleAdjustment_LM.h b/meowpp/gra/BundleAdjustment_LM.h new file mode 100644 index 0000000..7a86666 --- /dev/null +++ b/meowpp/gra/BundleAdjustment_LM.h @@ -0,0 +1,375 @@ +#ifndef BundleAdjustment_LM_H__ +#define BundleAdjustment_LM_H__ + +#include "Eye.h" + +#include "BundleAdjustment.h" + +#include "../math/methods.h" +#include "../math/Vector.h" +#include "../math/Matrix.h" +#include "../math/utility.h" + +#include "../oo/ObjBase.h" + +#include <algorithm> + +namespace meow { + +template<class Pixel> +class BundleAdjustment_LM: public BundleAdjustment<Pixel> { +private: + struct MatchPair { + size_t from_i; + Matrix<double> from_m; + size_t to_i; + Matrix<double> to_m; + }; + + class NoOffsetController { + private: + std::vector<MatchPair >* pairs_; + std::vector<Rotation3D <double> >* rot_; + std::vector<PhotoProjection<double> >* pho_; + BallProjection<double> bll_; + bool flag; + public: + NoOffsetController(std::vector<MatchPair >* pairs, + std::vector<Rotation3D<double> >* rot, + std::vector<PhotoProjection<double> >* pho, + bool fg): + pairs_(pairs), rot_(rot), pho_(pho), bll_(3.0, 1.0), flag(fg) { + } + Vector<double> init() { + if (flag == false) { + Vector<double> v(4, 0.0); + int i = (*pho_).size() - 1, n = 0; + v.entry(n++, (*pho_)[i].focal()); + v.entry(n++, (*rot_)[i].theta(0)); + v.entry(n++, (*rot_)[i].theta(1)); + v.entry(n++, (*rot_)[i].theta(2)); + return v; + } + Vector<double> v((*rot_).size() * 4, 0.0); + for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { + v.entry(n++, (*pho_)[i].focal()); + v.entry(n++, (*rot_)[i].theta(0)); + v.entry(n++, (*rot_)[i].theta(1)); + v.entry(n++, (*rot_)[i].theta(2)); + } + return v; + } + Vector<double> residure(Vector<double> const& v) { + for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { + if (flag == false && i != I - 1) continue; + (*pho_)[i].focal(v(n++)); + (*rot_)[i].theta(0, v(n++)); + (*rot_)[i].theta(1, v(n++)); + (*rot_)[i].theta(2, v(n++)); + } + for (typename std::vector<MatchPair>::iterator + it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it) { + (*it).from_m.entry(2, 0, -(*pho_)[(*it).from_i].focal()); + (*it). to_m.entry(2, 0, -(*pho_)[(*it). to_i].focal()); + } + // + Vector<double> ret((*pairs_).size() * 2, 0.0); + size_t n = 0; + for (typename std::vector<MatchPair>::iterator + it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { + Matrix<double> tr( + (*it).to_m + - + (*pho_)[(*it).to_i].transformate( + (*rot_)[(*it).to_i].transformate( + (*rot_)[(*it).from_i].transformateInv( + bll_.transformate( + (*it).from_m + ) + ) + ) + ) + ); + ret.entry(n * 2 , tr(0, 0)); + ret.entry(n * 2 + 1, tr(1, 0)); + } + //* + //for (size_t i = 0; i < ret.dimension(); i++) { + // printf("(%-9.1f ", ret(i)); + // if (i % 8 == 7) printf("\n"); + //} + //printf("\n"); + printf("re = %20.5f ?? %f\n", ret.length2(), 25.0 * (*pairs_).size()); + // */ + return ret; + } + Matrix<double> jacobian() const { + Matrix<double> ret; + if (flag == false) { + ret.reset((*pairs_).size() * 2, 4, 0.0); + } + else { + ret.reset((*pairs_).size() * 2, (*rot_).size() * 4, 0.0); + } + size_t n = 0; + for (typename std::vector<MatchPair>::iterator + it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { + Matrix<double> tr_A( bll_ .transformate((*it).from_m)); + Matrix<double> tr_B((*rot_)[(*it).from_i].transformateInv(tr_A)); + Matrix<double> tr_C((*rot_)[(*it). to_i].transformate (tr_B)); + Matrix<double> ja_A((*pho_)[(*it). to_i].jacobian (tr_C)); + Matrix<double> ja_B((*rot_)[(*it). to_i].jacobian (tr_B)); + Matrix<double> ja_C((*rot_)[(*it).from_i].jacobianInv(tr_A)); + Matrix<double> m; + int fr = (flag == false ? 0 : (*it).from_i); + int to = (flag == false ? 0 : (*it). to_i); + if (flag != false || (*it).from_i == (*rot_).size() - 1) { + m = ja_A * ja_B * ja_C * bll_.jacobian((*it).from_m).col(2); + ret.entry(n * 2 , fr * 4, m(0, 0)); + ret.entry(n * 2 + 1, fr * 4, m(1, 0)); + for (size_t k = 0; k < 3; ++k) { + m = ja_A * ja_B * (*rot_)[(*it).from_i].jacobianInv(tr_A, k); + ret.entry(n * 2 , fr * 4 + 1 + k, m(0, 0)); + ret.entry(n * 2 + 1, fr * 4 + 1 + k, m(1, 0)); + } + } + if (flag != false || (*it).to_i == (*rot_).size() - 1) { + m = (*pho_)[(*it).to_i].jacobian(tr_C, 0); + ret.entry(n * 2 , to * 4, m(0, 0)); + ret.entry(n * 2 + 1, to * 4, m(1, 0)); + for (size_t k = 0; k < 3; ++k) { + m = ja_A * (*rot_)[(*it).to_i].jacobian(tr_B, k); + ret.entry(n * 2 , to * 4 + 1 + k, m(0, 0)); + ret.entry(n * 2 + 1, to * 4 + 1 + k, m(1, 0)); + } + } + } + return ret; + } + Matrix<double> identity() const { + if (flag == false) { + Matrix<double> ret(4, 4, 0.0); + ret.identitied(); + return ret; + } + Matrix<double> ret((*rot_).size() * 4, (*rot_).size() * 4, 0.0); + ret.identitied(); + return ret; + } + }; + + struct Myself { + double t_; + + Myself(): t_(5.0) { + } + + Myself(Myself const& m): t_(m.t_) { + } + + ~Myself() { + } + }; + + Self<Myself> const self; + +public: + BundleAdjustment_LM(): self() { + } + + BundleAdjustment_LM(BundleAdjustment_LM const& b): + self(b.self, Self<Myself>::COPY_FROM) { + } + + ~BundleAdjustment_LM() { + } + + BundleAdjustment_LM& copyFrom(BundleAdjustment_LM const& b) { + self().copyFrom(b.self); + return *this; + } + + BundleAdjustment_LM& referenceFrom(BundleAdjustment_LM const& b) { + self().referenceFrom(b.self); + return *this; + } + + double threshold() const { + return self->t_; + } + + double threshold(double t) { + self()->t_ = t; + return threshold(); + } + + bool adjustEye(std::vector<SceneInfo<Pixel> >* seq) const { + // check + size_t N = (*seq).size(); + for (size_t i = 0; i < N; ++i) { + if ( (*seq)[i].flag & CAN_OFFSET ) return false; + if (!((*seq)[i].flag & CAN_ROTATE)) return false; + if (!((*seq)[i].flag & CAN_ZOOM )) return false; + } + // get all pairs + typedef typename Camera<Pixel>::FixedPoints2D::IdentityPointsMapIterK FPS_K; + std::vector<FPS_K> beg(N), end(N); + FPS_K it1, it2; + for (size_t i = 0; i < N; ++i) { + beg[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().begin(); + end[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().end (); + } + std::vector<std::vector<std::vector<MatchPair> > > all_pairs(N); + for (size_t i = 0; i < N; ++i) { + all_pairs[i].resize(N); + for (size_t j = 0; j < N; ++j) { + if (i == j) continue; + for (it1 = beg[i], it2 = beg[j]; it1 != end[i] && it2 != end[j]; ) { + if (it1->first < it2->first) ++it1; + else if(it1->first > it2->first) ++it2; + else { + MatchPair tmp; + tmp.from_i = i; + tmp.from_m = it1->second.matrix(); + tmp.from_m.rows(3, -(*seq)[i].eye->camera().photo().focal()); + tmp. to_i = j; + tmp. to_m = it2->second.matrix(); + tmp. to_m.rows(3, -(*seq)[j].eye->camera().photo().focal()); + all_pairs[i][j].push_back(tmp); + ++it1; + ++it2; + } + } + } + } + // + std::vector<MatchPair > pairs; + std::vector<Rotation3D <double> > rot; + std::vector<PhotoProjection<double> > pho; + std::vector<int > sum (N, 0); + std::vector<int > big (N, 0); + std::vector<int > real(N); + std::vector<int > rev (N); + // first!! + int best = -1, best_ct = -1; + for (size_t i = 0; i < N; ++i) { + int d = 0; + for (size_t j = 0; j < N; ++j) { + d += all_pairs[i][j].size(); + } + if (best_ct < d) { + best_ct = d; + best = i; + } + real[i] = i; + big [i] = i; + } + for (size_t i = 0; i < N; ++i) { + // update else + real[i] = best; + rev[best] = i; + for (size_t j = 0; j < N; ++j) { + if ((int)j == best) { + sum[j] = -1; + continue; + } + if (sum[j] < 0) continue; + sum[j] += all_pairs[best][j].size(); + if (all_pairs[j][big[j]].size() < all_pairs[j][best].size()) + big[j] = best; + } + // add me + printf("%d same as %d\n", best, big[best]); + if (big[best] == best) { + rot.push_back((*seq)[big[best]].eye->camera() .rotation()); + pho.push_back((*seq)[big[best]].eye->camera().photo().projection()); + } + else { + rot.push_back(rot[rev[big[best]]]); + pho.push_back(pho[rev[big[best]]]); + } + for (size_t j = 0; j < N; ++j) { + if (sum[j] >= 0) continue; + for (size_t k = 0, K = all_pairs[best][j].size(); k < K; ++k) { + all_pairs[best][j][k].from_i = rev[all_pairs[best][j][k].from_i]; + all_pairs[best][j][k]. to_i = rev[all_pairs[best][j][k]. to_i]; + pairs.push_back(all_pairs[best][j][k]); + } + for (size_t k = 0, K = all_pairs[j][best].size(); k < K; ++k) { + all_pairs[j][best][k].from_i = rev[all_pairs[j][best][k].from_i]; + all_pairs[j][best][k]. to_i = rev[all_pairs[j][best][k]. to_i]; + pairs.push_back(all_pairs[j][best][k]); + } + } + for (size_t j = 0; j < N; ++j) { printf("%4d ", sum[j]); } printf("\n"); + for (size_t j = 0; j < N; ++j) { printf("%4d ", big[j]); } printf("\n"); + for (size_t j = 0; j < N; ++j) { printf("%4d ", real[j]); } printf("\n"); + printf("\n"); + // bundle adjustment + if (i > 0) { + NoOffsetController ct1(&pairs, &rot, &pho, false); + ct1.residure(levenbergMarquardtTraining(ct1, ct1.init(), + 7.3, 1.0, + squ(threshold()) * pairs.size(), + 7, 1000)); + /* + NoOffsetController ct2(&pairs, &rot, &pho, true); + ct2.residure(levenbergMarquardtTraining(ct2, ct2.init(), + 0.1 * pairs.size(), 1.0, + squ(threshold()) * pairs.size(), + 7, 1000)); + // */ + } + // find next + best_ct = 0; + for (size_t j = 0; j < N; ++j) { + if (best_ct < sum[j]) { + best = j; + best_ct = sum[j]; + } + } + getchar(); + //if (i == N - 2) break; + } + // feedback + for (size_t i = 0; i < N; ++i) { + int id = real[i]; + (*seq)[id].eye->cameraGet() .rotation (rot[i]); + (*seq)[id].eye->cameraGet().photoGet().projection(pho[i]); + //if (i == N - 2) break; + } + return true; + } + + bool adjustFixedPoint(std::vector<SceneInfo<Pixel> >* seq) const { + return false; + } + + bool write(FILE* f, bool bin, unsigned int fg) const { + return false; + } + + bool read(FILE* f, bool bin, unsigned int fg) const { + return false; + } + + ObjBase* create() const { + return new BundleAdjustment_LM; + } + + ObjBase* copyFrom(ObjBase const* o) { + return &(copyFrom(*(BundleAdjustment_LM const*)o)); + } + + char const* ctype() const { + return typeid(*this).name(); + } + + std::string type() const { + return std::string(ctype()); + } +}; + +} // meow + +#endif // BundleAdjustment_LM_H__ diff --git a/meowpp/gra/Camera.h b/meowpp/gra/Camera.h index 45321de..2b6347c 100644 --- a/meowpp/gra/Camera.h +++ b/meowpp/gra/Camera.h @@ -32,13 +32,10 @@ private: Myself() { fixed2D_.dimension(2); } - ~Myself() { + Myself(Myself const& v): + photo_(v.photo_), rot_(v.rot_), fixed2D_(v.fixed2D_) { } - Myself& copyFrom(Myself const& b) { - photo_ .copyFrom(b. photo_); - rot_ .copyFrom(b. rot_); - fixed2D_.copyFrom(b.fixed2D_); - return *this; + ~Myself() { } }; @@ -47,14 +44,13 @@ public: /*! * @brief constructor */ - Camera(): self(true) { + Camera(): self() { } /*! * @brief copy constructor */ - Camera(Camera const& b): self(false) { - copyFrom(b); + Camera(Camera const& b): self(b.self, Self<Myself>::COPY_FROM) { } /*! @@ -119,7 +115,7 @@ public: * @brief 設定rotation */ Rotation3D<double> const& rotation(Rotation3D<double> const& rot) { - self()->rot_ = rot; + self()->rot_.copyFrom(rot); return rotation(); } @@ -142,7 +138,7 @@ public: */ FixedPoints2D const& fixedPoints2D(FixedPoints2D const& fps2d) const { if (fps2d.dimension() == 2) { - self()->fixed2D_ = fps2d; + self()->fixed2D_.copyFrom(fps2d); } return fixedPoints2D(); } @@ -150,7 +146,7 @@ public: /*! * @brief 取得編號為i的fixed points 2d */ - Vector<double> fixedPoints2D(int i) { + Vector<double> fixedPoint2D(int i) { return self->fixed2D_.identityPoint(i); } @@ -159,7 +155,7 @@ public: */ bool inside(Vector3D<double> p) const { return self->photo_.inside( - Vector3D<double>(self->rot_.transformate(p.matrix()))); + Vector3D<double>(rotation().transformate(p.matrix()))); } /*! @@ -167,7 +163,7 @@ public: */ Pixel color(Vector3D<double> p) const { return self->photo_.color( - Vector3D<double>(self->rot_.transformate(p.matrix()))); + Vector3D<double>(rotation().transformate(p.matrix()))); } /*! @@ -182,7 +178,20 @@ public: * @note 未完成 */ bool write(FILE* f, bool bin, unsigned int fg) const { - return false; + if (bin) { + double tmp; + for (size_t i = 0; i < 3; ++i) { + if (fwrite(&(tmp = rotation().theta(i)), sizeof(tmp), 1, f) < 1) + return false; + } + } + else { + for (size_t i = 0; i < 3; ++i) { + if (fprintf(f, "%f ", rotation().theta(i)) < 1) return false; + } + fprintf(f, "\n"); + } + return (fixedPoints2D().write(f, bin, fg) && photo().write(f, bin, fg)); } /*! @brief 將資料讀入 @@ -190,7 +199,23 @@ public: * @note 未完成 */ bool read(FILE* f, bool bin, unsigned int fg) { - return false; + if (bin) { + double tmp; + for (size_t i = 0; i < 3; ++i) { + if (fread(&tmp, sizeof(tmp), 1, f) < 1) { + return false; + } + rotationGet().theta(i, tmp); + } + } + else { + double a; + for (size_t i = 0; i < 3; ++i) { + if (fscanf(f, "%lf", &a) < 1) return false; + rotationGet().theta(i, a); + } + } + return (fixedPoints2DGet().read(f, bin, fg) && photoGet().read(f, bin, fg)); } /*! @brief new一個自己 @@ -229,316 +254,8 @@ public: std::string type() const { return std::string(ctype()); } - - //////////////////////////////////////////////////////////////////// -private: - class BoundleAdjustment2D { - private: - class Parameters { - private: - std::vector<Camera>& cam_; - std::vector<Rotation3D<double> > rot_; - std::vector<PhotoProjection<double> > pho_; - struct Pair { - size_t i1_; - size_t i2_; - Vector<double> v1_; - Vector<double> v2_; - Pair(size_t a, size_t b, - Vector<double> const& v1, Vector<double> const& v2): - i1_(a), i2_(b), v1_(v1), v2_(v2) { - } - }; - std::vector<Pair> pairs_; - - void setParameters(Vector<double> const& v) { - size_t n = 0; - for (size_t i = 0, I = cam_.size(); i < I; ++i) { - pho_[i].focal(v(n++)); - for (size_t j = 0; j < 3; j++) { - rot_[i].theta(j, v(n++)); - } - } - for (size_t i = 0, I = pairs_.size(); i < I; ++i) { - pairs_[i].v1_.entry(2, pho_[pairs_[i].i1_].focal()); - pairs_[i].v2_.entry(2, pho_[pairs_[i].i2_].focal()); - } - } - Vector<double> getParameters() const { - Vector<double> ret(cam_.size() * 4, 0.0); - for (size_t i = 0, I = cam_.size(); i < I; ++i) { - ret.entry(i * 4, pho_[i].focal()); - for (size_t j = 0; j < 3; ++j) { - ret.entry(i * 4 + 1 + j, rot_[i].theta(j)); - } - } - return ret; - } - Vector<double> residureV() const { - Vector<double> ret(pairs_.size() * 3, 0.0); - for (size_t i = 0, I = pairs_.size(); i < I; ++i) { - size_t i_from = pairs_[i].i1_; - size_t i_to = pairs_[i].i2_; - Matrix<double> v_from(pairs_[i].v1_.matrix()); - Matrix<double> v_to (pairs_[i].v2_.matrix()); - Matrix<double> v_tr( - pho_[i_to].transformate( - rot_[i_to].transformate( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - ) - ); - Matrix<double> delta(v_to - v_tr); - for (size_t j = 0; j < 3; ++j) { - ret.entry(i * 3 + j, delta(j, 0)); - } - } - return ret; - } - public: - Parameters(std::vector<Camera>& cam): cam_(cam) { - rot_.resize(cam_.size()); - pho_.resize(cam_.size(), PhotoProjection<double>(3)); - for (size_t i = 0, I = cam_.size(); i < I; ++i) { - rot_[i].referenceFrom(cam_[i].rotation()); - pho_[i].focal(cam_[i].photo().focal()); - } - for (size_t i = 0, I = cam_.size(); i < I; ++i) { - std::map<int,Vector<double> >const& p1 = ( - cam_[i].fixedPoints2D().identityPoints()); - for (size_t j = 0; j < I; ++j) { - if (i == j) continue; - std::map<int,Vector<double> >const& p2 = ( - cam_[j].fixedPoints2D().identityPoints()); - for (std::map<int,Vector<double> >::const_iterator - it1 = p1.begin(); it1 != p1.end(); ++it1) { - for (std::map<int,Vector<double> >::const_iterator - it2 = p2.begin(); it2 != p2.end(); ++it2) { - if (it1->first != it2->first) continue; - Vector<double> v1(it1->second), v2(it2->second); - v1.dimension(3, 0.0); - v2.dimension(3, 0.0); - pairs_.push_back(Pair(i, j, v1, v2)); - } - } - } - } - } - Vector<double> init() const { - return getParameters(); - } - Vector<double> residure(Vector<double> const& v) const { - ((Parameters*)this)->setParameters(v); - return residureV(); - } - Matrix<double> jacobian(Vector<double> const& v) const { - //setParameters(v); - Matrix<double> ret(pairs_.size() * 3, v.dimension(), 0.0); - for (size_t i = 0, I = pairs_.size(); i < I; ++i) { - for (size_t j = 0, J = v.dimension(); j < J; ++j) { - size_t j0 = j / 4; - size_t dj = j % 4; - size_t i_from = pairs_[i].i1_; - size_t i_to = pairs_[i].i2_; - Matrix<double> v_from(pairs_[i].v1_.matrix()); - Matrix<double> v_to (pairs_[i].v2_.matrix()); - Matrix<double> v_tr (3, 1, 0.0); - if (j0 == i_from) { - if (dj == 0) { - v_tr = ( - pho_[i_to].jacobian( - rot_[i_to].transformate( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - ) - * - rot_[i_to].jacobian( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - * - rot_[i_from].jacobianInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - * - BallProjection<double>(3, 1.0).jacobian( - v_from - ).col(2) - ); - } - else { - v_tr = ( - pho_[i_to].jacobian( - rot_[i_to].transformate( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - ) - * - rot_[i_to].jacobian( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - * - rot_[i_from].jacobianInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ); - } - } - else if (j0 == i_to) { - if (dj == 0) { - v_tr = ( - pho_[i_to].jacobian( - rot_[i_to].transformate( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - ).col(2) - ); - } - else { - v_tr = ( - pho_[i_to].jacobian( - rot_[i_to].transformate( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ) - ) - ) - * - rot_[i_to].jacobian( - rot_[i_from].transformateInv( - BallProjection<double>(3, 1.0).transformate( - v_from - ) - ), - dj - 1 - ) - ); - } - } - for (size_t k = 0; k < 3; ++k) { - ret.entry(i * 3 + k, j, -v_tr(k, 0)); - } - } - } - return ret; - } - Matrix<double> identity(Vector<double> const& v) const { - //setParameters(v); - Matrix<double> ret(v.dimension(), v.dimension(), 0.0); - ret.identity(); - return ret; - } - double averageResidure() const { - Vector<double> res(residureV()); - double sum = 0; - for (size_t i = 0, I = res.dimension(); i < I; ++i) { - sum += res(i); - } - return sum / res.dimension(); - } - size_t dimensinonI() const { - return cam_.size() * 4; - } - size_t dimensionO() const { - return pairs_.size() * 3; - } - }; - class F { - private: - Parameters& p_; - public: - F(Parameters& p): p_(p) { - } - Vector<double> operator()(Vector<double> const& v) const { - return p_.residure(v); - } - }; - class J { - private: - Parameters& p_; - public: - J(Parameters& p): p_(p) { - } - Matrix<double> operator()(Vector<double> const& v) const { - return p_.jacobian(v); - } - }; - class I { - private: - Parameters& p_; - public: - I(Parameters& p): p_(p) { - } - Matrix<double> operator()(Vector<double> const& v) const { - return p_.identity(v); - } - }; - class Stop { - private: - Parameters& p_; - double t_; - public: - Stop(Parameters& p, double t): p_(p), t_(t) { - } - bool operator()(double r) const { - return (r < p_.dimensionO() * t_); - } - }; - public: - BoundleAdjustment2D() { - } - ~BoundleAdjustment2D() { - } - double operator()(std::vector<Camera>* cs, double threshold) const { - Parameters p(*cs); - Vector<double> v0(p.init()); - levenbergMarquardt(F(p), J(p), I(p), v0, Stop(p, threshold), 100000); - return p.averageResidure(); - } - }; -public: - /*! - * @brief 將數台camera用fixed points做boundle adjustment - * - * @param [in] cs 要調整的cameras - * @param [in] threshold 允許誤差值 - * @return 誤差值 - */ - static double boundleAdjustment2D(std::vector<Camera>* cs, double threshold) { - static BoundleAdjustment2D bdl; - return bdl(cs, threshold); - } }; -} +} // meow #endif // gra_Camera_H__ diff --git a/meowpp/gra/Eye.h b/meowpp/gra/Eye.h new file mode 100644 index 0000000..2621a16 --- /dev/null +++ b/meowpp/gra/Eye.h @@ -0,0 +1,174 @@ +#ifndef Eye_H__ +#define Eye_H__ + +#include "Camera.h" + +#include "../Self.h" +#include "../oo/ObjBase.h" + +namespace meow { + +/*! + * @brief 一個 \c Camera 加上一個offset transformation + * + * @author cat_leopard + */ +template<class Pixel> +class Eye: public ObjBase { +private: + struct Myself { + Camera<Pixel> cam_; + Vector3D<double> ofs_; + + Myself(): cam_(), ofs_(0.0, 0.0, 0.0) { + } + + Myself(Camera<Pixel> const& c, Vector3D<double> const& o): cam_(c), ofs_(o){ + } + + Myself(Myself const& b): cam_(b.cam_), ofs_(b.ofs_) { + } + + ~Myself() { + } + }; + + Self<Myself> const self; +public: + Eye(): self() { + } + + Eye(Eye const& b): self(b.self(), Self<Myself>::COPY_FROM) { + } + + Eye(Camera<Pixel> const& c, Vector3D<double> const& o): self(Myself(c, o)) { + } + + ~Eye() { + } + + Eye& copyFrom(Eye const& e) { + self().copyFrom(e.self); + return *this; + } + + Eye& referenceFrom(Eye const& e) { + self().referenceFrom(e.self); + return *this; + } + + Camera<Pixel> const& camera() const { + return self->cam_; + } + + Camera<Pixel>& cameraGet() { + return self()->cam_; + } + + Camera<Pixel> const& camera(Camera<Pixel> const& c) { + self()->cam_.copyFrom(c); + return camera(); + } + + Vector3D<double> const& offset() const { + return self->ofs_; + } + + Vector3D<double>& offsetGet() { + return self()->ofs_; + } + + Vector3D<double> const& offset(Vector3D<double> const& ofs) { + self()->ofs_ = ofs; + return offset(); + } + + bool inside(Vector3D<double> const& v) const { + return camera().inside(v - offset()); + } + + Eye& operator=(Eye const& e) { + return copyFrom(e); + } + + /*! @brief 將資料寫入檔案 + * + * @note 未完成 + */ + bool write(FILE* f, bool bin, unsigned int fg) const { + if (bin) { + double tmp; + for (size_t i = 0; i < 3; ++i) { + if (fwrite(&(tmp = offset()(i)), sizeof(tmp), 1, f) < 1) + return false; + } + } + else { + for (size_t i = 0; i < 3; ++i) { + if (fprintf(f, "%f ", offset()(i)) < 1) return false; + } + fprintf(f, "\n"); + } + return camera().write(f, bin, fg); + } + + /*! @brief 將資料讀入 + * + * @note 未完成 + */ + bool read(FILE* f, bool bin, unsigned int fg) { + if (bin) { + double tmp[3]; + if (fread(tmp, sizeof(double), 3, f) < 3) return false; + offsetGet().xyz(tmp[0], tmp[1], tmp[2]); + } + else { + double a, b, c; + if (fscanf(f, "%lf %lf %lf", &a, &b, &c) < 3) return false; + offsetGet().x(a); + offsetGet().y(b); + offsetGet().z(c); + } + return cameraGet().read(f, bin, fg); + } + + /*! @brief new一個自己 + * + * @return 一個new出來的pointer + */ + ObjBase* create() const { + return new Eye(); + } + + /*! @brief 複製資料 + * + * 輸入型別是 \c ObjBase \c const* + * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom + * + * @param [in] b 資料來源 + * @return this + */ + ObjBase* copyFrom(ObjBase const* b) { + return &(copyFrom(*(Eye*)b)); + } + + /*! @brief 回傳class的type + * + * @return \c char \c const\c * 形式的typename + */ + char const* ctype() const{ + return typeid(*this).name(); + } + + /*! @brief 回傳class的type + * + * @return \c std::string 形式的typename + */ + std::string type() const { + return std::string(ctype()); + } +}; + +} // meow + +#endif // Eye_H__ diff --git a/meowpp/gra/FeaturePoint.h b/meowpp/gra/FeaturePoint.h index 4b80a3d..c3ab8f3 100644 --- a/meowpp/gra/FeaturePoint.h +++ b/meowpp/gra/FeaturePoint.h @@ -75,6 +75,13 @@ public: } /*! + * @brief 回傳position (non-const reference) + */ + Vector<Scalar>& positionGet() { + return pos_; + } + + /*! * @brief 回傳description */ Vector<Description> const& description() const { @@ -82,6 +89,13 @@ public: } /*! + * @brief 回傳description (non-const reference) + */ + Vector<Description>& descriptionGet() { + return des_; + } + + /*! * @brief 修改position */ Vector<Scalar> const& position(Vector<Scalar> const& p) const { @@ -128,20 +142,6 @@ public: } /*! - * @brief 取得position - */ - Vector<Scalar>& positionGet() { - return pos_; - } - - /*! - * @brief 取得description - */ - Vector<Description>& descriptionGet() { - return des_; - } - - /*! * @brief same as copyFrom(fp) */ FeaturePoint& operator=(FeaturePoint const& fp) { @@ -163,11 +163,53 @@ public: } bool write(FILE* f, bool bin, unsigned int fg) const { - return false; + if (bin) { + double tmp; + for (size_t i = 0, I = position().dimension(); i < I; ++i) { + if (fwrite(&(tmp = position(i)), sizeof(tmp), 1, f) < 1) return false; + } + for (size_t i = 0, I = description().dimension(); i < I; ++i) { + if (fwrite(&(tmp = description(i)), sizeof(tmp), 1, f) < 1) + return false; + } + } + else { + for (size_t i = 0, I = position().dimension(); i < I; ++i) { + if (fprintf(f, "%f ", (double)position(i)) < 1) return false; + } + fprintf(f, "\n"); + for (size_t i = 0, I = description().dimension(); i < I; ++i) { + if (fprintf(f, "%f ", (double)description(i)) < 1) return false; + } + fprintf(f, "\n"); + } + return true; } bool read (FILE* f, bool bin, unsigned int fg) { - return false; + if (bin) { + double tmp; + for (size_t i = 0, I = position().dimension(); i < I; ++i) { + if (fread(&tmp, sizeof(tmp), 1, f) < 1) return false; + position(i, tmp); + } + for (size_t i = 0, I = description().dimension(); i < I; ++i) { + if (fread(&tmp, sizeof(tmp), 1, f) < 1) return false; + description(i, tmp); + } + } + else { + double tmp; + for (size_t i = 0, I = position().dimension(); i < I; ++i) { + if (fscanf(f, "%lf", &tmp) < 1) return false; + position(i, tmp); + } + for (size_t i = 0, I = description().dimension(); i < I; ++i) { + if (fscanf(f, "%lf", &tmp) < 1) return false; + description(i, tmp); + } + } + return true; } ObjBase* create() const { @@ -179,8 +221,7 @@ public: } char const* ctype() const { - static char const* ptr = typeid(*this).name(); - return ptr; + return typeid(*this).name(); } std::string type() const { @@ -188,6 +229,6 @@ public: } }; -} +} // meow #endif // gra_FeaturePoint_H__ diff --git a/meowpp/gra/FeaturePointsDetector.h b/meowpp/gra/FeaturePointsDetector.h index 415419a..858c66a 100644 --- a/meowpp/gra/FeaturePointsDetector.h +++ b/meowpp/gra/FeaturePointsDetector.h @@ -18,9 +18,9 @@ public: virtual ~FeaturePointsDetector() { } virtual std::vector<FeaturePoint<double, double> > - detect(Bitmap<Pixel> const& __bitmap) const = 0; + detect(Bitmap<Pixel> const& bitmap) const = 0; }; -} +} // meow #endif // gra_FeaturePointsDetector_H__ diff --git a/meowpp/gra/FeaturePointsDetector_Harris.h b/meowpp/gra/FeaturePointsDetector_Harris.h index 25a46b2..11529f0 100644 --- a/meowpp/gra/FeaturePointsDetector_Harris.h +++ b/meowpp/gra/FeaturePointsDetector_Harris.h @@ -13,7 +13,6 @@ #include <vector> - namespace meow { /*! @@ -33,27 +32,26 @@ private: double lightL_; double featureG_; size_t boundB_; - - Myself() { - ratioK_ = 0.03; - thresholdR_ = 0.001; - sizeW_ = 2.0; - noiseN_ = 3.0; - lightL_ = 30.0; - featureG_ = 3.0; - boundB_ = 10u; + + Myself(): + ratioK_(0.03), + thresholdR_(0.001), + sizeW_(2.0), + noiseN_(3.0), + lightL_(30.0), + featureG_(3.0), + boundB_(10u) { } - ~Myself() { + Myself(Myself const& m): + ratioK_(m.ratioK_), + thresholdR_(m.thresholdR_), + sizeW_(m.sizeW_), + noiseN_(m.noiseN_), + lightL_(m.lightL_), + featureG_(m.featureG_), + boundB_(m.boundB_){ } - Myself& copyFrom(Myself const& b) { - ratioK_ = b.ratioK_ ; - thresholdR_ = b.thresholdR_ ; - sizeW_ = b.sizeW_ ; - noiseN_ = b.noiseN_ ; - lightL_ = b.lightL_ ; - featureG_ = b.featureG_ ; - boundB_ = b.boundB_ ; - return *this; + ~Myself() { } }; @@ -62,19 +60,11 @@ public: typedef FeaturePoint<double, double> MyFeaturePoint; typedef std::vector<MyFeaturePoint> MyFeaturePoints; //! @brief constructor 使用預設參數 - FPD_Harris(): self(true) { - self()->ratioK_ = 0.03; - self()->thresholdR_ = 0.001; - self()->sizeW_ = 2.0; - self()->noiseN_ = 3.0; - self()->lightL_ = 30.0; - self()->featureG_ = 3.0; - self()->boundB_ = 10u; + FPD_Harris(): self() { } //! @brief constructor 參數複製自另一個 FeaturePointsDetector_Harris - FPD_Harris(FPD_Harris const& fps): self(false) { - self().copyFrom(fps.self); + FPD_Harris(FPD_Harris const& fps): self(fps.self, Self<Myself>::COPY_FROM) { } //! @brief 解構子 @@ -178,9 +168,11 @@ public: MyFeaturePoints detect(Bitmap<Pixel> const& bmp) const { Bitmap<Pixel> input = bmp; + // gradiance Bitmap<Pixel> input_gx(input.gradianceX(0, self->noiseN_)); Bitmap<Pixel> input_gy(input.gradianceY(self->noiseN_, 0)); + // get Matrix I for each pixel Bitmap<double> Ixx(input.height(), input.width(), 0.0); Bitmap<double> Iyy(input.height(), input.width(), 0.0); Bitmap<double> Ixy(input.height(), input.width(), 0.0); @@ -194,10 +186,12 @@ public: } } + // blur Ixx.gaussianed(self->sizeW_, self->sizeW_); Iyy.gaussianed(self->sizeW_, self->sizeW_); Ixy.gaussianed(self->sizeW_, self->sizeW_); + // filter too flat or on edge Bitmap<double> R(input.height(), input.width(), 0.0); Bitmap<bool> good(input.height(), input.width(), false); ssize_t b = self->boundB_; @@ -211,6 +205,7 @@ public: } } + // find union neighbor DisjointSet dsj(input.size()); ssize_t dy[2] = {0, 1}; ssize_t dx[2] = {1, 0}; @@ -227,6 +222,7 @@ public: } } + // find local maximum std::vector<size_t> max_i(input.size()); for (size_t i = 0, I = input.size(); i < I; i++) { max_i[i] = i; @@ -239,6 +235,7 @@ public: } } + // blur before get description input.gaussianed(self->featureG_, self->featureG_); MyFeaturePoints ret; @@ -253,7 +250,7 @@ public: } ssize_t dx[4] = {1, 0, -1, 0}; ssize_t dy[4] = {0, 1, 0, -1}; - std::vector<double> desc; + std::vector<double> desc; // description for (ssize_t d = 1; d <= (ssize_t)self->boundB_; d++) { std::vector<double> light; size_t max_id = 0; diff --git a/meowpp/gra/FeaturePointsMatch.h b/meowpp/gra/FeaturePointsMatch.h index 8b05632..ffdbe53 100644 --- a/meowpp/gra/FeaturePointsMatch.h +++ b/meowpp/gra/FeaturePointsMatch.h @@ -3,32 +3,15 @@ #include "FeaturePoint.h" +#include "../utility.h" #include "../oo/ObjBase.h" -#include <utility> #include <cstdlib> namespace meow { -struct FeaturePointIndexPair { - std::pair<size_t, size_t> from; - std::pair<size_t, size_t> to; - - FeaturePointIndexPair() { - } - FeaturePointIndexPair(size_t ff, size_t fs, - size_t tf, size_t ts) { - from.first = ff; - from.second = fs; - to.first = tf; - to.second = ts; - } - bool operator==(FeaturePointIndexPair const& p) const { - return (from == p.from && to == p.to); - } -}; - -typedef std::vector<FeaturePointIndexPair> FeaturePointIndexPairs; +typedef PairToPair<size_t, size_t, size_t, size_t> FeaturePointIndexPair ; +typedef std::vector<FeaturePointIndexPair> FeaturePointIndexPairs; template<class Scalar, class Description> class FeaturePointsMatch: public ObjBase { @@ -58,6 +41,6 @@ public: FeaturePointss const& fpss) const = 0; }; -} +} // meow #endif // gra_FeaturePointsMatch_H__ diff --git a/meowpp/gra/FeaturePointsMatch_K_Match.h b/meowpp/gra/FeaturePointsMatch_K_Match.h index ca47d27..f1fff12 100644 --- a/meowpp/gra/FeaturePointsMatch_K_Match.h +++ b/meowpp/gra/FeaturePointsMatch_K_Match.h @@ -1,13 +1,10 @@ #ifndef gra_FeaturePointsMatch_K_Match_H__ #define gra_FeaturePointsMatch_K_Match_H__ -#include "../dsa/VP_Tree.h" - #include "FeaturePointsMatch.h" #include "../Self.h" - - +#include "../dsa/VP_Tree.h" #include "../oo/ObjBase.h" #include <cstdlib> @@ -19,20 +16,20 @@ class FeaturePointsMatch_K_Match: public FeaturePointsMatch<Scalar, Description> { # define FPMKM FeaturePointsMatch_K_Match public: - typedef std::vector<FeaturePoint<Scalar, Description> > FeaturePoints; + typedef std::vector<FeaturePoint<Scalar, Description> > FeaturePoints ; typedef std::vector<FeaturePoints > FeaturePointss; private: struct Node { - size_t id_; - size_t index_; - FeaturePointss const* ptr_; + size_t id_; + size_t index_; + FeaturePointss const* ptr_; Node() { } Node(Node const& nd) { - id_ = nd.id_; + id_ = nd. id_; index_ = nd.index_; - ptr_ = nd.ptr_; + ptr_ = nd. ptr_; } Node(size_t id, size_t index, FeaturePointss const* ptr) { id_ = id; @@ -48,30 +45,30 @@ private: return (*ptr_)[id_][index_][id]; } }; + struct Myself { size_t k_; Myself() { k_ = 1; } - ~Myself() { + Myself(size_t k): k_(k) { } - Myself& copyFrom(Myself const& m) { - k_ = m.k_; - return *this; + Myself(Myself const& m): k_(m.k_) { + } + ~Myself() { } }; Self<Myself> const self; public: - FPMKM(): self(true) { + FPMKM(): self() { } - FPMKM(FPMKM const& m): self(false) { + FPMKM(FPMKM const& m): self(m.self, Self<Myself>::COPY_FROM) { self().copyFrom(m.self); } - FPMKM(size_t k): self(true) { - self()->k_ = k; + FPMKM(size_t k): self(Myself(k)) { } ~FPMKM() { @@ -175,8 +172,7 @@ public: } char const* ctype() const { - static char const* ptr = typeid(*this).name(); - return ptr; + return typeid(*this).name(); } std::string type() const { @@ -185,6 +181,6 @@ public: # undef FPMKM }; -} +} // meow #endif // gra_FeaturePointsMatch_K_Match_H__ diff --git a/meowpp/gra/IdentityPoints.h b/meowpp/gra/IdentityPoints.h index c33eb55..1646bf7 100644 --- a/meowpp/gra/IdentityPoints.h +++ b/meowpp/gra/IdentityPoints.h @@ -2,12 +2,11 @@ #define gra_IdentityPoints_H__ #include "../Self.h" - #include "../math/Vector.h" - #include "../oo/ObjBase.h" #include <map> +#include <set> #include <cstdlib> @@ -24,45 +23,42 @@ public: typedef typename std::map<ID, Vector<Scalar> > IdentityPointsMap; typedef typename IdentityPointsMap:: iterator IdentityPointsMapIter; typedef typename IdentityPointsMap::const_iterator IdentityPointsMapIterK; - + private: struct Myself { IdentityPointsMap points_; size_t dimension_; - + Myself() { dimension_ = 1; } - ~Myself() { + Myself(Myself const& m): points_(m.points_), dimension_(m.dimension_) { } - Myself& copyFrom(Myself const& b) { - points_ = b.points_; - dimension_ = b.dimension_; - return *this; + ~Myself() { } }; - + Self<Myself> const self; public: /*! * @brief constructor */ - IdentityPoints(): self(true) { + IdentityPoints(): self() { } - + /*! * @brief constructor, 並且複製資料 */ - IdentityPoints(IdentityPoints const& b): self(false) { - copyFrom(b); + IdentityPoints(IdentityPoints const& b): + self(b.self, Self<Myself>::COPY_FROM) { } - + /*! * @brief destructor */ ~IdentityPoints() { } - + /*! * @brief 複製資料 */ @@ -70,7 +66,7 @@ public: self().copyFrom(b.self); return *this; } - + /*! * @brief 參照 */ @@ -78,42 +74,42 @@ public: self().referenceFrom(b.self); return *this; } - + /*! * @brief 清除一切identity points */ void clear() { self()->points_.clear(); } - + /*! * @brief 回傳有幾個identity points */ size_t size() const { return self->points_.size(); } - + /*! * @brief 回傳是否沒有identity points */ bool empty() const { return (size() == 0u); } - + /*! * @brief 檢查某id是否有使用 */ bool exist(ID const& id) const { return (self->points_.find(id) != self->points_.end()); } - + /*! * @brief 回傳dimension */ size_t dimension() const { return self->dimension_; } - + /*! * @brief 設定dimension, 並且清空資料 */ @@ -122,7 +118,7 @@ public: clear(); return dimension(); } - + /*! * @brief 設定dimension, 並且針對每個identity point指定重設dimension */ @@ -134,14 +130,14 @@ public: } return dimension(); } - + /*! * @brief 取得所有identity points */ IdentityPointsMap const& identityPoints() const { return self->points_; } - + /*! * @brief 設定所有identity points */ @@ -149,7 +145,7 @@ public: clear(); return identityPointsAdd(points); } - + /*! * @brief 加入identity Points */ @@ -159,7 +155,7 @@ public: } return identityPoints(); } - + /*! * @brief 移除identity Points */ @@ -170,14 +166,14 @@ public: } return identityPoints(); } - + /*! * @brief 取得一個identity point */ Vector<Scalar> identityPoint(ID const& id) const { return (exist(id) ? self->points_.find(id)->second : Vector<Scalar>()); } - + /*! * @brief 修改一個identity point */ @@ -187,7 +183,7 @@ public: } return identityPoint(id); } - + /*! * @brief 新增一個identity point */ @@ -197,42 +193,99 @@ public: } return identityPoint(id); } - + /*! * @brief 刪除一個identity point */ void identityPointDel(ID const& id) { self()->points_.erase(id); } - + /*! * @brief 取得一個identity point, non-constant reference */ Vector<Scalar>& identityPointGet(ID const& id) { return self()->points_[id]; } - + /*! * @brief same as \c copyFrom(b) */ IdentityPoints& operator=(IdentityPoints const& b) { return copyFrom(b); } - + /*! @brief 將資料寫入檔案 * * @note 未完成 */ bool write(FILE* f, bool bin, unsigned int fg) const { - return false; + if (bin) { + long dim, ct; + if (fwrite(&(dim = dimension()), sizeof(dim), 1, f) < 1) return false; + if (fwrite(&(ct = size()), sizeof(ct), 1, f) < 1) return false; + for (IdentityPointsMapIterK + it = identityPoints().begin(), ed = identityPoints().end(); + it != ed; ++it) { + double tmp; + if (fwrite(&(tmp = it->first), sizeof(tmp), 1, f) < 1) return false; + for (long i = 0; i < dim; ++i) { + if (fwrite(&(tmp = it->second(i)), sizeof(tmp), 1, f) < 1) + return false; + } + } + } + else { + if (fprintf(f, "%ld %lu\n", dimension(), size()) < 1) return false; + for (IdentityPointsMapIterK + it = identityPoints().begin(), ed = identityPoints().end(); + it != ed; ++it) { + if (fprintf(f, "%f ", (double)it->first) < 1) return false; + for (long i = 0, I = dimension(); i < I; ++i) { + if (fprintf(f, "%f ", (double)it->second(i)) < 1) return false; + } + fprintf(f, "\n"); + } + } + return true; } - + /*! @brief 將資料讀入 * * @note 未完成 */ bool read(FILE* f, bool bin, unsigned int fg) { - return false; + long dim, ct; + if (bin) { + if (fread(&dim, sizeof(dim), 1, f) < 1) return false; + dimension(dim); + if (fread(&ct, sizeof(ct), 1, f) < 1) return false; + double id, tt; + Vector<Scalar> tmp(dim, 0); + for (int i = 0; i < ct; ++i) { + if (fread(&id, sizeof(id), 1, f) < 1) return false; + for (size_t j = 0, J = dim; j < J; ++j) { + if (fread(&tt, sizeof(tt), 1, f) < 1) return false; + tmp.entry(j, tt); + } + identityPointAdd((ID)id, tmp); + } + } + else { + if (fscanf(f, "%ld %ld", &dim, &ct) < 2) return false; + dimension(dim); + double id, tt; + Vector<Scalar> tmp(dim, 0); + for (int i = 0; i < ct; ++i) { + if (fscanf(f, "%lf", &id) < 1) return false; + for (int j = 0, J = dim; j < J; ++j) { + if (fscanf(f, "%lf", &tt) < 1) return false; + tmp.entry(j, tt); + } + identityPointAdd((ID)id, tmp); + } + } + return true; } /*! @brief new一個自己 @@ -242,7 +295,7 @@ public: ObjBase* create() const { return new IdentityPoints(); } - + /*! @brief 複製資料 * * 輸入型別是 \c ObjBase \c const* @@ -255,16 +308,15 @@ public: ObjBase* copyFrom(ObjBase const* b) { return &(copyFrom(*(IdentityPoints*)b)); } - + /*! @brief 回傳class的type * * @return \c char \c const\c * 形式的typename */ - char const* ctype() const{ - static char const* ptr = typeid(*this).name(); - return ptr; + char const* ctype() const { + return typeid(*this).name(); } - + /*! @brief 回傳class的type * * @return \c std::string 形式的typename diff --git a/meowpp/gra/Photo.h b/meowpp/gra/Photo.h index 15768aa..1837727 100644 --- a/meowpp/gra/Photo.h +++ b/meowpp/gra/Photo.h @@ -1,8 +1,11 @@ #ifndef gra_Photo_H__ #define gra_Photo_H__ +#include "Bitmap.h" + #include "../Self.h" +#include "../geo/Vectors.h" #include "../math/utility.h" #include "../math/Matrix.h" #include "../math/Transformations.h" @@ -20,7 +23,7 @@ namespace meow { /*! * @brief 底片 * - * 基本上就是一個 \c Photo 加上 \c focal + * 基本上就是一個 \c Bitmap 加上 \c focal * * @author cat_leopard */ @@ -33,13 +36,9 @@ private: PhotoProjection<double> proj_; Myself(): proj_(3) { } - ~Myself() { + Myself(Myself const& b): bmp_(b.bmp_), c_(b.c_), proj_(b.proj_) { } - Myself& copyFrom(Myself const& b) { - bmp_ .copyFrom(b. bmp_); - c_ .copyFrom(b. c_); - proj_.copyFrom(b.proj_); - return *this; + ~Myself() { } }; @@ -57,7 +56,7 @@ public: * * focal 預設為 1 */ - Photo(): self(true) { + Photo(): self() { self()->proj_.focal(1.0); } @@ -68,8 +67,7 @@ public: * * @param [in] b 資料來源 */ - Photo(Photo const& b): self(false) { - copyFrom(b); + Photo(Photo const& b): self(b.self, Self<Myself>::COPY_FROM) { } /*! @@ -79,7 +77,7 @@ public: * * @param [in] bmp 給定的圖片 */ - Photo(Bitmap<Pixel> const& bmp): self(true) { + Photo(Bitmap<Pixel> const& bmp): self() { reset(bmp); } @@ -91,7 +89,7 @@ public: * @param [in] bmp 給定的圖片 * @param [in] f 給定的焦距 */ - Photo(Bitmap<Pixel> const& bmp, double f): self(true) { + Photo(Bitmap<Pixel> const& bmp, double f): self() { reset(bmp, f); } @@ -104,8 +102,7 @@ public: * @param [in] f 給定的焦距 * @param [in] c 中心點作標 */ - Photo(Bitmap<Pixel> const& bmp, double f, Vector2D<double> const& c): - self(true) { + Photo(Bitmap<Pixel> const& bmp, double f, Vector2D<double> const& c): self() { reset(bmp, f, c); } @@ -196,7 +193,7 @@ public: * @return 新的 \c bitmap */ Bitmap<Pixel> const& bitmap(Bitmap<Pixel> const& bmp) { - self()->bmp_ = bmp; + self()->bmp_.copyFrom(bmp); return bitmap(); } @@ -219,6 +216,23 @@ public: } /*! + * @brief 回傳相應的 photo projection + */ + PhotoProjection<double> projection() const { + return self->proj_; + } + + /*! + * @brief 設定 photo projection + */ + PhotoProjection<double> projection(PhotoProjection<double> const& p) { + if (p.dimension() == 3) { + self()->proj_ = p; + } + return projection(); + } + + /*! * @brief 取得照片中心點底片座標 * * @return 一個二維vector @@ -299,6 +313,7 @@ public: * @return \c true/false */ bool inside(Vector3D<double> const& p) const { + if (p.z() > 0) return false; return inside(Vector2D<double>(self->proj_.transformate(p.matrix()))); } @@ -352,7 +367,18 @@ public: * @note 未完成 */ bool write(FILE* f, bool bin, unsigned int fg) const { - return false; + if (bitmap().write(f, bin, fg) == false) return false; + if (bin) { + double tmp; + if (fwrite(&(tmp = center().x()), sizeof(tmp), 1, f) < 1) return false; + if (fwrite(&(tmp = center().y()), sizeof(tmp), 1, f) < 1) return false; + if (fwrite(&(tmp = focal()), sizeof(tmp), 1, f) < 1) return false; + } + else { + if (fprintf(f, "%f %f\n", center().x(), center().y()) < 2) return false; + if (fprintf(f, "%f\n", focal()) < 1) return false; + } + return true; } /*! @brief 將資料讀入 @@ -360,12 +386,23 @@ public: * @note 未完成 */ bool read(FILE* f, bool bin, unsigned int fg) { - return false; + if (bitmapGet().read(f, bin, fg) == false) return false; + double tmp[3]; + if (bin) { + if (fread(tmp, sizeof(double), 3, f) < 3) return false; + } + else { + if (fscanf(f, "%lf %lf %lf", tmp + 0, tmp + 1, tmp + 2) < 3) return false; + } + centerGet().x(tmp[0]); + centerGet().y(tmp[1]); + focal(tmp[2]); + return true; } /*! @brief new一個自己 * - * @return 一個new出來的Bitmap<Pixel> + * @return 一個new出來的Photo<Pixel> */ ObjBase* create() const { return new Photo(); @@ -389,8 +426,7 @@ public: * @return \c char \c const\c * 形式的typename */ char const* ctype() const{ - static char const* ptr = typeid(*this).name(); - return ptr; + return typeid(*this).name(); } /*! @brief 回傳class的type @@ -402,6 +438,6 @@ public: } }; -} +} // meow #endif // gra_Photo_H__ diff --git a/meowpp/gra/WatchBall.h b/meowpp/gra/WatchBall.h index c72e2a5..f3d2044 100644 --- a/meowpp/gra/WatchBall.h +++ b/meowpp/gra/WatchBall.h @@ -43,14 +43,13 @@ public: /*! * @brief constructor */ - WatchBall(): self(true) { + WatchBall(): self() { } /*! * @brief copy constructor */ - WatchBall(WatchBall const& b): self(false) { - copyFrom(b); + WatchBall(WatchBall const& b): self(b.self, Self<Myself>::COPY_FROM) { } /*! @@ -176,12 +175,12 @@ public: Bitmap<Pixel> ret(height, width, Pixel(0)); for (size_t i = 0; i < height; ++i) { for (size_t j = 0; j < width; ++j) { - double theta = (1.0 * j / width - 0.5) * 2 * PI; + double theta = (1.0 * j / width - 0.5) * 2 * PI; double phi = asin(-(1.0 * i / height - 0.5) * 2.0); ret.pixel(i, j, color(Vector3D<double>( - sin(-theta) * cos(phi), + sin(theta) * cos(phi), sin(phi), - cos(-theta) * cos(phi) + -cos(theta) * cos(phi) ))); } } |