| import torch |
|
|
| def detect_tables(model, pixel_values): |
| with torch.no_grad(): |
| outputs = model(pixel_values) |
| return outputs |
|
|
| def detect_cells(model, pixel_values): |
| with torch.no_grad(): |
| outputs = model(pixel_values) |
| return outputs |
|
|
| def outputs_to_objects(outputs, img_size, id2label): |
| def box_cxcywh_to_xyxy(x): |
| x_c, y_c, w, h = x.unbind(-1) |
| b = [(x_c - 0.5 * w), (y_c - 0.5 * h), (x_c + 0.5 * w), (y_c + 0.5 * h)] |
| return torch.stack(b, dim=1) |
|
|
| def rescale_bboxes(out_bbox, size): |
| img_w, img_h = size |
| b = box_cxcywh_to_xyxy(out_bbox) |
| b = b * torch.tensor([img_w, img_h, img_w, img_h], dtype=torch.float32) |
| return b |
|
|
| |
| if len(id2label) not in id2label: |
| id2label[len(id2label)] = "no object" |
|
|
| m = outputs.logits.softmax(-1).max(-1) |
| pred_labels = list(m.indices.detach().cpu().numpy())[0] |
| pred_scores = list(m.values.detach().cpu().numpy())[0] |
| pred_bboxes = outputs['pred_boxes'].detach().cpu()[0] |
| pred_bboxes = [elem.tolist() for elem in rescale_bboxes(pred_bboxes, img_size)] |
|
|
| print(f"Predicted labels: {pred_labels}") |
| print(f"id2label: {id2label}") |
|
|
| objects = [] |
| for label, score, bbox in zip(pred_labels, pred_scores, pred_bboxes): |
| try: |
| class_label = id2label[int(label)] |
| except KeyError: |
| print(f"Label {label} not found in id2label. Skipping.") |
| continue |
| if not class_label == 'no object': |
| objects.append({'label': class_label, 'score': float(score), |
| 'bbox': [float(elem) for elem in bbox]}) |
|
|
| return objects |
|
|
| def objects_to_crops(img, tokens, objects, class_thresholds, padding=10): |
| table_crops = [] |
| for obj in objects: |
| if obj['score'] < class_thresholds[obj['label']]: |
| continue |
|
|
| cropped_table = {} |
| bbox = obj['bbox'] |
| bbox = [bbox[0] - padding, bbox[1] - padding, bbox[2] + padding, bbox[3] + padding] |
| cropped_img = img.crop(bbox) |
|
|
| table_tokens = [token for token in tokens if iob(token['bbox'], bbox) >= 0.5] |
| for token in table_tokens: |
| token['bbox'] = [token['bbox'][0] - bbox[0], token['bbox'][1] - bbox[1], token['bbox'][2] - bbox[0], token['bbox'][3] - bbox[1]] |
|
|
| if obj['label'] == 'table rotated': |
| cropped_img = cropped_img.rotate(270, expand=True) |
| for token in table_tokens: |
| bbox = token['bbox'] |
| bbox = [cropped_img.size[0] - bbox[3] - 1, bbox[0], cropped_img.size[0] - bbox[1] - 1, bbox[2]] |
| token['bbox'] = bbox |
|
|
| cropped_table['image'] = cropped_img |
| cropped_table['tokens'] = table_tokens |
| table_crops.append(cropped_table) |
|
|
| return table_crops |
|
|
| def get_cell_coordinates_by_row(table_data): |
| rows = [entry for entry in table_data if entry['label'] == 'table row'] |
| columns = [entry for entry in table_data if entry['label'] == 'table column'] |
| rows.sort(key=lambda x: x['bbox'][1]) |
| columns.sort(key=lambda x: x['bbox'][0]) |
|
|
| def find_cell_coordinates(row, column): |
| cell_bbox = [column['bbox'][0], row['bbox'][1], column['bbox'][2], row['bbox'][3]] |
| return cell_bbox |
|
|
| cell_coordinates = [] |
| for row in rows: |
| row_cells = [] |
| for column in columns: |
| cell_bbox = find_cell_coordinates(row, column) |
| row_cells.append({'column': column['bbox'], 'cell': cell_bbox}) |
| row_cells.sort(key=lambda x: x['column'][0]) |
| cell_coordinates.append({'row': row['bbox'], 'cells': row_cells, 'cell_count': len(row_cells)}) |
| cell_coordinates.sort(key=lambda x: x['row'][1]) |
| return cell_coordinates |
|
|