Create an image from a dataframe using Python

1

I am trying to create an image of a specific size of pixels and draw in it several trajectories that I have ordered in a dataframe by x and y coordinates. An example of how the dataframe looks with 2 trajectories would be like this:

In [60]: df
Out[60]: 
TRACK_ID     x            y                        
1          16.130       8.993
1          15.817       8.699
1          16.076       8.712
1          16.176       8.191
1          16.486       8.106
2          16.308       8.500
2          16.270       8.441
2          16.042       8.474
2          15.966       8.487
2          15.882       8.431
2          15.869       8.419

Next, I use PIL to generate the image:

from PIL import Image
from PIL import ImageDraw
img = Image.new("RGB", (512,512), "black")
draw = ImageDraw.Draw(img)

coords = ['x','y']
dotSize = 2

for (x,y) in coords:
    draw.line([x,y,x+dotSize-1,y+dotSize-1], fill="red")

img.show()

This works fine for points (x, y) but I must enter one by one, how can I do to enter my complete columns as independent paths? Is there a simpler way to pass my columns to a binary image? Thanks

    
asked by Jonathan Pacheco 18.09.2017 в 22:30
source

2 answers

1

You can use pandas.groupby to get each trajectory based on the value of the TRACK_ID column. Done this you only have to iterate on the object groupby and for each group create an iterable of tuples (x, y) to pass it to draw.line . You can do this last with zip .

If you want, you can create another iterable one to draw each group with a different color. A very simple option is to create a cyclic color map using itertool.cycle . You can use RGB or HSL values to define colors, however, it is usually simpler to use HTML color names ( More information at link )

For example, we are going to create a dataframe similar to yours (the points will be further distanced to be more descriptive) and we will create a line for each trajectory of a different color:

import itertools
import pandas as pd
from PIL import Image
from PIL import ImageDraw


data = {"TRACK_ID": [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4],
        "x": [10, 75, 50, 300, 400, 12, 17, 27, 30, 45, 40, 15, 65, 400, 19, 45, 234],
        "Y": [10, 75, 50, 300, 500, 10, 105, 200, 100, 305, 420, 17, 47, 176, 20, 165, 375]}

df = pd.DataFrame(data)
df.set_index("TRACK_ID", inplace = True)


# Lo anterior es solo para crear un DataFraem como el tuyo,
# lo importante es lo siguiente:
tracks = df.groupby("TRACK_ID")

img = Image.new("RGB", (512,512), "black")
draw = ImageDraw.Draw(img)
colors = itertools.cycle(("Red", "Chartreuse", "DarkOrange", "DarkMagenta"))

for t, group in tracks:
    coords = tuple(zip(group.x, group.Y))
    draw.line(coords, width=2, fill=next(colors))


img.show()

Exit:

You can also define the colors in a dictionary, the key being each value of TRACK_ID , so you can define precisely with which color each path is drawn.

    
answered by 19.09.2017 / 00:11
source
0

Let's see, first of all, when you do this:

dotSize = 2
for (x,y) in coords:
    draw.line([x,y,x+dotSize-1,y+dotSize-1], fill="red")

You are practically drawing each point, in reality, lines with a displacement of one pixel for each coordinate that you have. What you really should do, is, draw the complete line with the list of tuples of coordinates, ie invoke draw.line with that list. Something like that by way of example

from PIL import Image
from PIL import ImageDraw
img = Image.new("RGB", (512,512), "black")
draw = ImageDraw.Draw(img)

coords = [
  (100, 100),
  (150, 200),
  (300, 100),
  (400, 300),
]

dotSize = 2
draw.line(coords, width=dotSize, fill="red")
img.show()

This would be the exit:

    
answered by 18.09.2017 в 23:10