Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Colour picking from a curvy line

I have an image that looks equivalent to this image:

this.

It is a series of circles on a page in a curvy line, and the line is different every time.

from PIL import Image
im = Image.open("bride.jpg")

After importing it, I was wondering if there was a way of distinguishing the colours. For the example this might be:

[Purple, Cyan, Purple, Cyan, Purple Cyan...]

The line has no pattern to it, and is several thousand circles long, which means that it cannot be done manually. Also note that the image I'm actually testing on is of much higher quality, the actual image can be found here.

like image 451
Alexander Craggs Avatar asked Dec 22 '14 10:12

Alexander Craggs


2 Answers

Just create a list of RGB values along the line and then filter the list to remove like-adjacent values.

Get pixel's RGB using PIL

#find RGB values   
rgb_values = []
for point in line:
   r, g, b = rgb_im.getpixel(point)
   rgb_values += [ (r,g,b)]
#remove similar adjacent values
for i in range(len(rgb_values)-1):
    if rgb_values[i] == rgb_values[i+1]:
        rgb_values.pop(i)
        i -= 1
if len(rgb_values) > 1:
    if rgb_values[-1] == rgb_values[-2]:
         rgb_values.pop(-1)
like image 77
mattsap Avatar answered Nov 09 '22 06:11

mattsap


I think the main problem for you is to find a good path of pixels to follow from one end of your curve to the other. Once you have decided this path, you can just follow it and check the pixel colors as you go.

For now, I would suggest you input the path yourself by specifying a set of waypoints. Here is some code for your example figure. I took the first point in the left purple disc, the second at the angle, and the last one in the bottom-right purple disc.

from PIL import Image
from numpy import array, arange

im = Image.open("aqoGkjs.png")
rgb_im = im.convert('RGB')

def get_color_at(p):  # color function as mattsap suggested
    r, g, b = rgb_im.getpixel(tuple(p))
    if r > g and r > b:
        return 'Purple'
    elif r < 10 and g < 10:
        return 'Blue'
    return 'Cyan'

colors = []
via_points = [array([25, 65]), array([185, 44]), array([240, 210])]

for i in xrange(len(via_points) - 1):
    for x in arange(0, 1, 0.01):
        p = x * via_points[i] + (1 - x) * via_points[i + 1]  # linear interpolation
        cur_color = get_color_at(p)
        if cur_color == 'Blue':  # ignore borders
            continue
        if not colors or cur_color != colors[-1]:
            colors.append(cur_color)

print colors

It prints:

 ['Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple', 'Cyan', 'Purple']

For your big image, you can input all the waypoints by hand. Or try to make a smart piece of code to find them automatically ;)

like image 25
Tastalian Avatar answered Nov 09 '22 06:11

Tastalian