Mercurial > repos > imgteam > 2d_feature_extraction
comparison 2d_feature_extraction.py @ 4:a4bc9dfde846 draft default tip
planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/2d_feature_extraction/ commit 8e99ddb62ceab1da15996906a0813826b62d38fe
| author | imgteam |
|---|---|
| date | Wed, 17 Dec 2025 11:20:49 +0000 |
| parents | f4bcb0207519 |
| children |
comparison
equal
deleted
inserted
replaced
| 3:f4bcb0207519 | 4:a4bc9dfde846 |
|---|---|
| 1 import argparse | 1 import argparse |
| 2 | |
| 3 import giatools.io | |
| 2 import numpy as np | 4 import numpy as np |
| 3 import pandas as pd | 5 import pandas as pd |
| 4 import skimage.io | 6 import skimage.feature |
| 5 import skimage.measure | 7 import skimage.measure |
| 6 import skimage.feature | 8 import skimage.morphology |
| 7 import skimage.segmentation | 9 import skimage.segmentation |
| 8 import skimage.morphology | |
| 9 | 10 |
| 10 #TODO make importable by python script | |
| 11 | 11 |
| 12 parser = argparse.ArgumentParser(description='Extract Features 2D') | 12 if __name__ == '__main__': |
| 13 | 13 |
| 14 #TODO create factory for boilerplate code | 14 parser = argparse.ArgumentParser(description='Extract image features') |
| 15 features = parser.add_argument_group('compute features') | |
| 16 features.add_argument('--all', dest='all_features', action='store_true') | |
| 17 features.add_argument('--label', dest='add_label', action='store_true') | |
| 18 features.add_argument('--patches', dest='add_roi_patches', action='store_true') | |
| 19 features.add_argument('--max_intensity', dest='max_intensity', action='store_true') | |
| 20 features.add_argument('--mean_intensity', dest='mean_intensity', action='store_true') | |
| 21 features.add_argument('--min_intensity', dest='min_intensity', action='store_true') | |
| 22 features.add_argument('--moments_hu', dest='moments_hu', action='store_true') | |
| 23 features.add_argument('--centroid', dest='centroid', action='store_true') | |
| 24 features.add_argument('--bbox', dest='bbox', action='store_true') | |
| 25 features.add_argument('--area', dest='area', action='store_true') | |
| 26 features.add_argument('--filled_area', dest='filled_area', action='store_true') | |
| 27 features.add_argument('--convex_area', dest='convex_area', action='store_true') | |
| 28 features.add_argument('--perimeter', dest='perimeter', action='store_true') | |
| 29 features.add_argument('--extent', dest='extent', action='store_true') | |
| 30 features.add_argument('--eccentricity', dest='eccentricity', action='store_true') | |
| 31 features.add_argument('--equivalent_diameter', dest='equivalent_diameter', action='store_true') | |
| 32 features.add_argument('--euler_number', dest='euler_number', action='store_true') | |
| 33 features.add_argument('--inertia_tensor_eigvals', dest='inertia_tensor_eigvals', action='store_true') | |
| 34 features.add_argument('--major_axis_length', dest='major_axis_length', action='store_true') | |
| 35 features.add_argument('--minor_axis_length', dest='minor_axis_length', action='store_true') | |
| 36 features.add_argument('--orientation', dest='orientation', action='store_true') | |
| 37 features.add_argument('--solidity', dest='solidity', action='store_true') | |
| 38 features.add_argument('--moments', dest='moments', action='store_true') | |
| 39 features.add_argument('--convexity', dest='convexity', action='store_true') | |
| 40 | 15 |
| 41 parser.add_argument('--label_file_binary', dest='label_file_binary', action='store_true') | 16 # TODO create factory for boilerplate code |
| 17 features = parser.add_argument_group('compute features') | |
| 18 features.add_argument('--all', dest='all_features', action='store_true') | |
| 19 features.add_argument('--label', dest='add_label', action='store_true') | |
| 20 features.add_argument('--patches', dest='add_roi_patches', action='store_true') | |
| 21 features.add_argument('--max_intensity', dest='max_intensity', action='store_true') | |
| 22 features.add_argument('--mean_intensity', dest='mean_intensity', action='store_true') | |
| 23 features.add_argument('--min_intensity', dest='min_intensity', action='store_true') | |
| 24 features.add_argument('--moments_hu', dest='moments_hu', action='store_true') | |
| 25 features.add_argument('--centroid', dest='centroid', action='store_true') | |
| 26 features.add_argument('--bbox', dest='bbox', action='store_true') | |
| 27 features.add_argument('--area', dest='area', action='store_true') | |
| 28 features.add_argument('--filled_area', dest='filled_area', action='store_true') | |
| 29 features.add_argument('--convex_area', dest='convex_area', action='store_true') | |
| 30 features.add_argument('--perimeter', dest='perimeter', action='store_true') | |
| 31 features.add_argument('--extent', dest='extent', action='store_true') | |
| 32 features.add_argument('--eccentricity', dest='eccentricity', action='store_true') | |
| 33 features.add_argument('--equivalent_diameter', dest='equivalent_diameter', action='store_true') | |
| 34 features.add_argument('--euler_number', dest='euler_number', action='store_true') | |
| 35 features.add_argument('--inertia_tensor_eigvals', dest='inertia_tensor_eigvals', action='store_true') | |
| 36 features.add_argument('--major_axis_length', dest='major_axis_length', action='store_true') | |
| 37 features.add_argument('--minor_axis_length', dest='minor_axis_length', action='store_true') | |
| 38 features.add_argument('--orientation', dest='orientation', action='store_true') | |
| 39 features.add_argument('--solidity', dest='solidity', action='store_true') | |
| 40 features.add_argument('--moments', dest='moments', action='store_true') | |
| 41 features.add_argument('--convexity', dest='convexity', action='store_true') | |
| 42 | 42 |
| 43 parser.add_argument('--raw', dest='raw_file', type=argparse.FileType('r'), | 43 parser.add_argument('--label_file_binary', dest='label_file_binary', action='store_true') |
| 44 help='Original input file', required=False) | |
| 45 parser.add_argument('label_file', type=argparse.FileType('r'), | |
| 46 help='Label input file') | |
| 47 parser.add_argument('output_file', type=argparse.FileType('w'), | |
| 48 help='Tabular output file') | |
| 49 args = parser.parse_args() | |
| 50 | |
| 51 label_file_binary = args.label_file_binary | |
| 52 label_file = args.label_file.name | |
| 53 out_file = args.output_file.name | |
| 54 add_patch = args.add_roi_patches | |
| 55 | 44 |
| 56 raw_image = None | 45 parser.add_argument('--raw', dest='raw_file', type=argparse.FileType('r'), |
| 57 if args.raw_file is not None: | 46 help='Original input file', required=False) |
| 58 raw_image = skimage.io.imread(args.raw_file.name) | 47 parser.add_argument('label_file', type=argparse.FileType('r'), |
| 48 help='Label input file') | |
| 49 parser.add_argument('output_file', type=argparse.FileType('w'), | |
| 50 help='Tabular output file') | |
| 51 args = parser.parse_args() | |
| 59 | 52 |
| 60 raw_label_image = skimage.io.imread(label_file) | 53 label_file_binary = args.label_file_binary |
| 54 label_file = args.label_file.name | |
| 55 out_file = args.output_file.name | |
| 56 add_patch = args.add_roi_patches | |
| 61 | 57 |
| 62 df = pd.DataFrame() | 58 raw_image = None |
| 63 if label_file_binary: | 59 if args.raw_file is not None: |
| 64 raw_label_image = skimage.measure.label(raw_label_image) | 60 raw_image = giatools.io.imread(args.raw_file.name) |
| 65 regions = skimage.measure.regionprops(raw_label_image, intensity_image=raw_image) | |
| 66 | 61 |
| 67 df['it'] = np.arange(len(regions)) | 62 raw_label_image = giatools.io.imread(label_file) |
| 68 | 63 |
| 69 if add_patch: | 64 df = pd.DataFrame() |
| 70 df['image'] = df['it'].map(lambda ait: regions[ait].image.astype(np.float).tolist()) | 65 if label_file_binary: |
| 71 df['intensity_image'] = df['it'].map(lambda ait: regions[ait].intensity_image.astype(np.float).tolist()) | 66 raw_label_image = skimage.measure.label(raw_label_image) |
| 67 regions = skimage.measure.regionprops(raw_label_image, intensity_image=raw_image) | |
| 72 | 68 |
| 73 #TODO no matrix features, but split in own rows? | 69 df['it'] = np.arange(len(regions)) |
| 74 if args.add_label or args.all_features: | |
| 75 df['label'] = df['it'].map(lambda ait: regions[ait].label) | |
| 76 | 70 |
| 77 if raw_image is not None: | 71 if add_patch: |
| 78 if args.max_intensity or args.all_features: | 72 df['image'] = df['it'].map(lambda ait: regions[ait].image.astype(np.float).tolist()) |
| 79 df['max_intensity'] = df['it'].map(lambda ait: regions[ait].max_intensity) | 73 df['intensity_image'] = df['it'].map(lambda ait: regions[ait].intensity_image.astype(np.float).tolist()) |
| 80 if args.mean_intensity or args.all_features: | |
| 81 df['mean_intensity'] = df['it'].map(lambda ait: regions[ait].mean_intensity) | |
| 82 if args.min_intensity or args.all_features: | |
| 83 df['min_intensity'] = df['it'].map(lambda ait: regions[ait].min_intensity) | |
| 84 if args.moments_hu or args.all_features: | |
| 85 df['moments_hu'] = df['it'].map(lambda ait: regions[ait].moments_hu) | |
| 86 | 74 |
| 87 if args.centroid or args.all_features: | 75 # TODO no matrix features, but split in own rows? |
| 88 df['centroid'] = df['it'].map(lambda ait: regions[ait].centroid) | 76 if args.add_label or args.all_features: |
| 89 if args.bbox or args.all_features: | 77 df['label'] = df['it'].map(lambda ait: regions[ait].label) |
| 90 df['bbox'] = df['it'].map(lambda ait: regions[ait].bbox) | |
| 91 if args.area or args.all_features: | |
| 92 df['area'] = df['it'].map(lambda ait: regions[ait].area) | |
| 93 if args.filled_area or args.all_features: | |
| 94 df['filled_area'] = df['it'].map(lambda ait: regions[ait].filled_area) | |
| 95 if args.convex_area or args.all_features: | |
| 96 df['convex_area'] = df['it'].map(lambda ait: regions[ait].convex_area) | |
| 97 if args.perimeter or args.all_features: | |
| 98 df['perimeter'] = df['it'].map(lambda ait: regions[ait].perimeter) | |
| 99 if args.extent or args.all_features: | |
| 100 df['extent'] = df['it'].map(lambda ait: regions[ait].extent) | |
| 101 if args.eccentricity or args.all_features: | |
| 102 df['eccentricity'] = df['it'].map(lambda ait: regions[ait].eccentricity) | |
| 103 if args.equivalent_diameter or args.all_features: | |
| 104 df['equivalent_diameter'] = df['it'].map(lambda ait: regions[ait].equivalent_diameter) | |
| 105 if args.euler_number or args.all_features: | |
| 106 df['euler_number'] = df['it'].map(lambda ait: regions[ait].euler_number) | |
| 107 if args.inertia_tensor_eigvals or args.all_features: | |
| 108 df['inertia_tensor_eigvals'] = df['it'].map(lambda ait: regions[ait].inertia_tensor_eigvals) | |
| 109 if args.major_axis_length or args.all_features: | |
| 110 df['major_axis_length'] = df['it'].map(lambda ait: regions[ait].major_axis_length) | |
| 111 if args.minor_axis_length or args.all_features: | |
| 112 df['minor_axis_length'] = df['it'].map(lambda ait: regions[ait].minor_axis_length) | |
| 113 if args.orientation or args.all_features: | |
| 114 df['orientation'] = df['it'].map(lambda ait: regions[ait].orientation) | |
| 115 if args.solidity or args.all_features: | |
| 116 df['solidity'] = df['it'].map(lambda ait: regions[ait].solidity) | |
| 117 if args.moments or args.all_features: | |
| 118 df['moments'] = df['it'].map(lambda ait: regions[ait].moments) | |
| 119 if args.convexity or args.all_features: | |
| 120 perimeter = df['it'].map(lambda ait: regions[ait].perimeter) | |
| 121 area = df['it'].map(lambda ait: regions[ait].area) | |
| 122 df['convexity'] = area/(perimeter*perimeter) | |
| 123 | 78 |
| 124 del df['it'] | 79 if raw_image is not None: |
| 125 df.to_csv(out_file, sep='\t', line_terminator='\n', index=False) | 80 if args.max_intensity or args.all_features: |
| 81 df['max_intensity'] = df['it'].map(lambda ait: regions[ait].max_intensity) | |
| 82 if args.mean_intensity or args.all_features: | |
| 83 df['mean_intensity'] = df['it'].map(lambda ait: regions[ait].mean_intensity) | |
| 84 if args.min_intensity or args.all_features: | |
| 85 df['min_intensity'] = df['it'].map(lambda ait: regions[ait].min_intensity) | |
| 86 if args.moments_hu or args.all_features: | |
| 87 df['moments_hu'] = df['it'].map(lambda ait: regions[ait].moments_hu) | |
| 88 | |
| 89 if args.centroid or args.all_features: | |
| 90 df['centroid'] = df['it'].map(lambda ait: regions[ait].centroid) | |
| 91 if args.bbox or args.all_features: | |
| 92 df['bbox'] = df['it'].map(lambda ait: regions[ait].bbox) | |
| 93 if args.area or args.all_features: | |
| 94 df['area'] = df['it'].map(lambda ait: regions[ait].area) | |
| 95 if args.filled_area or args.all_features: | |
| 96 df['filled_area'] = df['it'].map(lambda ait: regions[ait].filled_area) | |
| 97 if args.convex_area or args.all_features: | |
| 98 df['convex_area'] = df['it'].map(lambda ait: regions[ait].convex_area) | |
| 99 if args.perimeter or args.all_features: | |
| 100 df['perimeter'] = df['it'].map(lambda ait: regions[ait].perimeter) | |
| 101 if args.extent or args.all_features: | |
| 102 df['extent'] = df['it'].map(lambda ait: regions[ait].extent) | |
| 103 if args.eccentricity or args.all_features: | |
| 104 df['eccentricity'] = df['it'].map(lambda ait: regions[ait].eccentricity) | |
| 105 if args.equivalent_diameter or args.all_features: | |
| 106 df['equivalent_diameter'] = df['it'].map(lambda ait: regions[ait].equivalent_diameter) | |
| 107 if args.euler_number or args.all_features: | |
| 108 df['euler_number'] = df['it'].map(lambda ait: regions[ait].euler_number) | |
| 109 if args.inertia_tensor_eigvals or args.all_features: | |
| 110 df['inertia_tensor_eigvals'] = df['it'].map(lambda ait: regions[ait].inertia_tensor_eigvals) | |
| 111 if args.major_axis_length or args.all_features: | |
| 112 df['major_axis_length'] = df['it'].map(lambda ait: regions[ait].major_axis_length) | |
| 113 if args.minor_axis_length or args.all_features: | |
| 114 df['minor_axis_length'] = df['it'].map(lambda ait: regions[ait].minor_axis_length) | |
| 115 if args.orientation or args.all_features: | |
| 116 df['orientation'] = df['it'].map(lambda ait: regions[ait].orientation) | |
| 117 if args.solidity or args.all_features: | |
| 118 df['solidity'] = df['it'].map(lambda ait: regions[ait].solidity) | |
| 119 if args.moments or args.all_features: | |
| 120 df['moments'] = df['it'].map(lambda ait: regions[ait].moments) | |
| 121 if args.convexity or args.all_features: | |
| 122 perimeter = df['it'].map(lambda ait: regions[ait].perimeter) | |
| 123 area = df['it'].map(lambda ait: regions[ait].area) | |
| 124 df['convexity'] = area / (perimeter * perimeter) | |
| 125 | |
| 126 del df['it'] | |
| 127 df.to_csv(out_file, sep='\t', lineterminator='\n', index=False) |
