-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCrop_image_main.py
executable file
·145 lines (112 loc) · 4.75 KB
/
Crop_image_main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 12 13:00:22 2022
@author: thibault
Contain functions to get the bounding box (bbox) from the metadata file
and crop the fish out of the image from the bbox
everything is wrap into a main function executable via
Crop_image_main.py image metadatafile output_crop
"""
import sys
import json
import numpy as np
import argparse
from PIL import Image, ImageFile
import matplotlib.pyplot as plt
# Some of the image are truncated and trigger an error the follow line solve the problem
ImageFile.LOAD_TRUNCATED_IMAGES = True
def get_bbox(metadata_file):
'''
From metadata.json (drexel_metadata_reformatter.py) extract the fish bounding box.
Version extracting from the reformat see (/~https://github.com/hdr-bgnn/drexel_metadata_formatter)
Parameters
----------
metadata_file : string
location/name of the json file containing the metadata to be extracted.
Returns
-------
bbox : list
list containing the bbox around the fish [left, top, right, bottom].
'''
f = open(metadata_file)
data = json.load(f)
bbox = []
if 'fish' in data:
if data['fish']['fish_num']>0:
bbox = data['fish']['bbox']
return bbox
def Crop(image, bbox, increase=0.05):
'''
Crop the image using the bounding box, expected format [left,top,right,bottom] and adding
an increase in size vertically and horizontally.
The function will cut off the crop at the boundary of the image if it would otherwise exceed the
image boundary
Parameters
----------
image : PIL image format
DESCRIPTION. image imported using PIL.Image.open(image_file)
bbox : list
DESCRIPTION. list with bbox coordinate format [left,top,right,bottom]
increase : float, optional
DESCRIPTION. Fractional increase of the bounding box around the fish in each dimension. The default is 0.05 (5%).
Returns
-------
im1 : image PIL format
DESCRIPTION. Cropped image
'''
# 5% increase by default of the bbox, metadata bbox is very tight sometime too tight
# increase factor in each direction (width height)
factor = increase/2
left,top,right,bottom = bbox
#h_increase = int(abs((right-left)*factor))
#v_increase = int(abs((bottom-top)*factor))
h_increase = (right-left)*factor
v_increase = (bottom-top)*factor
new_bbox = (left-h_increase, top-v_increase, right+h_increase, bottom+v_increase)
# cutoff the cropping to the original image boundary
image_limit = (0,0)+image.size
new_bbox_cutoff_1 = map(np.maximum, new_bbox[0:2], (0,0))
new_bbox_cutoff_2 = map(np.minimum, new_bbox[2:4], image.size)
new_bbox = tuple(new_bbox_cutoff_1) + tuple(new_bbox_cutoff_2)
im1 = image.crop(new_bbox) # bbox (left,top,right,bottom)
return im1
def main(image_file, metadata_file, output_file, increase=0.05):
'''
Extract the fish bbox from the metadatafile.json and crop the fish and save the result in outputfile
Parameters
----------
image_file : string
DESCRIPTION. filename location of the image .jpg
metadata_file : string
DESCRIPTION. filename location of the metadata file .json
output_file : string
DESCRIPTION. filename location where to save the cropped image
increase : float, optional
DESCRIPTION. Fractional increase of the size of the box around the fish in each dimension. The default is 0.05 (5%).
Returns
-------
None.
'''
im = Image.open(image_file)
bbox = get_bbox(metadata_file)
if bbox:
# use the crop function
im1 = Crop(im, bbox, increase=increase)
else:
# if no bounding box detected
print ("no bounding box available for {}, will return empty cropped image".format(image_file))
im1 = Image.fromarray(np.zeros(im.size))
im1.save(output_file)
def argument_parser():
parser = argparse.ArgumentParser(description='Crop the fish image using bounding bbox from a metadata.json.')
parser.add_argument('input_image', help='Path of input original fish image. Format JPG image file.')
parser.add_argument('input_metadata', help='Path of input drexel_metadata_reformatted. Format JSON metadata file.')
parser.add_argument('output', help='Path of output cropped fish image. Format JPG image file.')
parser.add_argument('--increase', type=float, default=0.05,
help='size increase apply to the bounding box for cropping (in width and height).Default 0.05. Format float.')
return parser
if __name__ == '__main__':
parser = argument_parser()
args = parser.parse_args()
main(args.input_image, args.input_metadata, args.output, increase=args.increase)