Extracting actual values from RGB-bands - python

I have a (geographic) raster-image in RGB. I also have an external legend displaying the heights according to a certain color. In below figure, I have sampled this legend, hopefully revealing its RGB-characteristics. I have plotted these values to their actual height values on the X-axis.
Now, is it possible to directly derive height from the pixel's RGB-value? Ultimately, I'm looking for a simple formula which is able to translate my RGB values into one height value (e.g. H = aR + bG + c*B) Any hint or tips? Is it even possible at all?

Related

Python matplotlib plot background

I want to compare a plot from a paper to my simulation results.
Therefore it would be convenient to plot my results with the ref pic in the background.
the x value range i choose to be the same as the ref pic
y should also be close to the ref pic.
Or i can set the y range also to the same values as the ref pic.
i tryed
x=range(len(P))
plt.plot(x,P)
img=plt.imread("REF.jpg")
plt.imshow(img)
plt.show()
But it chooses the scale i think according to pixels?
and my other plot was a miniature on it.
if i use extend and one dimension is much larger then the other, one can see nothing on the pic because of the bad aspect ratio

Filling Color Gradient between points

I have a bunch of (x,y) type points. Corresponding to these points there is an associated value (within a specific range). These values can be used to put color to them (using some color map).
If we now use these (x,y) and color we can have a pixelated image (with a color pixel at each x,y). Is there an easy way to fill the pixels between so that I get a sensible gradient of colors.
TLDR: How to fill pixels within a boundary when you know values at nearby pixels?
The thing which makes it difficult for me is I have much more pixels to fill than the number of already colored pixels.
Also can I control the gradient type (linear, quadratic etc.)

An alternative to using standard marker for 2D color plot?

At the moment I have a somewhat crude python program that I would like to modify to do the following:
Read in three columns of data from a single file (X,Y,C) which are then plotted as a 2D X,Y scatter plot with the C value representing the color map value. Each X,Y point represents the center of a square box of fixed size which will be colored based on the C value. The X,Y coordinates are such that there won't be any overlapping boxes - although there will be gaps where there are no coordinates. The size of the box will be fixed for each input file (but can vary from one file to the next) and the program is supposed to color in each square box depending on the C value. For instance, the desired plot for one particular input file might have 5,000 X,Y coordinates somewhere in the range X from 1000 to 6000 and Y from 2000 to 7000, with the desired box size being 40, and the color range going from 1 to 1700.
Currently the program is a hack based on using the standard marker to colour each box, so essentially the marker represents the size of the box. It works ok but requires selecting the correct marker size and also adjusting the size of the plot to ensure that boxes (i.e. the markers) fit without gap or overlap. This adjustment is specific to each input file - i.e. the X,Y range and the box size (based on minimum distance between points). So I am thinking how to automate this so that the program can read in any file (regardless of box size) and color in each box without requiring a lot of user input (perhaps box size will need to be entered somewhere) - so I guess not using the standard marker.
Current code:
plt.figure(figsize=(10.0, 10.5))
plt.rcParams['axes.facecolor'] = '#55AAFF' # background color
plt.scatter(X, Y, c=colrsabove, s=marker_size, marker='s', alpha=0.8, cmap='YlOrRd')

Matplotlib: assign an ever different colour

In Matplotlib, I have several sets of points to fill in with different colours, one per set. Now, the number of sets varies, so I would like to make sure that that the same colour doesn't appear more than once in the same plot.
Right now I just do:
colors = itertools.cycle(['r','g','b','c','y','m'])
# ...
ax.plot(Xs_for_a_set, Ys_for_a_set, c=colors.next())
... but I am limited to that number of colors. From the documentation I don't get how to specify a random color in RGB...
You can specify the color as a hex value in a string.
color = '#eeefff'
Using this you essentially have access to all colors via RGB and can create as many colors as you need

guessing the rgb gradient from a map?

I have a map with a scale like this one: (the numbers are just an example)
which describes a single variable on a map. However, I don't have access to the original data and know pretty close to nothing
about image processing. What I have done is use PIL to get the pixel-coordinates and RGB values of each point on the map. Simply using pix = im.load() and saving pix[x,y] for each x,y. Now I would like to guess the value of each point using the gradient above.
Is there a standard formula for such a gradient? Does it look very familiar to the trained eye? I have visited Digital Library of Mathematical Functions for some examples ... but I'm not sure if it's using the hue, the rgb height function or something else (to make things easier I'm also colorblind to some greens/brows/reds) :)
Any tips on how to proceed, libraries, links or ideas are appreciated. Thank you!
edit:
Following the replies and martineau's suggestion, I've tried to catch the colors at the top and bottom:
def rgb2hls(colotup):
'''converts 225 based RGB to 360 based HLS
`input`: (222,98,32) tuple'''
dec_rgb = [x/255.0 for x in colotup] # use decimal 0.0 - 1.0 notation for RGB
hsl_col = colorsys.rgb_to_hls(dec_rgb[0], dec_rgb[1], dec_rgb[2])
# PIL uses hsl(360,x%,y%) notation and throws errors on float, so I use int
return (int(hsl_col[0]*360), int(hsl_col[1]*100), int(hsl_col[2]*100))
def pil_hsl_string(hsltup):
'''returns a string PIL can us as HSL color
from a tuple (x,y,z) -> "hsl(x,y%,z%)"'''
return 'hsl(%s,%s%%,%s%%)' % (hsltup[0], hsltup[1], hsltup[2])
BottomRed = (222,98,32) # taken with gimp
TopBlue = (65, 24, 213)
hue_red = pil_hsl_string(rgb2hls(BottomRed))
hue_blue = pil_hsl_string(rgb2hls(TopBlue))
However they come out pretty different ... which makes me worry about using the rgb_to_hls function to extract the values. Or I'm I doing something very wrong? Here's what the color s convert to with the code:
Interesting question..
If you do a clock-wise walk in HSL color-space from 250,85%,85% --> 21,85%,85% you get a gradient very close to the one you've shown. The obvious difference being that your image exhibits a fairly narrow band of greenish values.
So, if you have the 4 magic numbers then you can interpolate to any point within the map.
These of course being the first and last colour, also the first and last scale value.
Here's the image I got with a straight linear gradient on the H channel (used the gimp).
EDIT: I've since whipped up a program to grab the pixel values for each row, graphing the results. You can see that indeed, the Hue isn't linear, you can also see the S & V channels taking a definite dip at around 115 (115 pixels from top of image) This indeed corresponds with the green band.
Given the shape of the curves, I'm inclined to think that perhaps they are intended to model something. But don't have the experience in related fields to recognise the shape of the curves.
Below, I've added the graphs for the change in both the HSV and RGB models.
The left of the graph represents the top of the bar.
The X-axis labels represent pixels
Quite interesting, me thinks. Bookmarked.
The scale in the image looks like an HSV gradient to me, something like what is mentioned in this question. If so, you could use the colorsys.rgb_to_hls() or colorsys.rgb_to_hsv() functions to obtain a hue color value between 0 and 1 from the r,g,b values in a pixel. That can then be mapped accordingly.
However, short of doing OCR, I have no idea how to determine the range of values being represented unless it's some consistent range you can just hardcode.
I would recomend to define an area where you want to compare the colour. Take an FFT of the regions. Each colour is defined by a frequency. You do the same on the countour scale. then compare and narrow on a value.
I have found some like to understand it better.
http://www.imagemagick.org/Usage/fourier/
You can get something like that by varying the hue with a fixed saturation and luminance.
http://en.wikipedia.org/wiki/HSL_and_HSV

Categories

Resources