Project 1: Hybrid Images
Key Information
Assigned | TBA |
Code Due | Tuesday 1/22 at 9:59pm via GitHub |
Artifact Due | Wednesday 1/23 at 9:59pm via GitHub |
This project must be done individually (groups of one).
Overview
The goal of this assignment is to write an image filtering function and use it to create hybrid images using a simplified version of the SIGGRAPH 2006 paper by Oliva, Torralba, and Schyns. Hybrid images are static images that change in interpretation as a function of the viewing distance. The basic idea is that high frequency tends to dominate perception when it is available, but, at a distance, only the low frequency (smooth) part of the signal can be seen. By blending the high frequency portion of one image with the low-frequency portion of another, you get a hybrid image that leads to different interpretations at different distances.
You will use your own solution to create your own hybrid images. You will submit your best creation as the artifact for this project, and the class will vote on the best hybrid image created.
Getting Started
Skeleton. In the Project 1 assignment on Canvas, you will find a GitHub Classroom
invitation link. Click this link to accept the Project 1 assignment
invitation and create your personal repository for this project. Your
repository already contains skeleton code, including a user interface
for creating hybrid images, as well as a file hybrid.py
that contains the functions that you need to implement. The next
section walks you through each function. Please keep track of the
approximate number of hours you spend on this assignment, as you will
be asked to report this in hours.txt when you submit.
Software. The CS lab computers have all the necessary dependencies installed for you to run this project. If you wish to work on it on your own computer, it is up to you to install the following dependencies. This list may be incomplete and is probably overcomplete - Send me email if I've missed something. The parenthesized versions are what is currently installed in the lab; other versions may well suffice, but it's recommended that you stick with the same major version numbers (i.e., Python 2.7, OpenCV 2.4) to minimize compatibility problems.
- Python (2.7.12)
- OpenCV (2.4.9.1), including Python 2 bindings
- python-tk (Tcl/Tk version 8.6)
- numpy (1.11.1)
- scipy (0.17.0)
- matplotlib (1.5.1)
- skimage (0.10.1)
Implementation Details
This project is intended to familiarize you with Python, NumPy and image filtering. Once you have created an image filtering function, it is relatively straightforward to construct hybrid images.
This project requires you to implement 5 functions, each of which builds on the previous ones:
cross_correlation_2d
convolve_2d
gaussian_blur_kernel_2d
low_pass
high_pass
Image Filtering. Image filtering (or convolution) is a
fundamental image processing tool. See chapter 3.2 of Szeliski and the
lecture materials to learn about image filtering (specifically linear
filtering). Numpy has numerous built in and efficient functions to
perform image filtering, but you will be writing your own such function
from scratch for this assignment. More specifically, you will implement
cross_correlation_2d
, followed by convolve_2d
which would use cross_correlation_2d
.
Gaussian Blur. As you have seen in the lectures,
there are a few different way to blur an image, for example taking an
unweighted average of the neighboring pixels. Gaussian blur is a special
kind of weighted averaging of neighboring pixels, and is
described in the lecture slides. To implement Gaussian blur, you will
implement a function gaussian_blur_kernel_2d
that produces
a kernel of a given height and width which can then be
passed to convolve_2d
from above, along with an image, to
produce a blurred version of the image.
High and Low Pass Filters.Recall that a low pass filter
is one that removed the fine details from an image (or, really, any
signal), whereas a high pass filter only retails the fine
details, and gets rid of the coarse details from an image. Thus, using
Gaussian blurring as described above, implement
high_pass
and low_pass
functions.
Hybrid Images. A hybrid image is the sum of a low-pass filtered version of the one image and a high-pass filtered version of a second image. There is a free parameter, which can be tuned for each image pair, which controls how much high frequency to remove from the first image and how much low frequency to leave in the second image. This is called the "cutoff-frequency". In the paper it is suggested to use two cutoff frequencies (one tuned for each image) and you are free to try that, as well. In the starter code, the cutoff frequency is controlled by changing the standard deviation (sigma) of the Gausian filter used in constructing the hybrid images. We provide you with the code for creating a hybrid image, using the functions described above.
Notes on efficiency
cross_correlation_2d
is computationally intensive:
filtering an image of size M x N with a kernel of size K x K is an
O(MNK2) operation. For arbitrary kernels, this is
unavoidable without using Fourier domain tricks. However, numpy's array
processing routines are highly optimized and allow for huge speedups of
array operations relative to Python for loops, which must be executed
line by line by the Python interpreter. As usual, focus on getting a
correct solution first; then, see if you can eliminate some of the
nested loops using numpy functions. For full credit, write
cross_correlation_2d
with only one pair of for loops that
loop over the kernel; see the rubric for details on the points assigned
for efficiency. Please don't sacrifice readability:
make sure your approach is well-commented if you're making any
nontrivial optimizations.
Testing. test.py
contains a test suite
that may help you debug your code.
Forbidden functions.
For just this assignment, you are
forbidden from using any Numpy, Scipy, OpenCV, or other preimplemented
functions for filtering. This limitation will be lifted in future
assignments, but for now, you should use for loops or Numpy vectorization
to apply a kernel to each pixel in the image. The bulk of your code will
be in cross_correlation_2d
, and
gaussian_blur_kernel_2d
, with the other functions using these
functions either directly or through one of the other functions you
implement.
We have provided a GUI in gui.py
, to help you debug your
image filtering algorithm. To see a pre-labeled version of the sample
images run:
python gui.py -t resources/sample-correspondance.json -c resources/sample-config.json
We provide you with a pair of images that need to be aligned using the GUI. The code for alignment uses an affine transform to map the eyes to eyes and nose to nose, etc. as you specify on the UI. We encourage you to create additional examples (e.g. change of expression, morph between different objects, change over time, etc.). See the hybrid images project page for some inspiration. The project page also contains materials from their Siggraph presentation.
For the example shown at the top of the page, the two original images look like this:
The low-pass (blurred) and high-pass versions of these images look like this:
Adding the high and low frequencies together gives you the image at the top of this page. If you're having trouble seeing the multiple interpretations of the image, a useful way to visualize the effect is by progressively downsampling the hybrid image as is done below:
Python and Numpy Tutorials
We will use python programming language for all assignments in this course. In particular, we will make heavy use of the Numpy package for scientific computing. If you are not farmilar with python and numpy, the following websites provide very good tutorials for them. If you have any questions related to python and numpy, please ask on Piazza or visit office hours.
Submission
Please read the submission instructions carefully to avoid losing points for submission mechanics.Code:
Commit your changes tohybrid.py
and your estimated hours spent in hours.txt
and push to GitHub. The last commit before the code deadline is the code that will be graded.
Artifact:
Place the following files in theartifact
directory
- left.png
- right.png
- hybrid.png
artifact/README.txt
file with the following
details about how your artifact was made:
- Give the high pass and low pass filter parameters (kernel size and kernel sigma) and Mix-in ratio.
- Specify which image was used for the high frequencies and which was used for low frequency.
- Optionally you can add comments on something interesting or different you did in the project.
git add
ed them) and those files and your final changes to
README are all pushed to GitHub.
Late sumbission:
To submit your work late, you must push your changes via git (as usual) then send me an email stating that you have submitted the assignment late. The timestamp of the email, which must be sent after your final changes are pushed to git, will be used as the submission time. It is your responsibility to keep track of your slip day balance - no exceptions will be made for accounting errors on your part. If you are submitting the assignment late, you must submit the artifact at the same time as the code.
If you submit late but don't email me, the latest code on GitHub as of the submission deadline will be the version that is graded.
Rubric
This project is worth a total of 50 points. Points are earned for correctness and efficiency, while deductions are possible for issues with clarity, coding style, or submission mechanics.
Correctness (30 points) | ||
30 points | Correctness as determined by automated tests. | |
Efficiency (14 points) | ||
10 points | Filtering routines are asymptotically efficient | |
2 points | cross_correlation_2d uses vectorization to avoid quadruply-nested for loops |
|
2 points | cross_correlation_2d uses python loops only over the kernel, not the image |
|
Artifact (5 points) | ||
5 points | Artifact and README are submitted as described | |
hours.txt (1 point) | ||
1 point | hours.txt contains a single integer with the approximate number of hours you spent on the assignment |
Clarity Deductions for poor coding style may be made. Please see the syllabus for general coding guidelines. Up to two points may be deducted for each of the following:
- Methods should be written as concisely and clearly as possible
- Methods should not be too long - use helper methods to break code into sensible subroutines
- Code should not be cryptic and terse - explain nontrivial blocks with comments
- Methods you introduce should be accompanied by a precise specification
- Variable and function names should be informative but not overly verbose
Submission Mechanics Up to 10 points may be deducted for problems with submission mechanics that require manual handling: for example, problems with your git repository, code that fails to run with automated test suite, failure to notify me of your late submission, etc.
Acknowledgements
Assignment based on versions developed and refined by Noah Snavely, Kavita Bala, James Hays, Derek Hoiem, and numerous underappreciated TAs.