CS 4810: Introduction to Computer Graphics
|
In this assignment you will create a simple image processing program, a pared-down version of Adobe Photoshop or The Gimp. The operations that you implement will be mostly filters which take in an input image, process the image, and produce an output image.The code skeleton can be downloaded here.
An overview of the code you will be using can be found here.
Some test images can be found here.
Examples of what some of the results should look like can be found here.
You should use the code skeleton as a starting point for your assignment. We provide you with several files, but you should only have to changeimage.todo.cpp
andlineSegments.todo.cpp
.
main.cpp
: Parses the command line arguments, and calls the appropriate image functions.Util/cmdLineParser.[cpp/h]
: Code for processing the command line arguments.JPEG/*.[cpp/h]
: Functions for the back end of jpeg file reading and writing. You won't need to modify these, but you will have to compile them into a library to support reading and writing files in this format.Image/bmp.[cpp/h]
: Functions to read and write Windows 24-bit BMP files.Image/jpeg.[cpp/h]
: Functions to read and write jpeg images.Image/image.[cpp/h]
: Image processing code.Image/lineSegments.[cpp/h]
: Line segment processing code.Image/image.todo.cpp
: Code stubs for image processing that you will need to implement.Image/lineSegments.todo.cpp
: Code stubs for line segment processing that you will need to implement.assignment1.dsw
: Workspace file suitable for Visual C++ on Windows 2000 platform.JPEG/Makefile
: The makefile for compiling theJPEG
library under Unix.Makefile
: The makefile for compiling theassignment1
executable under Unix (use 'gmake' to build!!).After you copy the provided files to your directory, the first thing to do is compile the program. To do this, you will first have to compile the
JPEG
library and then compile theassignment1
executable.On a Windows Machine
Begin by openingAssignment1.sln
using Microsoft Visual Studio.
- Build
Assignment1.exe
by selectingBuild -> Build Solution
orCtrl + Shift + B
. (If it has not been compiled yet, this will also compile theJPEG
library.)On a Unix Machine
- Type
make
to compile theAssignment1
executable. (If it has not been compiled yet, this will also compile theJPEG
library.)
The user interface for this assignment was kept to the simplest possible, so you can concentrate on the image processing issues. The program runs on the command line. It reads an image from a specified file, processes the image using the filter specified by the command line arguments, and writes the resulting image to the specified file.
The command line parser is set up to read the arguments from the command line that are specified in the following format: First the parameter name is specified by pre-pending with two hyphens, and then the parameter values are enumerated. (Note that the number of arguments associated to each parameter are fixed inmain.cpp
and the order in which the parameters are specified is ignored.)
For example, to increase the brightness of the imagein.bmp
by 10%, and save the result in the imageout.bmp
, you would type:To see the full list of possible arguments, you can simply type:% Assignment1 --brighten 1.1 --in in.bmp --out out.bmp
This gives you a list of all the possible parameter names and the number and meaning of the associated parameter values. Bracketed parameters are optional (an input image file and an output image file need to be specified).% Assignment1
Note that since the order in which parameters are specified is ignored, if you want to apply two filters to a single image you can specify parameters for both filters, but you cannot control the order in which the filters are applied. For some filters, the order in which the filters are applied does not affect the output image while for others, the output image may depend on the order. (For the latter case, you can control the ordering by applying one filter, writing the output to a temporary image, and then applying the second filter to the temporary image.)
The currentmain.cpp
decides if the specified image file is Windows BMP file or a JPEG file based on the file extension.
The assignment is worth 30 points. The following is a list of features that you may implement (listed roughly from easiest to hardest). The number in front of the feature corresponds to how many points the feature is worth.The assignment will be graded out of 30 points. In addition to implementing these features, there are several other ways to get more points:
- (1) Image32::AddRandomNoise (
image.todo.cpp
):
Add random noise to an image.- (1) Image32::Brighten (
image.todo.cpp
):
Individually scale the RGB channels of an image.- (1) Image32::Luminance (
image.todo.cpp
):
Change a color image into a luminance (grayscale) image.- (1) Image32::Contrast (
image.todo.cpp
):
Change the contrast of an image. (See Graphica Obscura.)- (1) Image32::Saturate (
image.todo.cpp
):
Change the saturation of an image. (See Graphica Obscura.)- (1) Image32::Crop (
image.todo.cpp
):
Extract a subimage specified by two corners(x1,y1)
and(x2,y2)
.- (2) Image32::Quantize (
image.todo.cpp
):
Change the number of bits per channel of an image, using simple rounding.- (2) Image32::RandomDither (
image.todo.cpp
):
Convert an image to a given number of bits per channel, using a random threshold.- (2) Image32::OrderedDither2x2 (
image.todo.cpp
):
Convert an image to a given number of bits per channel, using a 2x2 ordered dithering matrix.- (2) Image32::FloydSteinbergDither (
image.todo.cpp
):
Convert an image to a given number of bits per channel, using dithering with error diffusion.- (2) Image32::Blur3x3 (
image.todo.cpp
):
Blur an image by using a 3x3 mask of weights as a filter.- (2) Image32::EdgeDetect3x3 (
image.todo.cpp
):
Detect edges in an image by using a 3x3 mask of weights as a filter.- (1) Image32::NearestSample (
image.todo.cpp
):
Return the value of the pixel closest to the position(x,y)
.- (1) Image32::BilinearSample (
image.todo.cpp
):
Return the value of the pixel obtained by interpolating the values of the four pixels closest to the position(x,y)
.- (1) Image32::GaussianSample (
image.todo.cpp
):
Return the value of the pixel obtained by computing the weighted average of all pixels whose distance is less thanradius
from the sample point(x,y)
using Gaussian weighting where the variance of the Gaussian is specified byvariance
- (1) Image32::ScaleNearest (
image.todo.cpp
):
Scale an image up or down by a real valued factor using nearest pixel sampling.- (1) Image32::ScaleBilinear (
image.todo.cpp
):
Scale an image up or down by a real valued factor using bilinear interpolation.- (1) Image32::ScaleGaussian (
image.todo.cpp
):
Scale an image up or down by a real valued factor using Gaussian sampling. (Make sure to choose the variance of the Gaussian and the radius of weighting so that they correspond to the scale factor in a meaningful way.)- (2) Image32::RotateNearest (
image.todo.cpp
):
Rotate an image by a given angle about the center pixel using nearest pixel sampling.
Note: You may have to resize the image as the dimensions of the output image need not be the same as the dimensions of the input image.- (2) Image32::RotateBilinear (
image.todo.cpp
):
Rotate an image by a given angle about the center pixel using bilinear interpolation.
- (2) Image32::RotateGaussian (
image.todo.cpp
):
Rotate an image by a given angle about the center pixel using Gaussian sampling.
- (1) Image32::SetAlpha and Image32::Composite (
image.todo.cpp
):
Compose two images by overlaying the target image over the source.
Note: In practice, Windows BMP files and JPEG files only specify 3-channel, RGB (no alpha), images. Thus, in order to generate an image with an alpha-channel, composition is performed by calling something akin to:%assignment1 --in source.bmp --composite overlay.bmp matte.bmp --out out.bmpThen, inmain.cpp
, the methodImage32::SetAlpha
is called to set the alpha-channel of the imageoverlay.bmp
using the imagematte.bmp
. This generates a 4-channel, RGBA, image that is passed along toImage::Composite
for compositing.- (1) Create a composite image of yourself and a famous person.
- (2) Image32::FunFilter (
image.todo.cpp
):
Warp an image using a non-linear mapping of your choice (examples are fisheye, sine, bulge, swirl).- (6) Beier-Neely Morphing:
Morph two images using the method in Beier Neely's Feature-based Image Metamorphosis.
See this page for more information about the command line, input options, and some test cases.
To make your life easier, theImage32::BeierNeelyMorph
function already has a body which interpolates the line segments, calls the warping functionImage32::Warp
and then cross-dissolves the resultant images by callingImage32::CrossDissolve
.
TheImage::Warp
function callsOrientedLineSegmentPairs::getSourcePosition
which determines the position of the source pixel given the position of the target.
In order to get this function to actually return the desired image, you will need to implement the following methods:
- OrientedLineSegment::length (
lineSegments.todo.cpp
):
This method returns the length of the line segment.- OrientedLineSegment::distance (
lineSegments.todo.cpp
):
This method returns the shortest distance from the point(x,y)
to the line segment.- OrientedLineSegment::getPerpendicular (
lineSegments.todo.cpp
):
This method writes the coordinates of the unit-vector perpendicular to the direction of the line segment.
Note: When implementing this method, be sure to choose the orientation of the perpendicular vector consistently.- OrientedLineSegment::GetSourcePosition (
lineSegments.todo.cpp
):
This method uses a single pair of source and target line segments to define the position of the source pixel, given the position of the target pixel. (To change the way in which the blending occurs, you will want to change the default values of the parametersOrientedLineSegment::A
,OrientedLineSegment::B
, andOrientedLineSegment::P
.)- Image32::Warp (
image.todo.cpp
):
This method uses a set of oriented line segment pairs to warp the current image. In order to implement this method you will most likely want to callOrientedLineSegmentPairs::getSourcePosition
which returns the position of the source pixel you want to sample at in order to compute the color value at the target. (Assuming that you have implementedOrientedLineSegment::GetSourcePosition
, theOrientedLineSegmentPairs::getSourcePosition
method should not need any implementation.)- Image32::CrossDissolve (
image.todo.cpp
):
This static method takes in two images and a cross-disolving value in the range [0,1], and generates the specified blend of the two images.For images or movies that you submit, you also have to submit the sequence of commands used to created them, otherwise they will not be considered valid.
- (1) Submitting one or more images for the art contests.
- (1) Submitting a
.mpeg
or.gif
movie animating the results of one or more filters with continuously varying parameters. You can generate such a video by outputting the results of your filter in JPEG format and then using an executable such as FFmpeg or JPGAvi which stitches together a collection of JPEG files into a single movie. Alternatively, if you are a Linux user, you can use thempeg_encode
command or The Gimp to produce an animated gif for your results.- (2) winning the regular art contest,
It is possible to get more than 30 points. However, after 30 points, each point is divided by 2, and after 32 points, each point is divided by 4. If your raw score is 29, your final score will be 29. If the raw score is 33, you'll get 31.25. For a raw score of 36, you'll get 32.
Submission intstructions are specified here.
Please include the following in your submission:
- the complete source code;
- the
.bmp
images (source and dest) for the image processing features (you can alternatively submit .png or .jpg files);- the
.bmp
images (source, overlay, and matte) for the compositing feature (you can alternatively submit .png or .jpg files);- the line files for the morph feature and 10
.jpeg
images showing the morph between two images at 10 different time-steps (optional);- the
.mpeg
movie or animated .gif for the movie feature (optional);- the images for the art contest (optional); and
- a writeup.