Python 使用 Pillow 对图像进行多次裁剪,并使用 Bokeh 将图像分组并显示在一行中
Python image multiple crops with Pillow and grouped and displayed in a row with Bokeh
我有以下任务:生成多个图像裁剪,然后将它们分组显示在彼此相邻的行中。
到目前为止,我设法根据坐标生成作物。我不知道如何按行显示图像,按 'User' 分组并按 'Time' 排序。我应该使用 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)
我有以下任务:生成多个图像裁剪,然后将它们分组显示在彼此相邻的行中。 到目前为止,我设法根据坐标生成作物。我不知道如何按行显示图像,按 'User' 分组并按 'Time' 排序。我应该使用 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)