How to change white background for black


In a recent project I have to manipulate images, but since this is new to me I am kind of lost.

I need to scan the hand using a regular scan device. I could acomplish this but the background is white and I need it to be black. After several days of research finding the way to change the color, I only got an image that seems cut and paste in ms paint.

The original image:

<a href="https://s31.postimg.org/4oe0xvjx7/Scan.jpg" rel="nofollow"><img alt="Raw Scan of the hand" class="b-lazy" data-src="https://s31.postimg.org/4oe0xvjx7/Scan.jpg" data-original="https://s31.postimg.org/4oe0xvjx7/Scan.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>


<a href="https://s31.postimg.org/7pdpgr5p7/test.jpg" rel="nofollow"><img alt="Raw Scan of the hand" class="b-lazy" data-src="https://s31.postimg.org/7pdpgr5p7/test.jpg" data-original="https://s31.postimg.org/7pdpgr5p7/test.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

What I need is something like this:

<a href="https://s31.postimg.org/4ti8qx863/pies1.jpg" rel="nofollow"><img alt="Target image" class="b-lazy" data-src="https://s31.postimg.org/4ti8qx863/pies1.jpg" data-original="https://s31.postimg.org/4ti8qx863/pies1.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

I trying using <a href="http://marvinproject.sourceforge.net" rel="nofollow noreferrer">Marvin Framework</a>, <a href="https://imagej.nih.gov/ij/" rel="nofollow">Imagej</a>, <a href="http://catalano-framework.com/" rel="nofollow">Catalano</a> framework. To see the setps that I need I use gimp, marving editor, fiji app (but without getting the result I was looking for).<br /> I think what I need is to convert to gray scale, apply some sort of threshold but in a certain range of colors use alpha colors (but I did not find the way, only threshold for binary images), and then apply a mask into the original using the threshold grayscaled image, but again I don't know how to do that, in Java directly, or using any of the frameworks I mentioned above.<br /> Any help would be appreciated.

<strong>UPDATE</strong> Based on what m69 said, i tried playing whith luminiscent value, converting from rgb to hsl. I only set darker colors which were lighten.

First try with a threshold of 0.5 of light:

<a href="https://i.stack.imgur.com/Tp1VA.png" rel="nofollow"><img alt="First try" class="b-lazy" data-src="https://i.stack.imgur.com/Tp1VA.png" data-original="https://i.stack.imgur.com/Tp1VA.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

Second try with a a threshold of 0.9 of light

<a href="https://i.stack.imgur.com/tVGSu.png" rel="nofollow"><img alt="Second try" class="b-lazy" data-src="https://i.stack.imgur.com/tVGSu.png" data-original="https://i.stack.imgur.com/tVGSu.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

float threshold = 0.5f; for(int y=0; y<imageIn.getHeight(); y++){ for(int x=0; x<imageIn.getWidth(); x++){ int r = imageOut.getIntComponent0(x, y); int g = imageOut.getIntComponent1(x, y); int b = imageOut.getIntComponent2(x, y); float[] hsl = HSLColor.fromRGB(r, g, b, null); if(hsl[2] >= threshold){ float t = (hsl[2]-0.5f)*2f; hsl[2] -= t; imageOut.setIntColor(x, y, HSLColor.toRGB(hsl)); } } }

The problem is that this approach changes the light of all pixels, the ideal is to change only color outside of the object. I was looking for a ideas on the internet and i found a thesis by Martin Janík for orthopaedic analisis. He proposes the next algorithm:

<ol><li>apply Gaussian filtering to the feet scan to get filtered image</li> <li>threshold the filtered image to get binary image</li> <li>morphologically close the binary image to get closed binary image</li> <li>apply Gaussian filtering to the binary image to get grayscale mask</li> <li>apply this mask to the feet scan to get overall foot image</li> </ol>

And with this i can get the next result:

<a href="https://i.stack.imgur.com/oyKtU.png" rel="nofollow"><img alt="Martin Janík algorithm" class="b-lazy" data-src="https://i.stack.imgur.com/oyKtU.png" data-original="https://i.stack.imgur.com/oyKtU.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

And this is close to what i want, because colors in the object are not touched. But still one problem the white border around the object. This is because i am using combineByMask marving plugin and it just support binary images (well not just binary images but only can mask one color). I think a new plugin is needed to combine using a grayscale image mask, when the color were in the range 1-255 try to combine to the image base to get a darker or lighten color (obiously when the color is 255, it should leave just the color of the base image).

This is an example image of what i am talking about masking grayscale images:

<a href="https://i.stack.imgur.com/bNKC3.png" rel="nofollow"><img alt="Example image apply a mask using a binary image and a grayscale image" class="b-lazy" data-src="https://i.stack.imgur.com/bNKC3.png" data-original="https://i.stack.imgur.com/bNKC3.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

I think this is the path i am going to take.

<strong>UPDATE 2</strong>

After doing some research, i think i am close to the result i want. The algorithm i used was:

<ol><li>Apply a contrast of five</li> <li>Convert to gray image</li> <li>Apply gaussian filter</li> <li>Threshold the image</li> <li>Morphological close</li> <li>Applay a gaussian filter again</li> <li>Use this result image as a grayscale mask to the original</li> </ol>

This is the result image:

<a href="https://s32.postimg.org/f8i7ltjnp/image.png" rel="nofollow"><img alt="Result apply a grayscale mask" class="b-lazy" data-src="https://s32.postimg.org/f8i7ltjnp/image.png" data-original="https://s32.postimg.org/f8i7ltjnp/image.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

This is close to what i want. In the six step i could apply two, three or more times a gaussian filter, given a more soft border effect, but in the end a thin white border is always displayed because of the nature of scanned image (i think this is something i can not deal with) but i am comfortable with this result. Now as i did not found a java algorithm to apply a grayscale mask, i code this:

for(int y=0; y<mask.getHeight(); y++){ for(int x=0; x<mask.getWidth(); x++){ //ya que está en grayscale, los 3 valores son los mismos int r1 = mask.getIntComponent0(x, y); int g1 = mask.getIntComponent1(x, y); int b1 = mask.getIntComponent2(x, y); int r2 = image.getIntComponent0(x, y); int g2 = image.getIntComponent1(x, y); int b2 = image.getIntComponent2(x, y); //al color de salida, le asignamos la luminicencia de la imagen mascara int r = 0, g = 0, b = 0; if(r1 > 0 || r2 > 0){ r = r1*r2/Math.max(r1, r2); } if(g1 > 0 || g2 > 0){ g = g1*g2/Math.max(g1, g2); } if(b1 > 0 || b2 > 0){ b = b1*b2/Math.max(b1, b2); } image.setIntColor(x, y, r, g, b); } }

And work almost very well, but with a little tiny detail that i can not resolve. The idea is to mix the images as in gimp i did the following: having the grayscale mask in a upper layer, apply a color to alpha function to the white color, give this result:

<a href="https://s32.postimg.org/p45k3rxs1/image.png" rel="nofollow"><img alt="Gimp mix" class="b-lazy" data-src="https://s32.postimg.org/p45k3rxs1/image.png" data-original="https://s32.postimg.org/p45k3rxs1/image.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

With the algorithm i wrote for marving framework, i get the next image:

<a href="https://s32.postimg.org/u8tfzjni9/image.png" rel="nofollow"><img alt="Using marving" class="b-lazy" data-src="https://s32.postimg.org/u8tfzjni9/image.png" data-original="https://s32.postimg.org/u8tfzjni9/image.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

The difference is that my algorithm can not low the intensity color when there is a more white color on the original image, you can see that effect comparing the 2 images. Any idea how to deal with it? This is the image result after applying the layer combination in gimp:

<a href="https://s32.postimg.org/pog1g9e4l/image.png" rel="nofollow"><img alt="Layer combination en gimp" class="b-lazy" data-src="https://s32.postimg.org/pog1g9e4l/image.png" data-original="https://s32.postimg.org/pog1g9e4l/image.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>


Your best bet is to go into photo shop or GIMP and use the quick mask feature paint in or out what you want and you can get very detailed down to the pixel then exit quick mask mode and make sure the white is the part your marching ants are around and delete it from there go ahead and fill a layer for black with background. You may have use a slight feather on the edges to blend it in naturally. There are more specific tutorials on how to do this but that is how I would approach it.


The approach depends on the purpose of your analysis. The first approach affects the entire image, therefore the texture of the palm of the hand is changed! The second approach only affects the hand border!

The both approaches were developed using <a href="http://marvinproject.sourceforge.net/" rel="nofollow">Marvin Image Processing Framework</a>.

<strong>INPUT :</strong>

<a href="https://i.stack.imgur.com/8apOh.jpg" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/8apOh.jpg" data-original="https://i.stack.imgur.com/8apOh.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

<strong>APROACH 1:</strong>

As sugested by user m69, a color tranformation based on the gray scale values.


<a href="https://i.stack.imgur.com/WHLSA.jpg" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/WHLSA.jpg" data-original="https://i.stack.imgur.com/WHLSA.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>


import marvin.image.MarvinImage; import marvin.io.MarvinImageIO; public class ScanTest { public static void main(String[] args) { MarvinImage image = MarvinImageIO.loadImage("./res/scan.jpg"); int r,g,b; for(int y=0; y<image.getHeight(); y++){ for(int x=0; x<image.getWidth(); x++){ r = image.getIntComponent0(x, y); g = image.getIntComponent1(x, y); b = image.getIntComponent2(x, y); int gray = (int)((0.22*r)+(0.7*g)+(0.08*b)); double t = transform(gray, 1.3); image.setIntColor(x, y, (int)(r*t), (int)(g*t), (int)(b*t)); } } MarvinImageIO.saveImage(image, "./res/scan_out.jpg"); } private static double transform(int gray, double brightness){ if(gray < 127){ return brightness; } else{ return (1-((double)(gray-127)/128))*brightness; } } }

<strong>APROACH 2:</strong>

You can use HSV collor model to darken bright areas of the image considering some saturation and value threshold. This approach does not affect the texture of the palm of the hand.


<a href="https://i.stack.imgur.com/WsW6w.jpg" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/WsW6w.jpg" data-original="https://i.stack.imgur.com/WsW6w.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>


public class ScanTest { public static void main(String[] args) { MarvinImage image = MarvinImageIO.loadImage("./res/scan.jpg"); int r,g,b; int rgb[] = new int[1]; double hsv[]; for(int y=0; y<image.getHeight(); y++){ for(int x=0; x<image.getWidth(); x++){ r = image.getIntComponent0(x, y); g = image.getIntComponent1(x, y); b = image.getIntComponent2(x, y); rgb[0] = image.getIntColor(x, y); hsv = MarvinColorModelConverter.rgbToHsv(rgb); if(r >= 235 && g >= 235 && b >=235){ image.setIntColor(x, y, 0,0,0); } else if(hsv[1] <= 0.12 && hsv[2] >= 0.6){ double diff = 1-hsv[2]; if(diff > 0.02){ diff = Math.max(diff,0.2); } diff*=3; image.setIntColor(x, y, (int)(r*diff), (int)(g*diff*0.75), (int)(b*diff*0.75)); } } } MarvinImageIO.saveImage(image, "./res/scan_out.jpg"); } }


You should probably start by converting RGB to HSL (Hue, Saturation, Luminance/Brightness) and then apply a curve to the luminance so that values above a certain level (too bright) gradually go back to black again. Exactly up to which point the luminance should follow the diagonal before dropping off would depend on the lightness and contrast of the photos. (I'm guessing these are probably standard functions in graphics frameworks.)

Here are two examples of curves applied to luminance to demonstrate the kind of result you'd get:

<a href="https://i.stack.imgur.com/dYPZk.png" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/dYPZk.png" data-original="https://i.stack.imgur.com/dYPZk.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a> <a href="https://i.stack.imgur.com/JE6GP.png" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/JE6GP.png" data-original="https://i.stack.imgur.com/JE6GP.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>


This might seem like a really stupid suggestion, but can you scan your hand with the scanner lid open? The only reason you have a white background is because the inside lid of the scanner is white and is reflecting light from the scanner itself. If you open the lid and scan your hand in a dark room, you should have an effect that is very close to the photo of feet you referenced.

Not a software solution, but it might get you closer to your desired result. It could also help with the oversaturation on your index and middle fingers.


  • PHP - How to replace all instances of words in a string
  • How to get the distance to an object and size of the object using the camera (Android device)?
  • Possible to measure distance with an iPhone and laser pointer?
  • How to convert images color space in Keras?
  • Javascript: adding an integer and decimal giving wrong answer
  • Can I use entities without context?
  • how can i know if the image is in RGB or BGR format?
  • modernizr check for grayscale filters IE 10
  • basic.Nack not being processed
  • smoothing image in Matlab
  • Javascript and VERY LONG string
  • overhead of reserving address space using mmap
  • How to hide header on specific page in wordpress
  • Configuration class - Get configuration array from the function string argument
  • Android Studio 2.0 - this version of Android Studio is incompatible with the Gradle Plugin used. Try
  • Escape exclamation mark in batch file
  • SQL how to do an outer join properly
  • How do I include superscripts in NSString?
  • Is it possible to collect a stream to two different collections using one line?
  • Quickly find the min and max coordinates of connected component in a large image
  • Finding for convolution kernel if many 0's for FFT?
  • K-means in OpenCV's Python interface
  • Waiting for $.post to finish
  • How to update powerpivot pivot table filter via cell reference?
  • VBScript to check for open process by user
  • Unable to run SDL program in Eclipse but able to do so in Windows Explorer
  • Return to second to last URL in MVC (return View with previous filter conditions applied)?
  • date format change with DT and shiny
  • How do I translate LR(1) Parse into a Abstract syntax tree?
  • SQL Query - Table Joining Problems
  • C# fibonacci function returning errors
  • bad substitution shell- trying to use variable as name of array
  • converting text file into xml using php?
  • How to run “Deployd” on port 80 instead of port 5000 in webserver.
  • Android full screen on only one activity?
  • Resize panoramic image to fixed size
  • TFS: Get latest causes slow project reloading
  • Running a C# exe file
  • Weird JavaScript statement, what does it mean?
  • Reading document lines to the user (python)