我有以下任务:生成多个图像裁剪,然后将它们按行分组显示。到目前为止,我设法基于坐标生成农作物。我不知道如何按“用户”分组并按“时间”排序以行显示图像。我应该使用Bokeh绘制图像,因为会有更多的图要集成。请帮助!!!
数据框:
#Import libraries
import numpy as np
from numpy import asarray
import pandas as pd
from PIL import Image
import matplotlib as plt
#Create the dataframe
data = {'Time': ['2586', '2836', '2986', '3269', '3702'],
'Map': ['Buc.jpg', 'Buc.jpg', 'Buc.jpg', 'Buc.jpg', 'Buc.jpg'],
'Index': ['9', '10', '11', '12', '13'],
'PSize': ['250', '150', '283', '433', '183'],
'X': ['751', '673', '542', '762', '624'],
'Y': ['458', '316', '287', '303', '297'],
'User': ['u1', 'u1', 'u2', 'u2', 'u2'],
}
columns = ['Time','Map','Index','PSize','X','Y','User']
df = pd.DataFrame (data, columns = columns)
df = df.astype(dtype= {"Time":"int64", "Map":"object","Index":"int64", 'PSize':'int64', 'X': 'int64', 'Y':"int64", 'User':'object'})
df.head()
基于坐标生成农作物:
#Create coordinate and crop the image
imagefile = 'Buc.jpg'
coordinates = list(df[['X', 'Y']].itertuples(index=False, name=None))
psize = 100
img = Image.open(imagefile)
for x, y in coordinates:
box = (x-psize/2, y-psize/2, x+psize/2, y+psize/2)
img.crop(box).show('%s.x%03d.y%03d.jpg'% (imagefile.replace('.jpg',''), x, y))
输出示例:
这样的事情。请注意,运行脚本时,Buc.jpg
必须在当前工作目录中可用。
import numpy as np
import pandas as pd
from PIL import Image
from bokeh.io import show
from bokeh.models import FixedTicker, FuncTickFormatter, ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge
df = pd.DataFrame({'Time': [2586, 2836, 2986, 3269, 3702],
'X': [751, 673, 542, 762, 624],
'Y': [458, 316, 287, 303, 297],
'User': ['u1', 'u1', 'u2', 'u2', 'u2']})
imagefile = 'Buc.jpg'
coordinates = list(df[['X', 'Y']].itertuples(index=False, name=None))
psize = 100
img = Image.open(imagefile).convert('RGBA')
cropped_images = []
for x, y in coordinates:
box = (x - psize / 2, y - psize / 2, x + psize / 2, y + psize / 2)
cropped_images.append(np.array(img.crop(box)).view(np.uint32)[::-1])
df['Image'] = cropped_images
# There's probably a better method to populate `TimeCoord` which I don't know.
df = df.sort_values('Time')
df['TimeCoord'] = 0
for u in df['User'].unique():
udf = (df['User'] == u)
df.loc[udf, 'TimeCoord'] = np.arange(udf.sum())
user_coords = dict(zip(df['User'].unique(), range(df.shape[0])))
df['UserCoord'] = df['User'].replace(user_coords)
p = figure(match_aspect=True)
for r in [p.xaxis, p.xgrid, p.ygrid]:
r.visible = False
# Manually creating a categorical-like axis to make sure that we can use `dodge` below.
p.yaxis.ticker = FixedTicker(ticks=list(user_coords.values()))
p.yaxis.formatter = FuncTickFormatter(args=dict(rev_user_coords={v: k for k, v in user_coords.items()}),
code="return rev_user_coords[tick];")
ds = ColumnDataSource(df)
img_size = 0.8
p.image_rgba(image='Image',
x=dodge('TimeCoord', -img_size / 2), y=dodge('UserCoord', -img_size / 2),
dw=img_size, dh=img_size, source=ds)
p.rect(x='TimeCoord', y='UserCoord', width=img_size, height=img_size, source=ds,
line_dash='dashed', fill_alpha=0)
show(p)