Python 从列中的类似值创建嵌套字典,并使用value作为键,因为字典包含具有该值的所有行
全部,, 我有一个图像中边界框的数据框,每个框都在一个单独的行中。我要做的是为一个特定的图像合并所有的行Python 从列中的类似值创建嵌套字典,并使用value作为键,因为字典包含具有该值的所有行,python,pandas,dictionary,Python,Pandas,Dictionary,全部,, 我有一个图像中边界框的数据框,每个框都在一个单独的行中。我要做的是为一个特定的图像合并所有的行 image xmin ymin xmax ymax label 0 bookstore_video0_40.jpg 763 899 806 940 pedestrian 3 bookstore_video0_40.jpg 1026 754 1075 797 pedestrian 4 bookst
image xmin ymin xmax ymax label
0 bookstore_video0_40.jpg 763 899 806 940 pedestrian
3 bookstore_video0_40.jpg 1026 754 1075 797 pedestrian
4 bookstore_video0_40.jpg 868 770 927 822 biker
5 bookstore_video0_40.jpg 413 1010 433 1040 pedestrian
21 bookstore_video0_80.jpg 866 278 917 328 pedestrian
22 bookstore_video0_80.jpg 761 825 820 865 biker
我想的是,也许可以把它做成一个单级嵌套字典,注意,我对任何解决方案都持开放态度,而不是像这样固定在字典里
{'bookstore_video0_40.jpg': {'xmin': 1066, 'ymin': 802, 'xmax': 1093, 'ymax': 829, 'label': 'pedestrian'}
但所有行数据都以图像名称为键。我的最终目标是将其传递给一个函数,该函数将按顺序将每一行的数据写入一个文件。
尽管如此,我还是不知道如何将数据分组成块。我做了groupby“图像”,但我不知道如何将这些数据转换成我想要的东西。有人有想法吗?我很确定这很容易,我环顾了四周,但我看到的大多数回答都是针对更复杂的问题。提前感谢。您可能需要使用dict,并在groupby上应用元组/列表: 这个怎么样
new_dict = df.set_index('image').stack().groupby('image').apply(list).to_dict()
print(new_dict)
{'bookstore_video0_40.jpg': [763,
899,
806,
940,
'pedestrian',
1026,
754,
1075,
797,
'pedestrian',
868,
770,
927,
822,
'biker',
413,
1010,
433,
1040,
'pedestrian'],
'bookstore_video0_80.jpg': [866,
278,
917,
328,
'pedestrian',
761,
825,
820,
865,
'biker']}
我想这样做是作为一个评论,而不是一个答案,但问题太长了:
我写过一个voc作家。我只需要能够传递数据,这样我就可以在上面循环。我有一个不同的数据集,在那里我做了一些类似的事情,但数据已经是一种易于使用的形式。对于我的项目,我花了很多时间编辑、清理、转换等数据。对我来说不好玩这里是一个基于您的示例的工作示例,除了读取实际的XML文件。非常感谢你。我怀疑你的答案会有用,因为这是机器视觉的人在切割已经注释过的4K图像时遇到的问题
import sys
import glob
import numpy as np
import pandas as pd
from lxml import etree
from pathlib import Path, PurePosixPath
from xml.etree import ElementTree as ET
df = pd.DataFrame(dict(
image = '40.jpg 40.jpg 40.jpg 40.jpg 80.jpg 80.jpg'.split(),
xmin = [763, 1026, 868, 413, 866, 761],
ymin = [899, 754, 770, 1010, 278, 825],
xmax = [806, 1075, 927, 433, 917, 820],
ymax = [940, 797, 822, 1040, 328, 865],
label = 'pedestrian pedestrian biker pedestrian pedestrian biker'.split(),
))
for img in df['image'].unique():
img_df = df[df['image']==img].drop(columns = 'image').reset_index()
boxes = range(img_df.shape[0])
print(img, '\n', img_df)
# Ideally your custom voc writer can be inited here
# with something like:
image = img
# v_writer = VocWriter(f'path/{img[:-4]}.xml')
print("New custom VOC Writer instance inited here!")
depth = 3
filepath = PurePosixPath('image')
annotation = ET.Element('annotation')
ET.SubElement(annotation, 'folder').text = str(image)
ET.SubElement(annotation, 'filename').text = str(image)
ET.SubElement(annotation, 'segmented').text = '0'
size = ET.SubElement(annotation, 'size')
ET.SubElement(size, 'width').text = str('0')
ET.SubElement(size, 'height').text = str('0')
ET.SubElement(size, 'depth').text = str('3')
for box in boxes:
xmin = img_df.loc[box,'xmin']
ymin = img_df.loc[box,'ymin']
xmax = img_df.loc[box,'xmax']
ymax = img_df.loc[box,'ymax']
label = img_df.loc[box,'label']
print(xmin, ymin, xmax, ymax)
# Inside of this loop,
# you can add each box to your VocWriter object
# something like:
ob = ET.SubElement(annotation, 'object')
ET.SubElement(ob, 'name').text = str(img_df.loc[box,'label'])
ET.SubElement(ob, 'pose').text = 'Unspecified'
ET.SubElement(ob, 'truncated').text = '0'
ET.SubElement(ob, 'difficult').text = '0'
bbox = ET.SubElement(ob, 'bndbox')
ET.SubElement(bbox, 'xmin').text = str(img_df.loc[box,'xmin'])
ET.SubElement(bbox, 'ymin').text = str(img_df.loc[box,'ymin'])
ET.SubElement(bbox, 'xmax').text = str(img_df.loc[box,'xmax'])
ET.SubElement(bbox, 'ymax').text = str(img_df.loc[box,'ymax'])
# Once you exit that inner loop,
# you can save your data to your .xml file
# with something like:
# v_writer.save(f'path/{img[:-4]}.xml')
print(".xml file saved here!")
fileName = str(img)
tree = ET.ElementTree(annotation)
tree.write("./mergedxml/" + fileName + ".xml", encoding='utf8')
你从哪里知道ie.bookstore\u video0\u 40.jpg的正确属性是什么?因为该图像有多个实例,你会为Xmini选择什么?如果你的最终目标是将所有这些数据写入一个文件,为什么不保持表格式,并通过或或pandas拥有的许多其他文件写入方法之一将其写入csv或xls文件?分组是为了减少文件大小还是什么?我必须将其写入VOC XML格式,其中每一行都是同一图像的边界框。这是机器学习中的一种标准方法,其中图像可能有1到N个边界框。有些应用程序会将该数据转换为类似于您提到的表格数据格式的CSV。其他不同风格的XML。使用XML时,只需编写一次图像名称,然后在不同分支下编写构成该边界框的所有行。当你完成后,你为下一张图片制作了一个新的文件等。对不起,不清楚。你看过这个吗?我以前从来没有用过,但也许你可以用双for循环。第一个循环类似于df['image']中的img。唯一:然后执行writer=Writerpath,width,height部分,然后内部循环将是df[df['image']==img]中的bb,在该循环内部,您可以调用该writer.addObjectbb['label'],bb['xmin'],bb['ymin'],bb['xmax'],bb['xmin'],最后是writer.save'path/to/img.xml'部分,我已经编写了一个voc编写器。我只需要能够传递数据,这样我就可以在上面循环。我有一个不同的数据集,在那里我做了一些类似的事情,但数据已经是一种易于使用的形式。对于我的项目,我花了很多时间编辑、清理、转换等数据。对我来说不好玩哦这很接近。它包括图像名称,但我可以处理。谢谢你的教育,克里斯蒂安。看起来也会有用的。由于列标签已经消失,我必须跟踪位置,但这似乎是另一个好的解决方案。我两个都要玩。非常感谢你,马修。这正是我想要的,而且比我预期的要多得多。给我一点时间,或者明天之前,如果可以的话,我会发布整个工作代码。我真的很感激这一点,因为我从未见过这个python导师网站。谢谢你通知我!看起来很棒!我的想法是1。看起来您将要保存这些.xml文件的文件名将包含原始的.jpg扩展名,即bookstore\u video0\u 40。jpg将保存为bookstore\u video0\u 40.jpg.xml。这更像是一件装饰性的事情,因为操作系统只应使用最后一个扩展名来识别文件类型,但是我认为如果在保存文件之前删除.jpg会更好一些。2您经常调用str函数,这可能是不必要的,但可能我误解了DataFrame中数据的对象类型或编写器的工作方式。
import sys
import glob
import numpy as np
import pandas as pd
from lxml import etree
from pathlib import Path, PurePosixPath
from xml.etree import ElementTree as ET
df = pd.DataFrame(dict(
image = '40.jpg 40.jpg 40.jpg 40.jpg 80.jpg 80.jpg'.split(),
xmin = [763, 1026, 868, 413, 866, 761],
ymin = [899, 754, 770, 1010, 278, 825],
xmax = [806, 1075, 927, 433, 917, 820],
ymax = [940, 797, 822, 1040, 328, 865],
label = 'pedestrian pedestrian biker pedestrian pedestrian biker'.split(),
))
for img in df['image'].unique():
img_df = df[df['image']==img].drop(columns = 'image').reset_index()
boxes = range(img_df.shape[0])
print(img, '\n', img_df)
# Ideally your custom voc writer can be inited here
# with something like:
image = img
# v_writer = VocWriter(f'path/{img[:-4]}.xml')
print("New custom VOC Writer instance inited here!")
depth = 3
filepath = PurePosixPath('image')
annotation = ET.Element('annotation')
ET.SubElement(annotation, 'folder').text = str(image)
ET.SubElement(annotation, 'filename').text = str(image)
ET.SubElement(annotation, 'segmented').text = '0'
size = ET.SubElement(annotation, 'size')
ET.SubElement(size, 'width').text = str('0')
ET.SubElement(size, 'height').text = str('0')
ET.SubElement(size, 'depth').text = str('3')
for box in boxes:
xmin = img_df.loc[box,'xmin']
ymin = img_df.loc[box,'ymin']
xmax = img_df.loc[box,'xmax']
ymax = img_df.loc[box,'ymax']
label = img_df.loc[box,'label']
print(xmin, ymin, xmax, ymax)
# Inside of this loop,
# you can add each box to your VocWriter object
# something like:
ob = ET.SubElement(annotation, 'object')
ET.SubElement(ob, 'name').text = str(img_df.loc[box,'label'])
ET.SubElement(ob, 'pose').text = 'Unspecified'
ET.SubElement(ob, 'truncated').text = '0'
ET.SubElement(ob, 'difficult').text = '0'
bbox = ET.SubElement(ob, 'bndbox')
ET.SubElement(bbox, 'xmin').text = str(img_df.loc[box,'xmin'])
ET.SubElement(bbox, 'ymin').text = str(img_df.loc[box,'ymin'])
ET.SubElement(bbox, 'xmax').text = str(img_df.loc[box,'xmax'])
ET.SubElement(bbox, 'ymax').text = str(img_df.loc[box,'ymax'])
# Once you exit that inner loop,
# you can save your data to your .xml file
# with something like:
# v_writer.save(f'path/{img[:-4]}.xml')
print(".xml file saved here!")
fileName = str(img)
tree = ET.ElementTree(annotation)
tree.write("./mergedxml/" + fileName + ".xml", encoding='utf8')