diff options
author | mbansal <mayank.bansal@sri.com> | 2011-09-21 14:19:17 -0400 |
---|---|---|
committer | Wei-Ta Chen <weita@google.com> | 2011-09-22 16:59:27 -0700 |
commit | dd28e1cc00373c02adf88dff878dbbe5d8be9e59 (patch) | |
tree | 3d51207c4c12c5b9067c71e7b29d00d1732e0a1f /jni/feature_mos | |
parent | b2563be21745e389218655625f42802edc911088 (diff) | |
download | LegacyCamera-dd28e1cc00373c02adf88dff878dbbe5d8be9e59.zip LegacyCamera-dd28e1cc00373c02adf88dff878dbbe5d8be9e59.tar.gz LegacyCamera-dd28e1cc00373c02adf88dff878dbbe5d8be9e59.tar.bz2 |
Updates to handle textureless scenes during capture.
1) Starts stitching only when the camera sees a textured scene at the beginning.
2) If a texturess scene is encountered in the middle of a capture, the stitching continues with the intermediate frames translated using the pan velocity estimate.
3) Added more error codes and percolated them up to the java layer.
4) Fix a build error in Mosaic::addFrame() and added comments.
5) Update the javadoc in Mosaic.java to reflect the new returning codes.
Change-Id: I7727ace615ece22adefe313a19ac2cbe8c8d21a8
Diffstat (limited to 'jni/feature_mos')
-rw-r--r-- | jni/feature_mos/src/mosaic/AlignFeatures.cpp | 119 | ||||
-rw-r--r-- | jni/feature_mos/src/mosaic/AlignFeatures.h | 16 | ||||
-rw-r--r-- | jni/feature_mos/src/mosaic/Mosaic.cpp | 42 | ||||
-rw-r--r-- | jni/feature_mos/src/mosaic/Mosaic.h | 2 |
4 files changed, 139 insertions, 40 deletions
diff --git a/jni/feature_mos/src/mosaic/AlignFeatures.cpp b/jni/feature_mos/src/mosaic/AlignFeatures.cpp index a181dd8..aeabf8f 100644 --- a/jni/feature_mos/src/mosaic/AlignFeatures.cpp +++ b/jni/feature_mos/src/mosaic/AlignFeatures.cpp @@ -26,12 +26,18 @@ #include "trsMatrix.h" #include "MatrixUtils.h" #include "AlignFeatures.h" +#include "Log.h" + +#define LOG_TAG "AlignFeatures" Align::Align() { width = height = 0; frame_number = 0; + num_frames_captured = 0; + reference_frame_index = 0; db_Identity3x3(Hcurr); + db_Identity3x3(Hprev); } Align::~Align() @@ -54,8 +60,8 @@ int Align::initialize(int width, int height, bool _quarter_res, float _thresh_st int nrsamples = DB_DEFAULT_NR_SAMPLES; double scale = DB_POINT_STANDARDDEV; int chunk_size = DB_DEFAULT_CHUNK_SIZE; - int nrhorz = 20; // 1280/32 = 40 - int nrvert = 12; // 720/30 = 24 + int nrhorz = width/48; // Empirically determined number of horizontal + int nrvert = height/60; // and vertical buckets for harris corner detection. bool linear_polish = false; unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD; @@ -66,10 +72,17 @@ int Align::initialize(int width, int height, bool _quarter_res, float _thresh_st thresh_still = _thresh_still; frame_number = 0; + num_frames_captured = 0; + reference_frame_index = 0; db_Identity3x3(Hcurr); + db_Identity3x3(Hprev); + if (!reg.Initialized()) { - reg.Init(width,height,motion_model_type,20,linear_polish,quarter_res,scale,reference_update_period, false, 0, nrsamples,chunk_size,nr_corners,max_disparity,use_smaller_matching_window, nrhorz, nrvert); + reg.Init(width, height, motion_model_type, 20, linear_polish, quarter_res, + scale, reference_update_period, false, 0, nrsamples, chunk_size, + nr_corners, max_disparity, use_smaller_matching_window, + nrhorz, nrvert); } this->width = width; this->height = height; @@ -90,47 +103,90 @@ int Align::addFrameRGB(ImageType imageRGB) int Align::addFrame(ImageType imageGray_) { - // compute the homography: - double Hinv[9]; - double Hinv33[3][3]; - double Hprev33[3][3]; - double Hcurr33[3][3]; + int ret_code = ALIGN_RET_OK; // Obtain a vector of pointers to rows in image and pass in to dbreg ImageType *m_rows = ImageUtils::imageTypeToRowPointers(imageGray_, width, height); - reg.AddFrame(m_rows, Hcurr); + if (frame_number == 0) + { + reg.AddFrame(m_rows, Hcurr, true); // Force this to be a reference frame + int num_corner_ref = reg.GetNrRefCorners(); + + if (num_corner_ref < MIN_NR_REF_CORNERS) + { + return ALIGN_RET_LOW_TEXTURE; + } + } + else + { + reg.AddFrame(m_rows, Hcurr, false); + } + + // Average translation per frame = + // [Translation from Frame0 to Frame(n-1)] / [(n-1)] + average_tx_per_frame = (num_frames_captured < 2) ? 0.0 : + Hprev[2] / (num_frames_captured - 1); + + // Increment the captured frame counter if we already have a reference frame + num_frames_captured++; if (frame_number != 0) { + int num_inliers = reg.GetNrInliers(); + + if(num_inliers < MIN_NR_INLIERS) + { + ret_code = ALIGN_RET_FEW_INLIERS; + + Hcurr[0] = 1.0; + Hcurr[1] = 0.0; + // Set this as the average per frame translation taking into acccount + // the separation of the current frame from the reference frame... + Hcurr[2] = -average_tx_per_frame * + (num_frames_captured - reference_frame_index); + Hcurr[3] = 0.0; + Hcurr[4] = 1.0; + Hcurr[5] = 0.0; + Hcurr[6] = 0.0; + Hcurr[7] = 0.0; + Hcurr[8] = 1.0; + } if(fabs(Hcurr[2])<thresh_still && fabs(Hcurr[5])<thresh_still) // Still camera { return ALIGN_RET_ERROR; } + // compute the homography: + double Hinv33[3][3]; + double Hprev33[3][3]; + double Hcurr33[3][3]; + // Invert and multiple with previous transformation Matrix33::convert9to33(Hcurr33, Hcurr); Matrix33::convert9to33(Hprev33, Hprev); - //NormalizeProjMat(Hcurr33); normProjMat33d(Hcurr33); inv33d(Hcurr33, Hinv33); mult33d(Hcurr33, Hprev33, Hinv33); normProjMat33d(Hcurr33); - Matrix9::convert33to9(Hcurr, Hcurr33); + Matrix9::convert33to9(Hprev, Hcurr33); + // Since we have already factored the current transformation + // into Hprev, we can reset the Hcurr to identity + db_Identity3x3(Hcurr); + // Update the reference frame to be the current frame reg.UpdateReference(m_rows,quarter_res,false); + + // Update the reference frame index + reference_frame_index = num_frames_captured; } frame_number++; - // Copy curr to prev - memcpy(Happly, Hcurr, sizeof(double)*9); - memcpy(Hprev, Hcurr, sizeof(double)*9); - - return ALIGN_RET_OK; + return ret_code; } // Get current transformation @@ -138,11 +194,38 @@ int Align::getLastTRS(double trs[3][3]) { if (frame_number < 1) { - fprintf(stderr, "Error: Align::getLastTRS called before a frame was processed\n"); + trs[0][0] = 1.0; + trs[0][1] = 0.0; + trs[0][2] = 0.0; + trs[1][0] = 0.0; + trs[1][1] = 1.0; + trs[1][2] = 0.0; + trs[2][0] = 0.0; + trs[2][1] = 0.0; + trs[2][2] = 1.0; return ALIGN_RET_ERROR; } - Matrix33::convert9to33(trs, Happly); + // Note that the logic here handles the case, where a frame is not used for + // mosaicing but is captured and used in the preview-rendering. + // For these frames, we don't set Hcurr to identity in AddFrame() and the + // logic here appends their transformation to Hprev to render them with the + // correct transformation. For the frames we do use for mosaicing, we already + // append their Hcurr to Hprev in AddFrame() and then set Hcurr to identity. + + double Hinv33[3][3]; + double Hprev33[3][3]; + double Hcurr33[3][3]; + + Matrix33::convert9to33(Hcurr33, Hcurr); + normProjMat33d(Hcurr33); + inv33d(Hcurr33, Hinv33); + + Matrix33::convert9to33(Hprev33, Hprev); + + mult33d(trs, Hprev33, Hinv33); + normProjMat33d(trs); + return ALIGN_RET_OK; } diff --git a/jni/feature_mos/src/mosaic/AlignFeatures.h b/jni/feature_mos/src/mosaic/AlignFeatures.h index 06be596..19f3905 100644 --- a/jni/feature_mos/src/mosaic/AlignFeatures.h +++ b/jni/feature_mos/src/mosaic/AlignFeatures.h @@ -36,8 +36,10 @@ public: static const int ALIGN_TYPE_PAN = 1; // Return codes + static const int ALIGN_RET_LOW_TEXTURE = -2; static const int ALIGN_RET_ERROR = -1; static const int ALIGN_RET_OK = 0; + static const int ALIGN_RET_FEW_INLIERS = 1; ///// Settings for feature-based alignment // Number of features to use from corner detection @@ -49,6 +51,9 @@ public: // static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE; static const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=1500; // Manual reference frame update so set this to a large number + static const int MIN_NR_REF_CORNERS = 25; + static const int MIN_NR_INLIERS = 10; + Align(); ~Align(); @@ -69,10 +74,13 @@ protected: db_FrameToReferenceRegistration reg; int frame_number; - double Happly[9]; // Homography to apply - double Hcurr[9]; // Homography from last frame - // (right now same as above) - double Hprev[9]; // Homography up until the last frame + + double Hcurr[9]; // Homography from the alignment reference to the frame-t + double Hprev[9]; // Homography from frame-0 to the frame-(t-1) + + int reference_frame_index; // Index of the reference frame from all captured frames + int num_frames_captured; // Total number of frames captured (different from frame_number) + double average_tx_per_frame; // Average pixel translation per captured frame int width,height; diff --git a/jni/feature_mos/src/mosaic/Mosaic.cpp b/jni/feature_mos/src/mosaic/Mosaic.cpp index 9eee2b3..f17c030 100644 --- a/jni/feature_mos/src/mosaic/Mosaic.cpp +++ b/jni/feature_mos/src/mosaic/Mosaic.cpp @@ -135,43 +135,49 @@ int Mosaic::addFrame(ImageType imageYVU) frame->image = imageYVU; - int align_flag = Align::ALIGN_RET_OK; - // Add frame to aligner + int ret = MOSAIC_RET_ERROR; if (aligner != NULL) { // Note aligner takes in RGB images - printf("Adding frame to aligner...\n"); + int align_flag = Align::ALIGN_RET_OK; align_flag = aligner->addFrame(frame->image); aligner->getLastTRS(frame->trs); - printf("Frame width %d,%d\n", frame->width, frame->height); if (frames_size >= max_frames) { - fprintf(stderr, "WARNING: More frames than preallocated, ignoring. Increase maximum number of frames (-f <max_frames>) to avoid this\n"); + LOGV("WARNING: More frames than preallocated, ignoring." + "Increase maximum number of frames (-f <max_frames>) to avoid this"); return MOSAIC_RET_ERROR; } - else if(align_flag == Align::ALIGN_RET_OK) - { - frames_size++; - return MOSAIC_RET_OK; - } - else + + switch (align_flag) { - return MOSAIC_RET_ERROR; + case Align::ALIGN_RET_OK: + frames_size++; + ret = MOSAIC_RET_OK; + break; + case Align::ALIGN_RET_FEW_INLIERS: + frames_size++; + ret = MOSAIC_RET_FEW_INLIERS; + break; + case Align::ALIGN_RET_LOW_TEXTURE: + ret = MOSAIC_RET_LOW_TEXTURE; + break; + case Align::ALIGN_RET_ERROR: + ret = MOSAIC_RET_ERROR; + break; + default: + break; } } - else - { - return MOSAIC_RET_ERROR; - } + + return ret; } int Mosaic::createMosaic(float &progress, bool &cancelComputation) { - printf("Creating mosaic\n"); - if (frames_size <= 0) { // Haven't accepted any frame in aligner. No need to do blending. diff --git a/jni/feature_mos/src/mosaic/Mosaic.h b/jni/feature_mos/src/mosaic/Mosaic.h index 36eafe7..fc6ecd9 100644 --- a/jni/feature_mos/src/mosaic/Mosaic.h +++ b/jni/feature_mos/src/mosaic/Mosaic.h @@ -146,6 +146,8 @@ public: static const int MOSAIC_RET_OK = 1; static const int MOSAIC_RET_ERROR = -1; static const int MOSAIC_RET_CANCELLED = -2; + static const int MOSAIC_RET_LOW_TEXTURE = -3; + static const int MOSAIC_RET_FEW_INLIERS = 2; protected: |