Skip to content

Commit bd6e71e

Browse files
committed
v0.6.1 merge conflict fixes
2 parents 07020ea + a9fb9f6 commit bd6e71e

10 files changed

+188
-31
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ model.run_training(loader)
156156
[ghai_broccoli_detection](https://github.com/Project-AgML/AgML/blob/main/docs/datasets/ghai_broccoli_detection.md) | Object Detection | 500 |
157157
[bean_synthetic_earlygrowth_aerial](https://github.com/Project-AgML/AgML/blob/main/docs/datasets/bean_synthetic_earlygrowth_aerial.md) | Semantic Segmentation | 2500 |
158158
[ghai_strawberry_fruit_detection](https://github.com/Project-AgML/AgML/blob/main/docs/datasets/ghai_strawberry_fruit_detection.md) | Object Detection | 500 |
159+
[vegann_multicrop_presence_segmentation](https://github.com/Project-AgML/AgML/blob/main/docs/datasets/vegann_multicrop_presence_segmentation.md) | Semantic Segmentation | 3775 |
159160

160161
## Usage Information
161162

@@ -186,4 +187,4 @@ a bug or feature that you would like to see implemented, please don't hesitate t
186187
See the [contributing guidelines](/CONTRIBUTING.md) for more information.
187188

188189
## Funding
189-
This project is partly funded by the [National AI Institute for Food Systems (AIFS)](https://aifs.ucdavis.ed
190+
This project is partly funded by the [National AI Institute for Food Systems (AIFS)](https://aifs.ucdavis.edu).

agml/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
__version__ = '0.6.0'
15+
__version__ = '0.6.1'
1616
__all__ = ['data', 'synthetic', 'backend', 'viz', 'io']
1717

1818

agml/_assets/public_datasources.json

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -254,31 +254,30 @@
254254
"annotation_format": "directory_names",
255255
"n_images": "17509",
256256
"docs_url": "https://github.com/AlexOlsen/DeepWeeds",
257+
"classes": {
258+
"0": "Chinee Apple",
259+
"1": "Lantana",
260+
"2": "Parkinsonia",
261+
"3": "Parthenium",
262+
"4": "Prickly Acacia",
263+
"5": "Rubber Vine",
264+
"6": "Siam Weed",
265+
"7": "Snake Weed",
266+
"8": "Negative"
267+
},
268+
"external_image_sources": [],
257269
"stats": {
258270
"mean": [
259-
0.3785816431045532,
260-
0.38957422971725464,
261-
0.3797682821750641
271+
0.3785804808139801,
272+
0.3895738422870636,
273+
0.37976858019828796
262274
],
263275
"std": [
264-
0.22421954572200775,
265-
0.22450360655784607,
266-
0.22274591028690338
276+
0.22421938180923462,
277+
0.2245042622089386,
278+
0.22274629771709442
267279
]
268-
},
269-
"classes": {
270-
"0": "no_weeds",
271-
"1": "chinee_apple",
272-
"2": "lantana",
273-
"3": "parkinsonia",
274-
"4": "parthenium",
275-
"5": "prickly_acacia",
276-
"6": "rubber_vine",
277-
"7": "siam_weed",
278-
"8": "snake_weed",
279-
"9": "negative"
280-
},
281-
"external_image_sources": []
280+
}
282281
},
283282
"fruit_detection_worldwide": {
284283
"ml_task": "object_detection",
@@ -1270,5 +1269,35 @@
12701269
0.18042609095573425
12711270
]
12721271
}
1272+
},
1273+
"vegann_multicrop_presence_segmentation": {
1274+
"classes": {
1275+
"1": "plant"
1276+
},
1277+
"ml_task": "semantic_segmentation",
1278+
"ag_task": "vegetation_segmentation",
1279+
"location": {
1280+
"continent": "worldwide",
1281+
"country": "worldwide"
1282+
},
1283+
"sensor_modality": "rgb",
1284+
"real_synthetic": "real",
1285+
"platform": "aerial",
1286+
"input_data_format": "png",
1287+
"annotation_format": "image",
1288+
"n_images": "3775",
1289+
"docs_url": "https://zenodo.org/records/7636408",
1290+
"stats": {
1291+
"mean": [
1292+
16.39170265197754,
1293+
18.68538475036621,
1294+
14.235136985778809
1295+
],
1296+
"std": [
1297+
4.590310573577881,
1298+
5.818269729614258,
1299+
4.1895012855529785
1300+
]
1301+
}
12731302
}
12741303
}

agml/_assets/shape_info.pickle

208 Bytes
Binary file not shown.

agml/_assets/source_citations.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,5 +142,9 @@
142142
"ghai_strawberry_fruit_detection": {
143143
"license": "CC BY-SA 4.0",
144144
"citation": ""
145+
},
146+
"vegann_multicrop_presence_segmentation": {
147+
"license": "CC BY-SA 4.0",
148+
"citation": " @article{Madec_Irfan_Velumani_Baret_David_Daubige_Samatan_Serouart_Smith_James_et al._2023, title={VegAnn, Vegetation Annotation of multi-crop RGB images acquired under diverse conditions for segmentation}, volume={10}, ISSN={2052-4463}, url={https://www.nature.com/articles/s41597-023-02098-y}, DOI={10.1038/s41597-023-02098-y}, abstractNote={Abstract\n \n Applying deep learning to images of cropping systems provides new knowledge and insights in research and commercial applications. Semantic segmentation or pixel-wise classification, of RGB images acquired at the ground level, into vegetation and background is a critical step in the estimation of several canopy traits. Current state of the art methodologies based on convolutional neural networks (CNNs) are trained on datasets acquired under controlled or indoor environments. These models are unable to generalize to real-world images and hence need to be fine-tuned using new labelled datasets. This motivated the creation of the VegAnn -\n Veg\n etation\n Ann\n otation - dataset, a collection of 3775 multi-crop RGB images acquired for different phenological stages using different systems and platforms in diverse illumination conditions. We anticipate that VegAnn will help improving segmentation algorithm performances, facilitate benchmarking and promote large-scale crop vegetation segmentation research.}, number={1}, journal={Scientific Data}, author={Madec, Simon and Irfan, Kamran and Velumani, Kaaviya and Baret, Frederic and David, Etienne and Daubige, Gaetan and Samatan, Lucas Bernigaud and Serouart, Mario and Smith, Daniel and James, Chrisbin and Camacho, Fernando and Guo, Wei and De Solan, Benoit and Chapman, Scott C. and Weiss, Marie}, year={2023}, month=may, pages={302}, language={en} }\n"
145149
}
146150
}

agml/_internal/preprocess.py

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ def rangeland_weeds_australia(self, dataset_name):
112112
os.makedirs(os.path.join(
113113
processed_dir, unique_label.title()), exist_ok = True)
114114
for file in tqdm(images, desc = "Moving Images", file = sys.stdout):
115-
save_dir = df.loc[df['Filename'] == file]['Species'].values[0].title()
115+
save_dir = df.loc[df['Filename'] == os.path.basename(file)]['Species'].values[0].title()
116116
shutil.copyfile(
117117
os.path.join(dataset_dir, 'images', file),
118-
os.path.join(processed_dir, save_dir, file)
118+
os.path.join(processed_dir, save_dir, os.path.basename(file))
119119
)
120120

121121
def fruit_detection_worldwide(self, dataset_name):
@@ -1029,6 +1029,62 @@ def ghai_strawberry_fruit_detection(self, dataset_name):
10291029
shutil.move(os.path.join(original_dir, 'coco.json'),
10301030
os.path.join(processed_dir, 'annotations.json'))
10311031

1032+
def vegann_multicrop_presence_segmentation(self, dataset_name):
1033+
# Create processed directories
1034+
original_dir = os.path.join(self.data_original_dir, dataset_name)
1035+
processed_dir = os.path.join(self.data_processed_dir, dataset_name)
1036+
processed_image_dir = os.path.join(processed_dir, 'images')
1037+
os.makedirs(processed_image_dir, exist_ok = True)
1038+
processed_annotation_dir = os.path.join(processed_dir, 'annotations')
1039+
os.makedirs(processed_annotation_dir, exist_ok = True)
1040+
1041+
# Move images
1042+
for image in tqdm(glob.glob(os.path.join(original_dir, 'images', '*.png'))):
1043+
shutil.copyfile(image, os.path.join(processed_image_dir, os.path.basename(image)))
1044+
1045+
# Read annotations
1046+
for annotation_file in tqdm(glob.glob(os.path.join(original_dir, 'annotations', '*.png'))):
1047+
annotation = cv2.imread(annotation_file, cv2.IMREAD_UNCHANGED)
1048+
annotation = np.where(annotation == 255, 1, 0)
1049+
cv2.imwrite(os.path.join(processed_annotation_dir,
1050+
os.path.basename(annotation_file)), annotation)
1051+
1052+
# Read the CSV file containing the splits
1053+
split_csv = pd.read_csv(os.path.join(original_dir, 'VegAnn_dataset.csv'), sep=';')
1054+
1055+
# Get the `Name` and `TVT-split{n}` columns for each n, and save the splits to a folder
1056+
splits_folder = os.path.join(processed_dir, '.splits')
1057+
os.makedirs(splits_folder, exist_ok = True)
1058+
column_pairs = [['Name', f'TVT-split{i}'] for i in range(1, 5 + 1)]
1059+
1060+
splits = {}
1061+
for column_pair in column_pairs:
1062+
columns = split_csv[column_pair]
1063+
train_images = columns[columns[column_pair[1]] == 'Training']['Name']
1064+
test_images = columns[columns[column_pair[1]] == 'Test']['Name']
1065+
splits[column_pair[1]] = {
1066+
'train': {os.path.join('images', i): os.path.join('annotations', i) for i in train_images},
1067+
'val': {},
1068+
'test': {os.path.join('images', i): os.path.join('annotations', i) for i in test_images}
1069+
}
1070+
1071+
# Save each split to a JSON file
1072+
for split_name, split in splits.items():
1073+
with open(os.path.join(splits_folder, f'{split_name}.json'), 'w') as f:
1074+
json.dump(split, f)
1075+
1076+
1077+
1078+
1079+
1080+
1081+
1082+
1083+
1084+
1085+
1086+
1087+
10321088

10331089
if __name__ == '__main__':
10341090
# Initialize program arguments.
@@ -1045,7 +1101,7 @@ def ghai_strawberry_fruit_detection(self, dataset_name):
10451101
print("Processing dataset")
10461102
p.preprocess(args.dataset)
10471103
print("Converting dataset")
1048-
os.chdir(f'{args.data_dir}/processed')
1049-
os.system(f'zip -r {args.dataset}.zip {args.dataset} -x ".*" -x "__MACOSX"')
1104+
# os.chdir(f'{args.data_dir}/processed')
1105+
# os.system(f'zip -r {args.dataset}.zip {args.dataset} -x ".*" -x "__MACOSX"')
10501106

10511107

agml/data/loader.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,10 +1234,27 @@ def save_split(self, name, overwrite = False):
12341234
raise NotImplementedError("Cannot save a split of data when no "
12351235
"split has been generated.")
12361236

1237-
# Get each of the individual splits.
1238-
splits = {'train': self._train_content,
1239-
'val': self._val_content,
1240-
'test': self._test_content}
1237+
# Get each of the individual splits, and for semantic segmentation/image
1238+
# classification, remove the full paths and only save the path relative
1239+
# to the dataset root (so only the file and its directory are saved).
1240+
splits = {}
1241+
if self._info.tasks.ml == 'image_classification':
1242+
for split in ['train', 'val', 'test']:
1243+
contents = getattr(self, f'_{split}_content')
1244+
if contents is not None:
1245+
contents = {
1246+
os.path.relpath(c, self.dataset_root): v for c, v in contents.items()
1247+
}
1248+
splits[split] = contents
1249+
elif self._info.tasks.ml == 'semantic_segmentation':
1250+
for split in ['train', 'val', 'test']:
1251+
contents = getattr(self, f'_{split}_content')
1252+
if contents is not None:
1253+
contents = {
1254+
os.path.relpath(c, self.dataset_root):
1255+
os.path.relpath(v, self.dataset_root) for c, v in contents.items()
1256+
}
1257+
splits[split] = contents
12411258

12421259
# Save the split to the internal location.
12431260
split_dir = os.path.join(SUPER_BASE_DIR, 'splits', self.name)
@@ -1258,6 +1275,10 @@ def load_split(self, name, **kwargs):
12581275
use the traditional split accessors (`train_data`, `val_data`, and
12591276
`test_data`) to access the loaded data.
12601277
1278+
You can also load a pre-defined split for the dataset by using its name
1279+
(any potential such splits can be found in the dataset info, and are
1280+
derived from the original dataset).
1281+
12611282
Parameters
12621283
----------
12631284
name: str
@@ -1271,14 +1292,33 @@ def load_split(self, name, **kwargs):
12711292
# Ensure that the split exists.
12721293
split_dir = os.path.join(SUPER_BASE_DIR, 'splits', self.name)
12731294
if not os.path.exists(os.path.join(split_dir, f'{name}.json')):
1274-
raise FileNotFoundError(f"Could not find a split with the name {name}.")
1295+
split_dir = os.path.join(self.dataset_root, '.splits')
1296+
if not os.path.exists(os.path.join(split_dir, f'{name}.json')):
1297+
raise FileNotFoundError(f"Could not find a split with the name {name}.")
12751298

12761299
# Load the split from the internal location.
12771300
with open(os.path.join(split_dir, f'{name}.json'), 'r') as f:
12781301
splits = json.load(f)
12791302

12801303
# Set the split contents.
12811304
for split, content in splits.items():
1305+
# If the data is for image classification or semantic segmentation,
1306+
# then we need to re-construct the full paths to the images.
1307+
if len(content) > 0:
1308+
first_item = list(content.items())[0]
1309+
if not os.path.isabs(first_item[0]): # backwards compatibility
1310+
if self._info.tasks.ml == 'image_classification':
1311+
content = {
1312+
os.path.join(self.dataset_root, c): v for c, v in content.items()
1313+
}
1314+
elif self._info.tasks.ml == 'semantic_segmentation':
1315+
content = {
1316+
os.path.join(self.dataset_root, c): os.path.join(self.dataset_root, v)
1317+
for c, v in content.items()
1318+
}
1319+
else:
1320+
content = None
1321+
12821322
setattr(self, f'_{split}_content', content)
12831323

12841324
def batch(self, batch_size = None):

agml/viz/labels.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ def show_images_and_labels(images,
116116
plt.setp(ax.spines.values(), visible = False)
117117
ax.set_xlabel(label)
118118

119+
# decrease the label size (if it's too big)
120+
ax.xaxis.label.set_size(8)
121+
119122
# Display and return the image.
123+
fig.tight_layout()
120124
image = convert_figure_to_image()
121125
if not kwargs.get('no_show', False):
122126
_ = display_image(image)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
# `vegann_multicrop_presence_segmentation`
3+
4+
## Dataset Metadata
5+
6+
| Metadata | Value |
7+
| --- | --- |
8+
| **Classes** | plant |
9+
| **Machine Learning Task** | semantic_segmentation |
10+
| **Agricultural Task** | vegetation_segmentation |
11+
| **Location** | Worldwide |
12+
| **Sensor Modality** | RGB |
13+
| **Real or Synthetic** | real |
14+
| **Platform** | aerial |
15+
| **Input Data Format** | PNG |
16+
| **Annotation Format** | image |
17+
| **Number of Images** | 3775 |
18+
| **Documentation** | https://zenodo.org/records/7636408 |
19+
20+
21+
## Examples
22+
23+
![Example Images for vegann_multicrop_presence_segmentation](https://github.com/Project-AgML/AgML/blob/main/docs/sample_images/vegann_multicrop_presence_segmentation_examples.png)
Loading

0 commit comments

Comments
 (0)