main-upsampling

Examples of Upsampling

Here are examples of upsampling with various reconstruction filters. I used my example solution to the Imaging Programming Assignment.

Notice how the best filters for the checkboard example, aren’t necessarily the best for a more natural image - in particular, the “sharper” filters (like Cat-Rom and Lanczos) are too sharp for the checkboard (they ring), but they produce much sharper results for the BAD LINK.

Synthetic Example

This is a very tiny example (24 pixels square) of a checkerboard (a bad case - natural images don’t have this much high frequencies). The colors in the main parts are not black and white (they are gray) so the ringing doesn’t “overflow” the 0-255 range. I have upsampled by a factor of 8.

original image (24x24)
Box Filter
Tent Filter
Cubic BSpline Filter
Catmull-Rom (interpolating cubic)
Mitchell-Netraveli
Lanczos (radius 2)
Lanczos (radius 3)
Lanczos (radius 4)

This time scaled up by 3 - the original is pretty small.

Natural Example

original image (90x60)
Box Filter
Tent Filter
Cubic BSpline Filter
Catmull-Rom (interpolating cubic)
Mitchell-Netraveli
Lanczos (radius 2)
Lanczos (radius 3)
Lanczos (radius 4)

Here are the equations for the various filters. All come from the book EXCEPT for Lanczos, which I took from Wikipedia (and adapted).

Warning: you are getting a glimpse into how my solution works (yes, its designed for simplicity, not for efficiency).

class Filter {
public:
	Filter(float rad, string& nm) : radius(rad), name(nm) {};
	string name;
	float radius;	// should be an over statement (so you get some zeros)
	virtual float eval(float) = 0;
};
class BoxFilter : public Filter {
public:
	BoxFilter() : Filter(1,string("Box")) {};
	virtual float eval(float t) {
		return ( (t>=-.5) && (t<.5) ) ? ((float)1) : ((float)0);
	};
};
class TentFilter : public Filter {
public:
	TentFilter() : Filter(1,string("Tent")) {};
	virtual float eval(float t) {
		float x = abs(t);
		return ( x>1 ) ? 0.0f : (1.0f - x);
	};
};
// from p90 of Shirley
static float cubed(float x) { return x*x*x; } 
static float squared(float x) { return x*x; } 
class BSplineFilter : public Filter {
public:
	BSplineFilter() : Filter(2,string("CubicBSpline")) { };
	virtual float eval(float x) {
		float a = abs(x);
		float m = 1.0f-a;
		if (a<=1) return (-3.0f * m*m*m + 3.0f*m*m + 3*m + 1) / 6.0f;
		if (a<2) return cubed(2.0f - a) / 6.0f;
		return 0;
	};	
};
// p91 of Shirley
class CatRomFilter : public Filter {
public:
	CatRomFilter() : Filter(2,string("Catmull-Rom")) { };
	virtual float eval(float x) {
		float a = abs(x);
		float m = 1.0f-a;
		if (a<=1) return (-3.0f * m*m*m + 4.0f*m*m + m) / 2.0f;
		if (a<2) return (cubed(2.0f - a) - squared(2.0f-a)) /2;;
		return 0;
	};	
};
class MitchellNetravali : public Filter {
public:
	MitchellNetravali() : Filter(2,string("Mitchell-Netravali")) {};
	virtual float eval(float x) {
		float a = abs(x);
		float m = 1.0f-a;
		if (a<=1) return (-21.0f * m*m*m + 27.0f*m*m + 9*m + 1) / 18.0f;
		if (a<2) return (7.0f*cubed(2.0f - a) - 6.0f*squared(2.0f-a)) / 18.0f;
		return 0;
	};	
};
// taken from the WikiPedia page
class Lanczos : public Filter
{
public:
	Lanczos(float radius) : Filter(radius,string("Lanczos")+stringify(radius)) {};
	float eval(float x) {
	  if (x == 0.0) return 1.0;
	  if (x <= -radius || x >= radius) return 0.0;
	  float pi_x = x * fpi;
	  return radius * sin(pi_x) * sin(pi_x / radius) / (pi_x * pi_x);
	}
};
Page last modified on September 18, 2008, at 10:01 PM