Your Head on my Body
By: Greg Leo
Add Comments, Corrections, Improvements Here-
Your Head on my Body - Comments
"Your head on my body."
This is a Common Photoshop practice to mess with pictures. The
idea is to copy somebody's head onto somebody else's body.
Doing this in JES will be a bit harder. However, with a good
setup,and careful coding, the outcome will be acceptable.
For this example, we will start with a picture of our dear
President Clough, and a picture of Mark McGwire. When choosing a picture to isolate the head from, try to find a picture which has a good bit of contrast between the head and the background.
Let us first figure out how to isolate President Clough's head.
The first step will be to find the pixel range in which
his head is. For this, we can use the media
tools.
This does not have to be perfect, we just want to get the
"square" of pixels that contains the head. In this case...
(128,67) to (494,605).
Here is the picture with the square of pixels designated.
Let's do the same thing for Mark McGwire...
Here, we get (140,39) to (214,137).
Now the we have our pixels picked out, we will want to
determine the multiplier we will use to reduce President
Clough's head to fit over Mark's. We have two options here...
start with a guess at what the number might be and change it
when we tweak our code later, or do a little math to get an
idea for what this number needs to be. Either way, tweaking
will be necessary. Let's start with the calculation though.
Size Of President Clough's Head = A
Size Of Mark McGwire's Head = B
A = (x2-x1)*(y2-y1) = (492-128)*(605-67) = 195832 pixels
B = (x2-x1)*(y2-y1) = (214-140)*(137-39) = 7252 pixels
The ratio of Mark's Head to President Clough's head is then,
B/A = .03703
This still isn't anything we can use though. So, lets think
back to our picture resizing code. Incrementing the sourceX
and SourceY by 2 pixels on each iteration created a picture
which was 1/4 the size.
The equation which comes out of this is,
Ratio to reduce to = (1/ (sourceX Increment * sourceY
Increment))
Size = 1/(Xfactor*yFactor)
Now, let's plug in our numbers...
.03703 = 1/(x*y)
(For the sake of the equation, we will assume we want to
reduce the X and Y equally)
.03703 = 1/(x^2)
.03703(X^2)=1
x^2 = 27
x = 5.2
So, our increment on our sourceX and sourceY will be around
5.2.
Our third step will be for figure out how to copy in just the
pixels that are part of President Clough's head. For this, we
will need to use some if statements and the distance function.
But first, let's take a close look at the picture, and list
the parts we do not want.
Looking within the square, we will want to skip over the
pixels that contain the suit jacket, the white shirt, and the
blue background. So, we will use an if statement like this...
if ((distance(color,blue) > #) and (distance(color,white) > #)
and (distance(color,black) > #)):
We will input the numbers when we start running the code.
Now, we are ready to write the code. I recycled some old code
from homework 2 and with a few changes here is our result.
def headToHead():
prescloughf=getMediaPath("presclough.jpg")
presclough = makePicture(prescloughf)
mcgwiref = getMediaPath("mcgwire.jpg")
mcgwire= makePicture(mcgwiref)
sourceX = 128
for targetX in range(140,214):
sourceY = 67
for targetY in range(39,137):
color =
getColor(getPixel(presclough,int(sourceX),int(sourceY)))
if ((distance(color,blue) > 5) and
(distance(color,white) > 60) and (distance(color,black) >
60)):
setColor(getPixel(mcgwire,targetX,targetY), color)
sourceY = sourceY + 5.2
sourceX = sourceX + 5.2
show(mcgwire)
return mcgwire
Running this code, we get a reasonable result.
It still isn't great though, let's make it a tad bit wider and
tweak the distances in the if statement.
def headToHead():
# Set up the source and target pictures
prescloughf=getMediaPath("presclough.jpg")
presclough = makePicture(prescloughf)
mcgwiref = getMediaPath("mcgwire.jpg")
mcgwire= makePicture(mcgwiref)
sourceX = 128
for targetX in range(140,214):
sourceY = 67
for targetY in range(39,137):
color =
getColor(getPixel(presclough,int(sourceX),int(sourceY)))
if ((distance(color,blue) > 5) and
(distance(color,white) > 35) and (distance(color,black) >
120)):
setColor(getPixel(mcgwire,targetX,targetY), color)
sourceY = sourceY + 5.2
sourceX = sourceX + 5.6
show(mcgwire)
return mcgwire
While the results of this tutorial were acceptable, they were not perfect. I doubt anyone would think that this is a picture of President Clough in a Cardinals uniform. To get this to look better, we would need to do some contiguous chromakeys. A tool which Photoshop calls the "Magic Wand". In this example, the white chromakey for President Clough's shirt also got a bit of his white hair and beard. What we would want to do is only remove the white from certain areas, in this case, the shirt. Coding this is JES would be much more tedious.
Also, this code will only work for these pictures. Unlike other code we have dealt with in 1315, this function is not recyclable, and it would be impossible to make the function work for any two picture. The only solution to this is to make the pictures conform to the function.
One of the main issues is skin tone and lightning conditions. This is another area where Photoshop reigns supreme, buy letting us guess and check to tweak the coloring and lighting, we can get a good match between source and target pictures. A practice which is much more difficult to code in JES.
I will leave you with my Photoshopped example of this same effect.

Links to this Page
- Tutorials last edited on 30 November 2006 at 7:35 pm by r40h103.res.gatech.edu
- Intro to the Intro last edited on 18 July 2005 at 5:57 pm by adsl-158-34-145.asm.bellsouth.net