Assignment 120: Portrait-preserving re-colouring of images

Your task is to implement image re-colouring (that is, targeted hue changes) in a way that preserves skin tones, so that the algorithm can be applied to portraits.



The 117raster project from the repository grcis (GIT) serves as a basis of the solution: the underlying framework is described here.

You place your new class(es) in a separate directory, and at the end submit the solution by zipping that directory and mailing it as an attachment. Please don't interfere with the 117raster project source files: if you encounter a bug in the base classes (to be more specific, a severe bug which makes it absolutely necessary to alter the project code), please contact us immediately, and we will fix it ourselves so that all lab participants can benefit from the bugfix.

Demo code

A simple placeholder module for globally re-colouring an image using the HSV color system is provided (it conforms to interface IRasterModule), and is located in the modules/HSV directory. There you will find several files:

ModuleHSV.cs – contains ModuleHSV, which implements interface IRasterModule. The module works with one input and one output image, and has a number of parameters:

  • dHHue change in degrees (the given angle is added to the hue angle of each pixel)
  • mulS – multiplies the Saturation by a constant factor
  • mulV – multiplies Value by a constant factor
  • gamma – the exponent for gamma correction. The input value is converted to the range [0.0, 1.0], and the exponent 1 / gamma is applied to it. Exponent values larger than 1 lighten the image, while values smaller than 1 darken it.
  • par – should multi-core computing be used (on CPUs with more than 1 core)?
  • slow – use a slow but reliable pixel access system (GetPixel / SetPixel)

The last two parameters only determine the implementation of the algorithm: it is possible to switch between a very slow calculation using the GetPixel / SetPixel functions, and a calculation with direct access to the binary representation of a picture in memory (pointers, "unsafe" solution). Only the second variant can be accelerated on multicore CPUs by turning on parallelisation (Parallel.For).

The re-colouring algorithm in the demo module is simple: without exception, all pixels of the input image are treated and written to the output image. Your task will be to implement some more complex technique, where all those pixels which are on faces will be exempt from the hue shift.

FormHSV*.cs – a form for entering color conversion parameters. All the above parameters can be entered interactively, the form can also be used to run the calculation directly, without having to return to the main application form.

Solution Suggestions

The color transformation in our framework uses the HSV color representation as an intermediate step. Each pixel must be read from the input bitmap (which uses RGB), then converted to HSV, then have its hue angle H modified, and finally the modified HSV is transformed back to RGB and stored in the result image. By leaving S (Saturation) and V (Value) unchanged, all shadows, reflections, and other image structure elements will be retained: only the targeted Hue change will take place.

You do not have to implement colour conversions yourself, various conversion functions between RGB and HSV are provided in the application framework: ColorToHSV(), HSVToColor(), RGBtoHSV(), HSVtoRGB()... Pay attention to the comments in the source code: there are small differences between them.

Portrait-preserving image re-colouring means that you will need to define a range of skin tone input colours that will not be affected by the transformation: that way, any faces that are in the picture will not be affected by the hue shift. One approach is to examine (for example, via a local HSV histogram) which colour ranges actually make up skin tones, and then add a suitable condition to the re-colouring algorithm.

Ideally, the re-colouring behaviour can be configured using parameters (taken from the "Param" text box and / or in your form).

If you devise and implement some "fuzzy" pixel handling condition, you can achieve very nice results and get extra bonus points. Try to play with your selective coloring a little bit in your algorithm.
"Fuzzy" pixel handling condition – pixels are divided into three categories: A. completely re-coloured, C. completely protected (left alone) and B. partially re-coloured (e.g. determined by a P between 0.0 and 1.0). If you propose a suitable transition between A.-B.-C. (continuous change of constant P), the results should improve considerably compared to a fixed two-category solution.

The text parameter Param

Parsing parameters from the text field: You may use functions from the supporting library Util. An example is given in the pilot implementation: Util.ParseKeyValueList( param ); first breaks the text into comma-separated sections, and then searches for definitions in the form <key>=<value>. See the pilot implementation example (the function bool Util.TryParse( p, "name", ref val ) returns true if the key was found, and the val parameter is overwritten at the same time.)

For an example of how to use this functionality, see the example code in ModuleHSV. All parameters are stored in instances of class ModuleHSV, and are modified both via Param, as well as the special input form FormHSV.

What to hand in

At minimum, you have to hand in your new class - the module (the descendant of DefaultRasterModule) which contains your re-colouring functionality, along with any other classes that you have implemented in a separate directory. Submit the solution by zipping the entire directory, and mailing it to your tutor as an attachment. Do not interfere with the 117raster project source files - your solution has to be a stand-alone module that plugs into an unmodified 117raster framework!

Recommended alternative

You can also implement your solution in similar fashion as in the previous assignment 123. Specifically both variations of CS-script and module based on modules/Formula/ModuleFormulaInternal.cs template are acceptable. Nonetheless all notes above apply - you have to add parameters of your re-colouring algorithm and their parsing into the formula.contextCreate method and its implementation into the formula.pixelTransform0 method. If you use this implementation approach, send in only a single file with your implementation (CS-script or the module .cs file).


The solution is due: 14. 11. 2021


8 points for a working solution,
up to 4 bonus points for creative or technically outstanding solution.


Visual Studio project: 117raster

Source file

A zipped sub-directory which can be used in the 117raster project.

Copyright (C) 2010-2021 J. Pelikán & V. Tázlar, last change: 2021-10-24 16:37:45 +0200 (Sun, 24 Oct 2021)