6.6. Background SubtractionLet's imagine that you have a picture of someone, and a picture of where they stood without them there (Figure 6.14). Could you subtract the background of the person (i.e., figure out where the colors are close), and then replace it with another another background? Say, of the moon (Figure 6.15)? Figure 6.14. A picture of a child (Katie), and her background without her.Figure 6.15. A new background, the moon.Program 43. Subtract the Background and Replace it with a New One |
/** * Method to replace the background in the current picture * with the background from another picture * @param oldBackground a picture with the old background * to replace * @param newBackground a picture with the new background * to use */ public void swapBackground(Picture oldBackground, Picture newBackground) { Pixel currPixel = null; Pixel oldPixel = null; Pixel newPixel = null; // loop through the columns for (int x=0; x<getWidth(); x++) { // loop through the rows for (int y=0; y<getHeight(); y++) { // get the current pixel and old background pixel currPixel = this.getPixel(x,y); oldPixel = oldBackground.getPixel(x,y); |
To test whether we can replace an old background with a new background, try:
> String fileName = FileChooser.getMediaPath("kid-in-frame.jpg"); > Picture p = new Picture(fileName); > fileName = FileChooser.getMediaPath("bgframe.jpg"); > Picture oldBg = new Picture(fileName); > fileName = FileChooser.getMediaPath("moon-surface.jpg"); > Picture newBg = new Picture(fileName); > p.swapBackground(oldBg,newBg); > p.show();
We can, but the effect isn't as good as we would like (Figure 6.16). Our daughter's top color was too close to the color of the wall. And though the light was dim, the shadow is definitely having an effect here.
Barb tried the same thing with a picture of two of our kids in front of a wall. Barb should have used a tripod (really critical to get the pixels to line up). The two original pictures (Figure 6.17) weren't all that comparable. The background swap (with the bridge scene) didn't change all that much! We changed the threshold value to 50, and finally got some pretty good swapping (Figure 6.18).
[Page 201] > String fileName = FileChooser.getMediaPath("twoKidsWall.jpg"); > Picture p = new Picture(fileName); > Picture oldBg = new Picture( FileChooser.getMediaPath("wall2.jpg")); > Picture newBg = new Picture( FileChooser.getMediaPath("bridge.jpg")); > p.swapBackground(oldBg,newBg); > p.show();
|
/** * Method to replace the background in the current picture * with the background from another picture * @param oldBackground a picture with the old background * to replace * @param newBackground a picture with the new background * to use * @param threshold if the distance between the current * pixel color and the background pixel color is less * than this amount use the new background pixel color */ public void swapBackground(Picture oldBackground, Picture newBackground, double threshold) { Pixel currPixel = null; Pixel oldPixel = null; Pixel newPixel = null; // loop through the columns for (int x=0; x<getWidth(); x++) { // loop through the rows for (int y=0; y<getHeight(); y++) { // get the current pixel and old background pixel currPixel = this.getPixel(x,y); oldPixel = oldBackground.getPixel(x,y); |
To make this work pass the threshold too when invoking swapBackground:
> Picture p = new Picture( FileChooser.getMediaPath("twoKidsWall.jpg")); > Picture oldBg = new Picture( FileChooser.getMediaPath("wall2.jpg")); > Picture newBg = new Picture( FileChooser.getMediaPath("bridge.jpg")); > p.swapBackground(oldBg,newBg,50); > p.show();