Пример #1
0
/******************* TO DO 4 *********************
 * AccumulateBlend:
 *	INPUT:
 *		img: a new image to be added to acc
 *		acc: portion of the accumulated image where img is to be added
 *		M: translation matrix for calculating a bounding box
 *		blendWidth: width of the blending function (horizontal hat function;
 *	    try other blending functions for extra credit)
 *	OUTPUT:
 *		add a weighted copy of img to the subimage specified in acc
 *		the first 3 band of acc records the weighted sum of pixel colors
 *		the fourth band of acc records the sum of weight
 */
static void AccumulateBlend(CByteImage& img, CFloatImage& acc, CTransform3x3 M, float blendWidth)
{
    /* Compute the bounding box of the image of the image */
    int bb_min_x, bb_min_y, bb_max_x, bb_max_y;
    ImageBoundingBox(img, M, bb_min_x, bb_min_y, bb_max_x, bb_max_y);

	int imgWidth = img.Shape().width;
	int imgHeight = img.Shape().height;

    CTransform3x3 Minv = M.Inverse();

    for (int y = bb_min_y; y <= bb_max_y; y++) {
        for (int x = bb_min_x; x < bb_max_x; x++) {
            /* Check bounds in destination */
            if (x < 0 || x >= acc.Shape().width || 
                y < 0 || y >= acc.Shape().height)
                continue;

            /* Compute source pixel and check bounds in source */
            CVector3 p_dest, p_src;
            p_dest[0] = x;
            p_dest[1] = y;
            p_dest[2] = 1.0;

            p_src = Minv * p_dest;

            float x_src = (float) (p_src[0] / p_src[2]);
            float y_src = (float) (p_src[1] / p_src[2]);

            if (x_src < 0.0 || x_src >= img.Shape().width - 1 ||
                y_src < 0.0 || y_src >= img.Shape().height - 1)
                continue;

            int xf = (int) floor(x_src);
            int yf = (int) floor(y_src);
            int xc = xf + 1;
            int yc = yf + 1;

            /* Skip black pixels */
            if (img.Pixel(xf, yf, 0) == 0x0 && 
                img.Pixel(xf, yf, 1) == 0x0 && 
                img.Pixel(xf, yf, 2) == 0x0)
                continue;

            if (img.Pixel(xc, yf, 0) == 0x0 && 
                img.Pixel(xc, yf, 1) == 0x0 && 
                img.Pixel(xc, yf, 2) == 0x0)
                continue;

            if (img.Pixel(xf, yc, 0) == 0x0 && 
                img.Pixel(xf, yc, 1) == 0x0 && 
                img.Pixel(xf, yc, 2) == 0x0)
                continue;

            if (img.Pixel(xc, yc, 0) == 0x0 && 
                img.Pixel(xc, yc, 1) == 0x0 && 
                img.Pixel(xc, yc, 2) == 0x0)
                continue;

            
            double weight = 1.0;

			// *** BEGIN TODO ***
			// set weight properly
			//(see mosaics lecture slide on "feathering") P455 on notebook
			//Q:How to find the invalid distance ? -> 
	
			double distance = ((imgWidth - x - 1)*(imgWidth - x - 1) + (imgHeight - y - 1)*(imgHeight - y - 1));
			if (distance < blendWidth)
			{
				weight = distance / blendWidth;
			}

            
			// *** END TODO ***	

			acc.Pixel(x, y, 0) += (float) (weight * img.PixelLerp(x_src, y_src, 0));
            acc.Pixel(x, y, 1) += (float) (weight * img.PixelLerp(x_src, y_src, 1));
            acc.Pixel(x, y, 2) += (float) (weight * img.PixelLerp(x_src, y_src, 2));
            acc.Pixel(x, y, 3) += (float) weight;
        }
    }
}
Пример #2
0
/******************* TO DO *********************
* AccumulateBlend:
*	INPUT:
*		img: a new image to be added to acc
*		acc: portion of the accumulated image where img is to be added
*       M: the transformation mapping the input image 'img' into the output panorama 'acc'
*		blendWidth: width of the blending function (horizontal hat function;
*	    try other blending functions for extra credit)
*	OUTPUT:
*		add a weighted copy of img to the subimage specified in acc
*		the first 3 band of acc records the weighted sum of pixel colors
*		the fourth band of acc records the sum of weight
*/
static void AccumulateBlend(CByteImage& img, CFloatImage& acc, CTransform3x3 M, float blendWidth)
{
    // BEGIN TODO
    // Fill in this routine
	// get shape of acc and img
	CShape sh = img.Shape();
    int width = sh.width;
    int height = sh.height;
	CShape shacc = acc.Shape();
    int widthacc = shacc.width;
    int heightacc = shacc.height;
	
	// get the bounding box of img in acc
	int min_x, min_y, max_x, max_y;
	ImageBoundingBox(img, M, min_x, min_y, max_x, max_y);

	CVector3 p;
	double newx, newy;

	// Exposure Compensation
	double lumaScale = 1.0;
	double lumaAcc = 0.0;
	double lumaImg = 0.0;
	int cnt = 0;

	for (int ii = min_x; ii < max_x; ii++)
		for (int jj = min_y; jj < max_y; jj++)
		{
			// flag: current pixel black or not
			bool flag = false;
			p[0] = ii; p[1] = jj; p[2] = 1;
			p = M.Inverse() * p;
			newx = p[0] / p[2];
			newy = p[1] / p[2];
			// If in the overlapping region
			if (newx >=0 && newx < width && newy >=0 && newy < height)
			{
				if (acc.Pixel(ii,jj,0) == 0 &&
					acc.Pixel(ii,jj,1) == 0 &&
					acc.Pixel(ii,jj,2) == 0)
					flag = true;
				if (img.PixelLerp(newx,newy,0) == 0 &&
					img.PixelLerp(newx,newy,1) == 0 &&
					img.PixelLerp(newx,newy,2) == 0)
					flag = true;
				if (!flag)
				{
					// Compute Y using RGB (RGB -> YUV)
					lumaAcc = 0.299 * acc.Pixel(ii,jj,0) +
							   0.587 * acc.Pixel(ii,jj,1) +
							   0.114 * acc.Pixel(ii,jj,2);
					lumaImg = 0.299 * img.PixelLerp(newx,newy,0) +
							   0.587 * img.PixelLerp(newx,newy,1) +
							   0.114 * img.PixelLerp(newx,newy,2);
					
					if (lumaImg != 0)
					{
						double scale = lumaAcc / lumaImg;
						if (scale > 0.5 && scale < 2)
						{
							lumaScale += lumaAcc / lumaImg;
							cnt++;
						}
					}
				}
			}
		}

	if (cnt != 0)
		lumaScale = lumaScale / (double)cnt;
	else lumaScale = 1.0;

	// add every pixel in img to acc, feather the region withing blendwidth to the bounding box,
	// pure black pixels (caused by warping) are not added
	double weight;
	
	for (int ii = min_x; ii < max_x; ii++)
		for (int jj = min_y; jj < max_y; jj++)
		{
			p[0] = ii; p[1] = jj; p[2] = 1;
			p = M.Inverse() * p;
			newx = p[0] / p[2];
			newy = p[1] / p[2];
			if ((newx >= 0) && (newx < width-1) && (newy >= 0) && (newy < height-1))
			{
				weight = 1.0;
				if ( (ii >= min_x) && (ii < (min_x+blendWidth)) )
					weight = (ii-min_x) / blendWidth;
				if ( (ii <= max_x) && (ii > (max_x-blendWidth)) )
					weight = (max_x-ii) / blendWidth;
				if (img.Pixel(iround(newx),iround(newy),0) == 0 &&
					img.Pixel(iround(newx),iround(newy),1) == 0 &&
					img.Pixel(iround(newx),iround(newy),2) == 0)
					weight = 0.0;

				double LerpR = img.PixelLerp(newx, newy, 0);
				double LerpG = img.PixelLerp(newx, newy, 1);
				double LerpB = img.PixelLerp(newx, newy, 2);
				
				double r = LerpR*lumaScale > 255.0 ? 255.0 : LerpR*lumaScale;
				double g = LerpG*lumaScale > 255.0 ? 255.0 : LerpG*lumaScale;
				double b = LerpB*lumaScale > 255.0 ? 255.0 : LerpB*lumaScale;
				acc.Pixel(ii,jj,0) += r * weight;
				acc.Pixel(ii,jj,1) += g * weight;
				acc.Pixel(ii,jj,2) += b * weight;
				acc.Pixel(ii,jj,3) += weight;
			}
		}
	
	printf("AccumulateBlend\n"); 

    // END TODO
}