Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New input format #5

Merged
merged 28 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7ade139
update Crop_image_main
Oct 17, 2022
c79e164
add test file for new version
Oct 17, 2022
ca53124
updated version of Crop_main.py
thibaulttabarin Oct 18, 2022
9029647
Update Deploy_Crop_Image.yml
thibaulttabarin Oct 19, 2022
31dc86e
in Crop_main.py documentation and command line option
thibaulttabarin Nov 7, 2022
b0b54a1
include boundary truncature issue #4
thibaulttabarin Nov 8, 2022
238c9ba
add examples
thibaulttabarin Nov 8, 2022
3599c9f
Update README.md
thibaulttabarin Nov 9, 2022
619b98a
Update Deploy_Crop_Image.yml
thibaulttabarin Nov 9, 2022
e52c367
Update Deploy_Crop_Image.yml
thibaulttabarin Nov 9, 2022
87b0229
Update README.md
thibaulttabarin Nov 10, 2022
a528c6d
Update README.md
thibaulttabarin Nov 10, 2022
44a2a8d
Update Crop_image_main.py
thibaulttabarin Nov 10, 2022
b53cbd2
Update README.md
thibaulttabarin Nov 10, 2022
860c350
Remove int(abs()) to avoid confusion
thibaulttabarin Nov 11, 2022
ae3c32f
Merge branch 'new-input-format' of github.com:hdr-bgnn/Crop_image int…
thibaulttabarin Nov 11, 2022
701c977
Update README.md
thibaulttabarin Nov 11, 2022
dda82d8
Update README.md
thibaulttabarin Nov 14, 2022
66d125a
Update README.md
thibaulttabarin Nov 14, 2022
a71729f
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
d17c1d7
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
7498ffb
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
1107845
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
49f1815
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
af2e23b
Update Crop_image_main.py
thibaulttabarin Nov 14, 2022
72489b8
Update README.md
thibaulttabarin Nov 14, 2022
9331e54
Update README.md
thibaulttabarin Nov 14, 2022
adc7e38
Update README.md
thibaulttabarin Nov 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 105 additions & 19 deletions Crop_image_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,118 @@
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
python crop_main.py <image> <metadatafile> <output_crop>
Crop_image_main.py image metadatafile output_crop
"""

import os
import sys
import json
import numpy as np
import argparse
from PIL import Image, ImageFile
import pandas as pd
from pathlib import Path
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)
first_value = list(data.values())[0]
bbox = []

if first_value['has_fish']==True:

bbox = first_value['fish'][0]['bbox']
else: 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:
# 5% increase by default of the bbox, metadata bbox is very tight sometime too tight
# increase factor in each direction
factor = increase/2
left,top,right,bottom = bbox
h_increase = int(abs((right-left)*factor))
v_increase = int(abs((bottom-top)*factor))
new_bbox = (left-h_increase, top-v_increase, right+h_increase, bottom+v_increase)
im1 = im.crop(new_bbox) # bbox (left,top,right,bottom)
# use the crop function
im1 = Crop(im, bbox, increase=increase)

else:
# if no bounding box detected
Expand All @@ -54,6 +127,19 @@ def main(image_file, metadata_file, output_file, increase=0.05):

im1.save(output_file)

if __name__ == '__main__':
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


main(sys.argv[1],sys.argv[2],sys.argv[3])
if __name__ == '__main__':

parser = argument_parser()
args = parser.parse_args()
main(args.input_image, args.input_metadata, args.output, increase=args.increase)

29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
# Crop_image
Small repository to store the "copping"step of the BGNN Fish project.
Small repository to store the "cropping"step of the BGNN Fish project.

This repo is linked to main BGNN Fish project rpo [BGNN_Snakemake](https://github.com/hdr-bgnn/BGNN_Snakemake) that encompasses a complete analysis workflow. It contained the code for the "Cropping" part [see here](https://github.com/hdr-bgnn/BGNN_Snakemake/blob/main/Picture_for_Documentation/Workflow_stage_1.png). It is easier to understand the purpose this code and its application if you are familar with BGNN_Snakemake repo.

## 1 - Short description

+ We use raw fish image [available at Tulane](http://www.tubri.org/HDR/INHS/) and Metadata json file generated by [Drexel_metadata generator] (https://github.com/hdr-bgnn/drexel_metadata) to crop the fish out of a more complexe image.
+ The metadata json file contained the bounding box of the fish which use to crop the fish [here is an exmaple](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742_cropped.jpg). We increase the size of the bounding box around the fish by 10% increase in case the bounding box (from the metadata) would truncate the edge of the fish. The Cropped image will be used later by a segmentation algorithm such as [trait_segmenation](https://github.com/hdr-bgnn/BGNN-trait-segmentation)
+ We use raw fish image [available at Tulane](http://www.tubri.org/HDR/INHS/) and Metadata json file generated by [Drexel_metadata](https://github.com/hdr-bgnn/drexel_metadata) and reformatted by [Drexel_metadata_formatter](https://github.com/hdr-bgnn/drexel_metadata_formatter) to crop the fish out of a more complexe image.

**input**
![original fish image](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742.jpg)
![original fish image](Test_data/INHS_FISH_000742.jpg)

**Cropped output**
![Cropped fish image](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742_cropped.jpg)
![Cropped fish image](Test_data/INHS_FISH_000742_cropped.jpg)

## 2 - Usage

Input :
+ fish image .jpg [see INHS_FISH_000742.jpg](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742.jpg)
+ Metadata.json [see INHS_FISH_000742.json](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742.json)
Input example :
+ fish image .jpg [see INHS_FISH_000742.jpg](Test_data/INHS_FISH_000742.jpg)
+ Metadata.json [see INHS_FISH_000742.json](Test_data/INHS_FISH_000742.json)

Ouput :
+ Cropped image .jpg [see INHS_FISH_000742_cropped.jpg](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/INHS_FISH_000742_cropped.jpg)
+ Cropped image .jpg [see INHS_FISH_000742_cropped.jpg]Test_data/INHS_FISH_000742_cropped.jpg)

Usage in python
you need the environment define by crop_env.yml. I suggest to use anaconda or miniconda as environment manager

```
python Crop_image_main.py INHS_FISH_000742.jpg INHS_FISH_000742.json INHS_FISH_000742_cropped.jpg
Crop_image_main.py [-h] [--increase] input_image imput_metadata output
```

Example using the Test_data with 10% increase in size

```
Crop_image_main.py INHS_FISH_000742.jpg INHS_FISH_000742.json INHS_FISH_000742_cropped.jpg --increase 0.10
```

The `--increase` parameter defines the fractional increase of the bounding box from the original metadata size in each direction (10% in this example). The default value in 0.05.

## 3 - Container and test

The container can be download here:
Expand All @@ -50,7 +57,7 @@ The usage can be display like this:
singularity run crop_image_0.0.2.sif
```

To execute the code on the [test data](https://github.com/hdr-bgnn/Crop_image/blob/main/Test_data/), run the following
To execute the code on the test images [test data](Test_data/), run the following

```
singularity exec crop_image_0.0.2.sif Crop_image_main.py Test_data/INHS_FISH_000742.jpg Test_data/INHS_FISH_000742.json Test_data/INHS_FISH_000742_cropped_test.jpg
Expand Down
Loading