Given two lists of dictionaries, such as -
poo = [{
"xmin":10,
"ymin":100,
"xmax":70,
"ymax":120,
"text":"fish",
}]
And also
foo = [{
"class":"Animal",
"percent":88.25,
"box_points":[30, 90, 80, 110]
}]
To produce an output like:
poofoo = [{
"class":"Animal",
"text":"fish",
"percent": 88.25,
"box_points":{
"xmin":10,
"ymin":90,
"xmax":80,
"ymax":120}
]}
Knowing that the
box_points
infoo
list of dictionaries is also in the formatxmin, ymin, xmax, ymax
. These box points are coordinates of bounding boxes detected by the system.
How could one access the nested elements, compare them and then merge the elements? The idea is to merge them if they are spatially close, in this example, a threshold of 10 units (x,y).
I already tried this:
def boxOverlap(box1, box2):
try:
if(box1[0]<=box2[2] and box1[0]>=box2[0]) \
or (box1[1]<=box2[3] and box1[1]>=box2[3]):
return True
else:
return False
except TypeError:
print(f"{message_error}")
final_json = []
for el1, el2 in zip(foo, poo):
el1_box_format = [el1['x_min'], el1['y_min'], el1['x_max'], el1['y_max']]
if(boxOverlap(el1_box_format, el2['box_points'])):
final_json.append({"class":el2["name"],
"text":el1["text"],
"confidence":el2["percentage_probability"],
"boxpoints":None
})
Note that, I created a function to return a boolean if the boxes overlap or not (later I will implement the threshold). But the problem is, I want to compare the dictionaries only if they are spatially close, and right now, as I am using zip(foo, poo)
it operates only in pairwise elements.
CodePudding user response:
A simple solution would look like below.
poo = [{
"xmin": 10,
"ymin": 100,
"xmax": 70,
"ymax": 120,
"text": "fish",
}]
foo = [{
"class": "Animal",
"percent": 88.25,
"box_points": [30, 90, 80, 110]
}]
def merge(p: dict, f: dict):
coords = list(p.values())[:-1]
box_coords = f.get("box_points")
box_points = {"xmin": min(coords[0], box_coords[0]),
"ymin": min(coords[1], box_coords[1]),
"xmax": max(coords[2], box_coords[2]),
"ymax": max(coords[3], box_coords[3]),
}
f['box_points'] = box_points
f['text'] = p.get('text')
return f
poofoo = [merge(poo[index], foo[index]) for index in range(len(poo))]
Output:
[
{
"class": "Animal",
"percent": 88.25,
"box_points": {
"xmin": 10,
"ymin": 90,
"xmax": 80,
"ymax": 120
},
"text": "fish"
}
]
This assumes the length of both list are same, the order of coordinates are also same all the way.
CodePudding user response:
This is not a really general solution, for this too much was unclear to me.
poo = [{
"xmin":10,
"ymin":100,
"xmax":70,
"ymax":120,
"text":"fish",
}]
foo = [{
"class":"Animal",
"percent":88.25,
"box_points":[30, 90, 80, 110]
}]
foo[0]["xmin"] = foo[0]["box_points"][0]
foo[0]["ymin"] = foo[0]["box_points"][1]
foo[0]["xmax"] = foo[0]["box_points"][2]
foo[0]["ymax"] = foo[0]["box_points"][3]
foo[0].pop("box_points")
poofoo = [{}]
for kp in poo[0]:
for kf in foo[0]:
if kp == kf:
if kp not in poofoo[0]:
if abs(poo[0][kp] - foo[0][kf]) < 10:
poofoo[0][kp] = poo[0][kp] #change if the smallest value for the mins is needed and the biggest value for maxs
else:
if kp not in poofoo:
poofoo[0][kp] = poo[0][kp]
if kf not in poofoo:
poofoo[0][kf] = foo[0][kf]