color shift image to match a palette - java

I'd like to know if anyone knows about an algorithm that changes properties like saturation, color, brightness etc. of an Image, such that it matches a color palette, but also still looks good enough.
It would be nice if anyone could share any ideas on how to do that.
My goal is to achieve a better result by doing this, when dithering the image, because my palette only contains 20 color.

When I used my simple C++ dithering on this input image(cropped from yours):
And use distinct colors as palette from this:
I got this output:
The squares in top are the palette used looks like more than 20 colors to me ... As you can see the output is much better than yours but your dithered result looks too pixelated is it downsampled and then zoomed?
Using just 2 shades of R,G,B,C,M,Y and 3 grayscales leads to 15 colors dithering:
The more shades and combinations of RGB the better the result... Here all the combinations of 3 shades 3^3=27 colors:
[Edit1] algorithm
handle each line of image separately
so process your image by horizontal or vertical lines. You need to have a r0,g0,b0 signed temp variable set to zero before processing any line and palette pal[] holding your allowed colors.
for each pixel (of processed line)
extract its r,g,b and add it to r0,g0,b0, then find closest color to (r0,g0,b0) in your palette pal[] and substract chosen r,g,b from r0,g0,b0.
something like this:
for (y=0;y<height;y++)
{
r0=0; g0=0; b0=0;
for (x=0;x<width;x++)
{
// pick and add wanted color
col=pixel(x,y);
r0+=col.r;
g0+=col.g;
b0+=col.b;
// chose closest color
ix=0; col=(r0,g0,b0);
for (i=0;i<palette_size;i++)
if (color_distance(col,pal[i])<color_distance(col,pal[ix]))
ix=i;
col=pal[ix];
// render and substract chosed color
pixel(x,y)=col;
r0-=col.r;
g0-=col.g;
b0-=col.b;
}
}
The choosing of closest color can be significantly speed up by LUT[r][g][b] table.
This approach is fast and simple but far from best visually.

Related

Identifying color ranges

For a project I need to go through all the pixels of an image and identify color ranges. Right now, I've written code that will go through all the pixels and construct an ArrayList of colors for each pixel. Now, I need to figure out a way to go through my ArrayList and identify groupings of colors. For clarification, in all pictures there are really only 3 different "colors". Obviously due to varying brightness across the picture the pixels don't exactly match the RGB values of the 3 different colors. Thus, I need to find a way to identify a range of variation for each of the 3 different colors. My theory is to "construct" a graph of the colors in the ArrayList and identify the color ranges by looking for gaps between color groupings. I'm just not sure how to go about doing this. Any suggestions are welcome!

Calculation of color position between black and white

When you read this title you might automatically think of luminescence,
but that's not what I'm after.
What I want is to have you current color and have it wait on a scale from black to white.
So something like this , and then I would like the current color returned as a percentage of how black or white that color is.
There are different algorithms for converting colors to grayscales. This is an explanation of an algorithm, the Wikipedia article on Grayscale might also lead you to useful ressources.
The implementation you finally choose highly depends on your use case.
What I was looking for was far simpler I kept over thinking this.
Basically just get RGB then get the highest color.
Then do int ColorIntensity = (color / 255) * 100; and that's basically your color intensity in percentage.

algorithm, image processing, flood fill

I am trying to process an X-ray image.
The task is to paint each bone to a different color. I've used canny filter,otsu binarization and Morphological Image Processing such as erosion, to get this effect:
Now I need to find an algorithm to color each bone. I was thinking about using connected-component labeling or flood fill but these algorithms requires closed area which will be filled with a color, but in my image there are also "almost closed" area to color. I was trying to "close each bone" with Dilation but it doesn't work.
And now I completely do not know what to do with it and how to color bones.
You can try to vectorize your image. I have done something similar and after running simple vectorization, connected components were easy to fill.
You can vectorize directly your input by eg. running Marching Squares on it. It will also create edge image.
While this might not be the exact thing you're looking for, I would recommend a simple edge-finding algorithm. The way I would do this (which may not be the best of the most efficient) is to extract the image into a 2D array of pixels. What you can do is compare the RGB values of each pixel to it's neighboring pixel and then color it a brighter color if the difference is higher. To calculate the difference you can use the 3D version of the 2D pythagorean distance formula. Finding the 'distance' between the RGB values and multiplying it by something to keep the values between 0 and 255, then replacing the pixel which you are comparing to it's surrounding pixels with a pixel with the average of this number for the 8 surrounding pixels.
If this is done correctly, it should produce a result similar to, if not identical to the one you present here.

Colour dominance in image and use of histograms

I would like to turn everyone's attention to this question before I begin as I want to do something similar: Getting the most common color of an image
Now, I have tested this and it is effective by filtering out the greys although does it really find us the most significant colours? It finds the most yes, although some greys do still show up.
I personally don't feel its the most efficient way. I have a colour histogram function, for both RGB and HSB and this divide up the space, but where do you go from here
If you want to find the most significant color you can do the following:
Reduce number of colors in image. See this discussion - algorithm is the same.
Cycle throught image and count each color.
Find maximum of that array of colors. This will be your color.

Assigning java colors

I'm building an application in Java where different patches of land consist of set of parcels. I want to color different patches with different color. My map presents patches' parcels. However two patches can have parcels in common. In that case I would like to color those parcels with some intermediate color(mix of two patches' colors). As I don't know how many patches are going to be selected I have to assign random colors to those in a loop. Then I have to resolve colors for those intersected parcels. Any idea about best possible way to do this in java?
For blending the colors, you can get the individual R,G,B values, via either getRed(), getBlue() etc. or getColorComponents(), then take the average for each, then create a new color. You could also average the HSB values. You could also play with alpha (transparency), drawing each original color with an alpha of 0.5. However, at some point all these subtle blendings become difficult for the user to figure out. Instead, you might want to use some pattern (like stripes) with the original colors.
I've experimented with many ways to pick "good" random colors, and haven't had much success. The best technique used HSB values. Lets say you need 5 colors. Divide 360 degrees by 5 and pick hues "around" the color wheel at those angles. This works o.k. if you like really bright fully saturated colors.
IMO, consider hard coding at least the "most common" parcel colors into something that looks good. Pick colors at random as little as possible.
I don't know obvious solution to this problem, but i suppose you can use average rgb components.
For example you have two colors in RGB notation: A(100,0,0) and B(0,100,0). Resulted color will be C(50, 50, 0).
Note: in that case you save invariant "Intersection between two equal colors will be same color"

Categories