For this assignment, I used the algorithm as described in the handout. Essentially, each pixel in the final image could be represented by one linear equation, and that linear equation could be represented by one row in the coefficient matrix and one value in the solution vector. Figuring out this row and value was the problem.
My algorithm looped over all pixels in the final image. If the pixel was under the mask, then its value was equal to the value in the target image. Thus, its linear equation is simply p = target(p). The row of the coefficient matrix would have a 1 at index p, and the solution vector would have target(p) at index p.
For a pixel not under the mask, it was slightly trickier. For this, #neighbors of p * final value of p is equal to the sum of the value of all of p's neighbors plus the sum of the gradients between p and its neighbors. If all of p's neighbors are not under the mask, their values are known (they are the value of the neighbor in the target image). This simplifies the linear equation since p is the only unknown. We put the number of neighbors p has in the coefficient matrix at (p,p). We choose (p,p) since the row of the coefficient matrix signifies which linear equation we are entering. In this case, we're entering the linear equation for p (remember, each pixel has its own linear equation and row). We choose column p because we are entering the coefficient for p, and we choose to enter #neighbors since that is the coefficient of p in the equation. The value of B(p) is simply a matter of summing the target values of the neighbors and their gradients with relation to p.
If a neighbor of p (we'll say q) is under the mask, then its value is unknown. We cannot simply grab it from the target image. We must represent it as another variable in the system of equations. Since the value of neighbors is originally on the right hand side of the linear equation, we must move this unknown variable over to the left, giving it a coefficient of -1. Thus, we set A(p, q)=-1. We do this for all of qs under the mask. p's coefficient is still number of neighbors, and B(p) is now the sum of all the values we can calculate for p's neighbors, namely the sum of the target values for neighbors not under the mask and gradients of all neighbors with relation to p.
The trickiest part was not being able to build the coefficient matrix directly. Since the problem yielded MxN linear equations each with MxN variables (for an MxN image), the coefficient matrix needs to be (MxN)x(MxN). That's a big matrix! The work around for this involved keeping three distinct vectors to represent the larger coefficient matrix (A). One vector was the row index, another the column index, and the third held the actual value.
For example, if I wanted to set A(700, 700) to 4 (if pixel (700, 700) had 4 neighbors, I had to set rows(index) = 700, cols(index) = 700, and values(index) = 4. It was important to set the same index in each vector.
The three images I chose to show directly on this page are my best results. Did I ever tell you about the time that I paraglided from the Grand Canyon to THE MOON?! It was awesome. The two images linked to from here are less good. For the picture of me playing with the New Orleans Jazz Philharmonic, the source image is not only too small, but the edges around me in the picture have really high gradients, thus, these high values end up in the final blended image. Similar effects are present in the image of Tricia wearing the sunglasses. Those glasses are just too big! The clown wig is certainly awesome in my opinion, although I claim the 5th on whether or not it is an improvement over the model's recently buzzed head.