Race Condition Image Batch Assignment

From CSE231 Wiki
Jump to navigation Jump to search

Motivation

Race conditions can lead to difficult bugs to find and fix. We gain experience finding them and fixing them.

Background

Pixels

The word pixel stands for Picture Element. A pixel is a small part of a picture. Pixels are the little dots that make up computer screens. When you see a low-resolution picture that is grainy, the grains you’re seeing are the pixels.

Color Models

There are many different representations of Color. These representations are called color models.

Subtractive Color Models

Some color models are subtractive. These models are useful for printing. They are subtractive because they model the subtraction of light as each color absorbs light (before what remains to bounce off into your eyes). The most common of these models is CMYK which represents Cyan, Magenta, Yellow, blacK. If you have ever changed the ink in a color printer, you have encountered CMYK cartridges. Truth be told, you don’t need the black. Essentially all of the visible spectrum of light would be absorbed printing layers of cyan, magenta, and yellow. A lot of black tends to be printed, so it is more cost effective to add to add black into the model.

CMYK subtractive color mixing

Additive Color Models

Component_video_RCA

Some color models are additive. These models are useful for display devices. They are additive because they model the addition of light which is thrown at your eyes.

RGB

RGB_color_solid_cube

The most common of these models is RGB which repesents Red, Green, Blue. If you have ever plugged an old device into a TV with a component video cable, that is what the separate cables are carrying: analog signal for red, green, and blue.

RGB_illumination

HSV

We will use the HSV color model which represents Hue, Saturation, Value.

HSV_color_solid_cone_chroma_gray

This model benefits from often being easier for humans to think about and will enable us to create some compelling image filters with minimal effort. Evidence for it being easier for humans to think about can be found in most defaults for color pickers, including the one which can be found by searching on Google for color picker.

Play around with the color picker for a while and watch the hue, saturation, and value change as you interact with it. Try to isolate the saturation by dragging left to right in the rectangle component of the color picker. Isolate changes to the value by dragging up and down. Control the hue with the slider below.

Hue

Hue is cyclical. Red is usually at 0.0 and the hue changes as you go around the ring… returning back to red at 1.0.

Saturation

Full saturation is a completely “vivid” form of the color. No saturation is “dull” gray. The "saturation" dimension is sometimes labeled chroma (as it is in this image).

Value

This component is somewhat uninspiringly named: “value”. It is often called brightness or lightness, but that can be somewhat confusing since one might expect full brightness to always equate to white, which it does not.

Code To Investigate

HsvColor

public class HsvColor {
	private final double hue;
	private final double saturation;
	private final double value;
	public HsvColor(double hue, double saturation, double value) {
		this.hue = hue;
		this.saturation = saturation;
		this.value = value;
	}
	public double hue() {
		return hue;
	}
	public double saturation() {
		return saturation;
	}
	public double value() {
		return value;
	}
}

HsvImage

public interface HsvImage {
	int width();
	int height();
	Optional<HsvColor> colorAtPixel(int x, int y);
	void setColorAtPixel(int x, int y, HsvColor color);
}

SequentialImageFilter

public class SequentialImageFilter implements ImageFilter {
	@Override
	public HsvImage apply(HsvImage src, PixelFilter pixelFilter) {
		HsvImage dst = new DefaultHsvImage(src.width(), src.height());
		for (int y = 0; y < src.height(); ++y) {
			for (int x = 0; x < src.width(); ++x) {
				Optional<HsvColor> srcPixelOptional = src.colorAtPixel(x, y);
				if (srcPixelOptional.isPresent()) {
					HsvColor srcPixel = srcPixelOptional.get();
					HsvColor dstPixel = pixelFilter.apply(srcPixel);
					dst.setColorAtPixel(x, y, dstPixel);
				} else {
					throw new Error();
				}
			}
		}
		return dst;
	}
}

DesaturateAllPixelFilter

public class DesaturateAllPixelFilter implements PixelFilter {
	@Override
	public HsvColor apply(HsvColor src) {
		return new HsvColor(src.hue(), 0.0, src.value());
	}
}

DesaturateNonSkinTonePixelFilter

public class DesaturateNonSkinTonePixelFilter implements PixelFilter {
	private static boolean isInRange(double min, double x, double max) {
		return min < x && x < max;
	}
	private static boolean isSkin(HsvColor src) {
		return (src.hue() < 0.1 || src.hue() > 0.9) && isInRange(0.1, src.saturation(), 0.7);
	}
	@Override
	public HsvColor apply(HsvColor src) {
		return new HsvColor(src.hue(), isSkin(src) ? src.saturation() : 0.0, src.value());
	}

}

Code To Debug

ImageBatch

applyToAll

class: ImageBatch.java Debugging icon.png
methods: applyToAll
package: racecondition.image.exercise
source folder: student/src/main/java

method: HsvImage[] applyToAll(HsvImage[] images, ImageFilter imageFilter, PixelFilter pixelFilter) Parallel.svg (parallel implementation required)

If one had a filter that could be applied to an image independently, it is reasonable to apply the filter to each image in an array of images in parallel. Unfortunately, the code you must debug has a data race. Fix the data race in ImageBatch's applyToAll method.

public class ImageBatch {
	public static HsvImage[] applyToAll(HsvImage[] images, ImageFilter imageFilter, PixelFilter pixelFilter)
			throws InterruptedException, ExecutionException {
		@SuppressWarnings("unchecked")
		Future<Void>[] futures = new Future[images.length];
		HsvImage[] desaturatedImages = new HsvImage[images.length];
		int[] array = { 0 };
		for (array[0] = 0; array[0] < images.length; ++array[0]) {
			futures[array[0]] = void_fork(() -> {
				desaturatedImages[array[0]] = imageFilter.apply(images[array[0]], pixelFilter);
			});
		}
		join(futures);
		return desaturatedImages;
	}
}

Client

class: ImageBatchApp.java VIZ
package: racecondition.image.viz
source folder: student/src/main/java

Testing Your Solution

Correctness

class: _ImageBatchTestSuite.java Junit.png
package: racecondition.image.exercise
source folder: testing/src/test/java

Pledge, Acknowledgments, Citations

file: race-condition-image-batch-pledge-acknowledgments-citations.txt

More info about the Honor Pledge