diff options
author | mbansal <mayank.bansal@sri.com> | 2011-09-13 15:22:33 -0400 |
---|---|---|
committer | Wei-Ta Chen <weita@google.com> | 2011-09-15 11:53:14 -0700 |
commit | 6c5b20113ba9f91352f32e5a53df66aec0ec761a (patch) | |
tree | aa03e0dd7b4dc41feb0a8fdbf36878a44d9352bd /jni/feature_mos | |
parent | 1e35ce08ae70575c6127c606dd4ba28f6ff2add1 (diff) | |
download | LegacyCamera-6c5b20113ba9f91352f32e5a53df66aec0ec761a.zip LegacyCamera-6c5b20113ba9f91352f32e5a53df66aec0ec761a.tar.gz LegacyCamera-6c5b20113ba9f91352f32e5a53df66aec0ec761a.tar.bz2 |
Updated cropping algorithm to get rid of gray pixels around the mosaic border.
1) Added documentation to the ComputeBlendParameters(...) function.
Bug: 5279291
Change-Id: Iad1c9388ec939c2969b550ee3c194c3d191eb492
Diffstat (limited to 'jni/feature_mos')
-rw-r--r-- | jni/feature_mos/src/mosaic/Blend.cpp | 186 |
1 files changed, 102 insertions, 84 deletions
diff --git a/jni/feature_mos/src/mosaic/Blend.cpp b/jni/feature_mos/src/mosaic/Blend.cpp index 6ecd291..6988ace 100644 --- a/jni/feature_mos/src/mosaic/Blend.cpp +++ b/jni/feature_mos/src/mosaic/Blend.cpp @@ -73,6 +73,9 @@ int Blend::initialize(int blendingType, int frame_width, int frame_height) return BLEND_RET_OK; } +inline double max(double a, double b) { return a > b ? a : b; } +inline double min(double a, double b) { return a < b ? a : b; } + void Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size) { // Unwarp this frame and Warp the others to match @@ -113,6 +116,8 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, return BLEND_RET_ERROR_MEMORY; } + // Bounding rectangle (real numbers) of the final mosaic computed by projecting + // each input frame into the mosaic coordinate system. BlendRect global_rect; global_rect.lft = global_rect.bot = 2e30; // min values @@ -123,6 +128,10 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, double z, x0, y0, x1, y1, x2, y2, x3, y3; + // Corners of the first and last frames in mosaic coordinate system + double xf[4] = {0.0, 0.0, 0.0, 0.0}; + double xl[4] = {0.0, 0.0, 0.0, 0.0}; + // Determine the extents of the final mosaic CSite *csite = m_AllSites ; for(int mfit = 0; mfit < frames_size; mfit++) @@ -140,6 +149,22 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, FrameToMosaic(mb->trs, mb->width-1.0, mb->height-1.0, x2, y2); FrameToMosaic(mb->trs, mb->width-1.0, 0.0, x3, y3); + if(mfit == 0) + { + xf[0] = x0; + xf[1] = x1; + xf[2] = x3; + xf[3] = x2; + } + + if(mfit==frames_size-1) + { + xl[0] = x0; + xl[1] = x1; + xl[2] = x3; + xl[3] = x2; + } + // Compute the centroid of the warped region FindQuadCentroid(x0, y0, x1, y1, x2, y2, x3, y3, csite->getVCenter().x, csite->getVCenter().y); @@ -148,6 +173,9 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, } // Get origin and sizes + + // Bounding rectangle (int numbers) of the final mosaic computed by projecting + // each input frame into the mosaic coordinate system. MosaicRect fullRect; fullRect.left = (int) floor(global_rect.lft); // min-x @@ -157,6 +185,20 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, Mwidth = (unsigned short) (fullRect.right - fullRect.left + 1); Mheight = (unsigned short) (fullRect.bottom - fullRect.top + 1); + int xlt, xrt; + + if(frames[0]->trs[0][2] < frames[frames_size-1]->trs[0][2]) //left->right mosaic + { + xlt = max(xf[0],xf[1]) - fullRect.left; + xrt = min(xl[2],xl[3]) - fullRect.left; + } + else + { + xlt = max(xl[0],xl[1]) - fullRect.left; + xrt = min(xf[2],xf[3]) - fullRect.left; + } + + // Make sure image width is multiple of 4 Mwidth = (unsigned short) ((Mwidth + 3) & ~3); Mheight = (unsigned short) ((Mheight + 3) & ~3); // Round up. @@ -184,8 +226,13 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size, int n = m_Triangulator.triangulate(&edge, numCenters, width, height); m_Triangulator.linkNeighbors(edge, n, numCenters); + // Bounding rectangle that determines the positioning of the rectangle that is + // cropped out of the computed mosaic to get rid of the gray borders. MosaicRect cropping_rect; + cropping_rect.left = xlt; + cropping_rect.right = xrt; + // Do merging and blending : ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect, cropping_rect, progress, cancelComputation); @@ -397,10 +444,14 @@ int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) int cx = (int)imgMos.Y.width/2; int cy = (int)imgMos.Y.height/2; - cropping_rect.left = 0; - cropping_rect.right = imgMos.Y.width-1; - cropping_rect.top = 0; - cropping_rect.bottom = imgMos.Y.height-1; + // 2D boolean array that contains true wherever the mosaic image data is + // invalid (i.e. in the gray border). + bool **b = new bool*[imgMos.Y.height]; + + for(int j=0; j<imgMos.Y.height; j++) + { + b[j] = new bool[imgMos.Y.width]; + } // Copy the resulting image into the full image using the mask int i, j; @@ -415,7 +466,7 @@ int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) muimg = m_pMosaicUPyr->ptr[j]; mvimg = m_pMosaicVPyr->ptr[j]; - for (i = imgMos.Y.width; i--;) + for (i = 0; i<imgMos.Y.width; i++) { // A final mask was set up previously, // if the value is zero skip it, otherwise replace it. @@ -436,10 +487,16 @@ int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) else if (value > 255) value = 255; *vimg = (unsigned char) value; + b[j][i] = false; + } else { // set border color in here *yimg = (unsigned char) 96; + *uimg = (unsigned char) 128; + *vimg = (unsigned char) 128; + + b[j][i] = true; } yimg++; @@ -451,102 +508,48 @@ int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) } } - yimg = imgMos.Y.ptr[0]; - uimg = imgMos.U.ptr[0]; - vimg = imgMos.V.ptr[0]; - - int mincol = 0; - int maxcol = imgMos.Y.width-1; - - const int MIN_X_FS = width*1/8; - const int MAX_X_FS = imgMos.Y.width - width*1/8; - + //Scan through each row and increment top if the row contains any gray for (j = 0; j < imgMos.Y.height; j++) { - int minx = MIN_X_FS; - int maxx = MAX_X_FS; - - for (i = 0; i < imgMos.Y.width; i++) + for (i = cropping_rect.left; i < cropping_rect.right; i++) { - if(*yimg == 96 && *uimg == 128 && *vimg == 128) - { - } - else + if (b[j][i]) { - if(i<minx) - minx = i; - if(i>maxx) - maxx = i; + break; // to next row } - - yimg++; - uimg++; - vimg++; } - // If we never touched the values, reset them to the image limits - if(minx == MIN_X_FS) - minx = 0; - if(maxx == MAX_X_FS) - maxx = imgMos.Y.width-1; - - if(minx>mincol) - mincol = minx; - if(maxx<maxcol) - maxcol = maxx; + if (i == cropping_rect.right) //no gray pixel in this row! + { + cropping_rect.top = j; + break; + } } - cropping_rect.left = mincol; - cropping_rect.right = maxcol; - - // Crop rows - yimg = imgMos.Y.ptr[0]; - uimg = imgMos.U.ptr[0]; - vimg = imgMos.V.ptr[0]; - - int minrow = 0; - int maxrow = imgMos.Y.height-1; - - const int MIN_Y_FS = height*1/8; - const int MAX_Y_FS = imgMos.Y.height - height*1/8; - - for (i = 0; i < imgMos.Y.width; i++) + //Scan through each row and decrement bottom if the row contains any gray + for (j = imgMos.Y.height-1; j >= 0; j--) { - int miny = MIN_Y_FS; - int maxy = MAX_Y_FS; - - for (j = 0; j < imgMos.Y.height; j++) + for (i = cropping_rect.left; i < cropping_rect.right; i++) { - if(*yimg == 96 && *uimg == 128 && *vimg == 128) + if (b[j][i]) { + break; // to next row } - else - { - if(j<miny) - miny = j; - if(j>maxy) - maxy = j; - } - - yimg++; - uimg++; - vimg++; } - // If we never touched the values, reset them to the image limits - if(miny == MIN_Y_FS) - miny = 0; - if(maxy == MAX_Y_FS) - maxy = imgMos.Y.height-1; + if (i == cropping_rect.right) //no gray pixel in this row! + { + cropping_rect.bottom = j; + break; + } + } - if(miny>minrow) - minrow = miny; - if(maxy<maxrow) - maxrow = maxy; + for(int j=0; j<imgMos.Y.height; j++) + { + delete b[j]; } - cropping_rect.top = minrow; - cropping_rect.bottom = maxrow; + delete b; return BLEND_RET_OK; } @@ -908,6 +911,8 @@ void Blend::FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360) { + // For FULL and PAN modes, we do not unwarp the mosaic into a rectangular coordinate system + // and so we set the theta to 0 and return. if (m_wb.blendingType != BLEND_TYPE_CYLPAN && m_wb.blendingType != BLEND_TYPE_HORZ) { m_wb.theta = 0.0; @@ -932,6 +937,9 @@ void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is double arcLength, lastTheta; m_wb.theta = lastTheta = arcLength = 0.0; + + // Step through all the frames to compute the total arc-length of the cone + // swept while capturing the mosaic (in the original conical coordinate system). for (int i = 0; i < frames_size; i++) { mb = frames[i]; @@ -941,18 +949,25 @@ void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is currY = ProjY(mb->trs, midX, midY, z, 1.0); double deltaX = currX - prevX; double deltaY = currY - prevY; + + // The arcLength is computed by summing the lengths of the chords + // connecting the pairwise projected image centers of the input image frames. arcLength += sqrt(deltaY * deltaY + deltaX * deltaX); + if (!is360) { double thisTheta = asin(mb->trs[1][0]); m_wb.theta += thisTheta - lastTheta; lastTheta = thisTheta; } + prevX = currX; prevY = currY; } - // In case of BMP output, stretch this to end at the proper alignment + // Stretch this to end at the proper alignment i.e. the width of the + // rectangle is determined by the arcLength computed above and the cone + // sector angle is determined using the rotation of the last frame. m_wb.width = arcLength; if (is360) m_wb.theta = asin(last->trs[1][0]); @@ -961,6 +976,8 @@ void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is { double dx = prevX - firstX; double dy = prevY - firstY; + + // If the mosaic was captured by sweeping horizontally if (abs(lxpos - fxpos) > abs(lypos - fypos)) { m_wb.horizontal = 1; @@ -982,6 +999,7 @@ void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is if (m_wb.horizontal) { // Horizontal strip + // m_wb.x,y record the origin of the rectangle coordinate system. if (is360) m_wb.x = firstX; else { |