|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis article describes a texture transfer program I developed based on Efros & Freeman's SIGGRAPH 2001 paper: Texture transfer is the process by which the texture of a source image is transferred to a target image. The result is that we get an image that looks like the target image but it is made out of the texture of the source image e.g. below are shown two images -- source, target and the result of transferring the texture of the source onto the target:
The source is an image of rice and the target is the man's face. After texture transfer we get a face that looks as though it is made out of rice. How do we do this? The idea is to take patches of rice and weave them together seamlessly into the image of the face. Bright patches of rice will goto areas where the face is bright and dark patches will goto areas where the face is dark. To illustrate the concept, in the image below the boundaries of the individual patches have been colored in red. You can find each of these patches in the rice image if you look for them hard enough.
The Texture Transfer AlgorithmThe texture transfer algorithm has to synthesize an image from the pixels of the source. Locally the result should have the appearance of the source texture but when looked at globally the result should look like the target. The texture transfer proceeds by synthesizing an image in faster scan order in units of block. You can control the size of the block in the setting window and it is set to 27x27 pixels by default. Whenever a block in the result has to be synthesized the algorithm needs to find a suitable block in the source texture that satisfies two criteria:
To this end for every patch in the source image the algorithm computes two difference measures d1, d2 that quantify how well criterion 1 and 2 above are satisfied and their weighted sum
The algorithm chooses the patch that minimizes d. The function
The algorithm synthesizes the result in several passes or iterations starting with a low value of a (a=0.1) and initial block size set to 27x27 pixels by default and decreasing block size by 1/3 rd in every iteration and increasing alpha until a=0.9 in the final iteration. The number of iterations to do is set to 3 by default. The following code snippet from function for (int i = 0; i < numIterations; i++)
{
bool isFirstIteration = i == 0;
// from Alyosha's paper
double alpha = 0.8 * i / (numIterations - 1) + 0.1;
nextX = 0; nextY = 0; nextBlockWidth = blockWidth; nextBlockHeight =
blockHeight; nextOverlapX = 0; nextOverlapY = 0;
bool completed = false;
while (!completed && !CancellationPending)
{
Point q = new Point(nextX, nextY);
// get matching block from src which will be pasted at location q in img
p = GetMatchingBlock(img, src, target, q, nextOverlapX, nextOverlapY,
nextBlockWidth, nextBlockHeight, alpha, isFirstIteration, probe,
out eh, out ev);
// the horizontal and vertical cuts will ensure that the patch
// from src will fit in seamlessly when it is pasted onto img
int[] Hcut = findHcut(eh); // compute the horizontal cut
int[] Vcut = findVcut(ev); // compute the vertical cut
// cut the block per the horizontal and vertical cuts and then
// paste it onto img
cutandpaste(src, p, img, q, Hcut, Vcut, nextBlockWidth,
nextBlockHeight, displayBoundaryCut);
// calculate how much of texture transfer is complete; 1->fully
// completed
double fractionComplete = CalculateFractionComplete(i, numIterations,
nextX, nextY, nextBlockWidth,
nextBlockHeight, imgWidth, imgHeight);
int percentComplete = (int)Math.Round(fractionComplete * 100);
// send progress report to UI thread
ReportProgress(percentComplete, new ProgressReport(fractionComplete,
rgb.ToBitmap(img)));
// (nextX, nextY): coordinates of top left corner in img where next
// block is to be synthesized;
// (nextBlockWidth, nextBlockHeight): dimensions of block to be
// synthesized
// (nextOverlapX, nextOverlapY): the amount by which block will will
// overlap neighbors completed: is this iteration complete
Next(X, Y, blockWidth, blockHeight, imgWidth, imgHeight, overlapX,
overlapY, out nextX, out nextY, out nextBlockWidth,
out nextBlockHeight, out nextOverlapX, out nextOverlapY,
out completed);
X = nextX; Y = nextY;
}
if (CancellationPending)
{
e.Cancel = true;
return;
}
X = 0; Y = 0;
blockWidth = (int)Math.Round(blockWidth * blockReductionFactor);
blockHeight = (int)Math.Round(blockHeight * blockReductionFactor);
probeWidth = srcWidth - blockWidth;
probeHeight = srcHeight - blockHeight;
probe.Reset(probeWidth, probeHeight);
overlapX = (int)Math.Round(overlapX * blockReductionFactor);
overlapY = (int)Math.Round(overlapY * blockReductionFactor);
if (overlapX >= blockWidth || overlapY >= blockHeight || blockWidth ==
0 || blockHeight == 0)
break;
}
Steps to Perform Texture Transfer
ResultsIn the following table I show some results I have obtained using the texture transfer program. These results are generated with amount to probe set to 10% and distance metric set to SSD. Note that the images have been resized to fit on the screen. Therefore if you download these images and run the program it is likely that you may not get the exact same results.
Wrap UpThis was a fun project for me as it introduced me to Computer Graphics and some neat features in C# 2.0 such as the Updates & Revision history3/7/08: I created this project using Visual C# Express Edition 2008 and have noticed if you attempt to open the solution using VS 2005 it gives an error message. If you encounter this just create a new project and add the source code contained in the zip file, compile and run. The only references you should need are System, System.Windows.Forms and System.Drawing. 3/11/08: Related links: Rob Burke's C# texture transfer code
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||