An example execution of the algorithm on the picture provided on the course web site.

Introduction

The purpose of this project was to implement an algorithm for content-aware resizing. This particular algorithm was invented by Shai Avidan and Ariel Shamir and the paper is available here.

Approach

The general idea of the algorithm is very intuitive and simple. First, you compute an energy function of the picture, which should correspond to the importance of the different parts. Then, at each iteration you pick a path (vertical or horizontal) that is of minimum cost and you remove it. This path can be easily computed using dynamic programming. On the right you can see a video of how my implementation works, reducing the width of the picture by 200 pixels. Furthermore, this same idea can be used for several other tasks like object removal and image stretching.

Energy Functions

There are many functions that can be used. One is to try to minimize the norm of the gradient vectors along the path (the gradient is taken as the average of the three per-channel gradients). The other function that I use computes both the norms of the gradients and finds the edges using an edge detector. Then, it does a linear interpolation between them, thus strengthening the important parts of the picture. Below are the resulting energy functions using both approaches from the picture that is in the video.

These are the final results, when the images are resized by 200 pixels in width. As you can see, when we are using both the gradient and the detected edges, the structure of the house is less disturbed than in the other case (see the edges of the roof).

Results

These are the results when the algorithm was applied by first scaling down horizontally and then vertically.

Original Image

Picture from flickr.

Original Image

A picture from flickr.

Original Image

The White Horse, John Constable

Original Image

The Fighting Temeraire, J. M. W. Turner

Original Image

Picture from flickr. A place near my hometown.

Original Image

The algorithm is of course, not perfect. There were some cases where it did not preserve the features of the picture. These pictures are presented in the next section, together with results of how some of them can be fixed using the techniques described below.

Bells & Whistles

Seam Insertion

To perform seam insertion, the algorithm finds the first K seams that it would remove and then it replicates them. When you replicate a seam you interpolate it with the other neighbor (linearly, you take the average). Also, note that if we do this for fairly large K what we will get is a standard image scaling. To avoid this, if we want to insert many seams, we do the operation explained above multiple times. In my implementation, I have limited every iteration to increase the size of the picture by at most 10% of the original size. Some results are shown below.

Enlarged

Same as the picture in the previous section.

Enlarged

Taken with my camera.
This is an example where the algorithm did not work correctly when set with maximum of 10% at each iteration.

From flickr.

Object Removal

Using a slight modification of the algorithm, you can easily remove objects from the picture while keeping the same size. First, using a user provided binary mask all selected pixels (where the mask is 1) are given large negative weights to their energies so they will be the first to be removed. An interesting question is, how to choose whether to remove vertical or horizontal seams? One way to do it is to use the optimal combination which can be computed using a dynamic programming algorithm. I have taken a greedy approach, at each iteration you take what gives you less cost, a horizontal or a vertical seam. As this will reduce the size of the image, then the seam insertion algorithm is used to restore the original size.

From flickr.

From deviantart.

Image Resize with Human Input

One way of improving the algorithm is to use human input as well. The user has to give to the algorithm a mask that will select the areas that he doesn't want to get shrinked. Then, the energy function is adjusted by adding large weights to these areas, ensuring that they will not get modified. This approach has managed to fix a lot of problems that occurred with the original implementation. Here, both results are presented: when the original implementation is used and when we use this approach with user input.

From deviantart.

Optimal Seam Removal

When we have to resize the picture in both dimensions, say by M horizontally and by N vertically, there are several ways in which we can order the combination of horizontal and vertical seams. In the pictures presented above, the seams were first removed in the vertical direction and then in the horizontal direction. Ideally, what would we be interested in is to find the optimal combination. Under optimal we understand the combination such that the total cost of all seams is minimal. This can be achieved using dynamic programming. We define a table T of size MxN such that entry T(i,j) contains the minimal cost obtainable when we perform i horizontal and j vertical seams. Using a simple recurrance we can fill in the table, and the result is then in T(M,N). I have implemented this in MATLAB, and because of MATLAB's notorious performance with loops, which can not be easily avoided because of taking minimums, this algorithm performs slowly. Below are some results of the differences when we use and when we do not use optimal seam carving.

Original Image

Shown in the previous section.

From flickr.

With Optimal Seam Carving

As you can see, the differences are very small, and I wouldn't recommend using the optimal algorithm as the time penalty is too high for the small improvement in quality.