laudari commited on
Commit
b601afa
·
verified ·
1 Parent(s): 5468c68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -78
app.py CHANGED
@@ -422,7 +422,8 @@ class PolygonAugmentation:
422
  if aug_type == "rotate":
423
  # For rotation, use the parameter as degrees and make it more visible
424
  rotation_angle = aug_param if abs(aug_param) >= 5 else (15 if aug_param >= 0 else -15)
425
- aug_transform = A.Rotate(limit=abs(rotation_angle), p=1.0, border_mode=cv2.BORDER_CONSTANT, value=0)
 
426
  logger.info(f"Applying rotation: {rotation_angle} degrees")
427
  elif aug_type == "horizontal_flip":
428
  aug_transform = A.HorizontalFlip(p=1.0 if aug_param == 1 else 0.0)
@@ -746,94 +747,124 @@ class PolygonAugmentation:
746
  def create_download_package(self):
747
  """Create a zip file with all augmented images and proper LabelMe JSON files"""
748
  if not self.augmented_results:
 
749
  return None
750
 
 
751
  zip_buffer = io.BytesIO()
752
 
753
- with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
754
- # Add all augmented images and their corresponding LabelMe JSON files
755
- for idx, result in enumerate(self.augmented_results):
756
- # Save augmented image
757
- img_buffer = io.BytesIO()
758
-
759
- # Convert PIL image back to OpenCV format for saving
760
- img_cv = np.array(result['image'])
761
- img_bgr = cv2.cvtColor(img_cv, cv2.COLOR_RGB2BGR)
762
-
763
- # Encode image as PNG
764
- success, encoded_img = cv2.imencode('.png', img_bgr)
765
- if success:
766
- zip_file.writestr(result['metadata']['filename'], encoded_img.tobytes())
767
- else:
768
- # Fallback to PIL saving
769
- result['image'].save(img_buffer, format='PNG')
770
- zip_file.writestr(result['metadata']['filename'], img_buffer.getvalue())
771
-
772
- # Save corresponding LabelMe JSON file
773
- json_filename = result['metadata']['filename'].replace('.png', '.json')
774
-
775
- # Create a clean LabelMe JSON without internal metadata
776
- clean_json_data = {
777
- "version": result['json_data'].get("version", "5.0.1"),
778
- "flags": result['json_data'].get("flags", {}),
779
- "shapes": result['json_data']['shapes'],
780
- "imagePath": result['metadata']['filename'],
781
- "imageData": None,
782
- "imageHeight": result['json_data']['imageHeight'],
783
- "imageWidth": result['json_data']['imageWidth']
784
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
785
 
786
- json_str = json.dumps(clean_json_data, indent=2, ensure_ascii=False)
787
- zip_file.writestr(json_filename, json_str)
788
-
789
- # Add comprehensive summary metadata
790
- summary = {
791
- 'package_info': {
792
- 'total_augmentations': len(self.augmented_results),
793
- 'generation_timestamp': datetime.now().isoformat(),
794
- 'generator': 'PolygonAugmentation v1.0',
795
- 'format': 'LabelMe JSON + PNG images'
796
- },
797
- 'augmentation_summary': [
798
- {
799
- 'filename': result['metadata']['filename'],
800
- 'json_file': result['metadata']['filename'].replace('.png', '.json'),
801
- 'augmentation_type': result['metadata']['augmentation_type'],
802
- 'parameter_value': result['metadata']['parameter_value'],
803
- 'polygon_count': len(result['json_data']['shapes']),
804
- 'image_size': f"{result['json_data']['imageWidth']}x{result['json_data']['imageHeight']}",
805
- 'timestamp': result['metadata']['timestamp'],
806
- 'labels': list(set([shape['label'] for shape in result['json_data']['shapes']]))
 
 
 
 
 
 
 
 
 
807
  }
808
- for result in self.augmented_results
809
- ],
810
- 'statistics': {
811
- 'unique_augmentation_types': list(set([r['metadata']['augmentation_type'] for r in self.augmented_results])),
812
- 'total_polygons': sum([len(r['json_data']['shapes']) for r in self.augmented_results]),
813
- 'unique_labels': list(set([
814
- shape['label']
815
- for result in self.augmented_results
816
- for shape in result['json_data']['shapes']
817
- ])),
818
- 'average_polygons_per_image': sum([len(r['json_data']['shapes']) for r in self.augmented_results]) / len(self.augmented_results)
819
  }
820
- }
821
- zip_file.writestr('augmentation_summary.json', json.dumps(summary, indent=2, ensure_ascii=False))
822
-
823
- # Add README for the package
824
- readme_content = f"""# Augmented Dataset Package
825
 
826
  ## Overview
827
  This package contains {len(self.augmented_results)} augmented images with their corresponding LabelMe annotation files.
828
 
829
  ## Contents
830
  - **Images**: PNG format augmented images
831
- - **Annotations**: LabelMe JSON format annotation files
832
  - **Summary**: augmentation_summary.json with detailed metadata
833
 
834
  ## File Structure
835
  - Each image file (*.png) has a corresponding annotation file (*.json) with the same base name
836
  - All annotations are in standard LabelMe format without embedded image data
 
837
 
838
  ## Statistics
839
  - Total augmented images: {len(self.augmented_results)}
@@ -849,11 +880,19 @@ This package contains {len(self.augmented_results)} augmented images with their
849
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
850
  Tool: PolygonAugmentation v1.0
851
  """
852
- zip_file.writestr('README.md', readme_content)
853
-
854
- zip_buffer.seek(0)
855
- logger.info(f"Created download package with {len(self.augmented_results)} image-annotation pairs")
856
- return zip_buffer.getvalue()
 
 
 
 
 
 
 
 
857
 
858
  def create_interface():
859
  augmenter = PolygonAugmentation(tolerance=2.0, area_threshold=0.01, debug=True)
@@ -957,7 +996,34 @@ def create_interface():
957
  return [], error_msg, None
958
 
959
  def download_package():
960
- return augmenter.create_download_package()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
961
 
962
  def show_mask_overlay(evt: gr.SelectData):
963
  if evt.index < len(augmenter.augmented_results):
@@ -1042,7 +1108,7 @@ def create_interface():
1042
 
1043
  with gr.Row():
1044
  download_btn = gr.Button("📥 Download All (ZIP)", variant="secondary")
1045
- download_file = gr.File(label="Download Package", visible=False)
1046
 
1047
  gr.Markdown("## 📋 Augmentation Metadata")
1048
  json_output = gr.Code(
 
422
  if aug_type == "rotate":
423
  # For rotation, use the parameter as degrees and make it more visible
424
  rotation_angle = aug_param if abs(aug_param) >= 5 else (15 if aug_param >= 0 else -15)
425
+ # Use angle directly (not abs) and set limit as tuple for specific angle
426
+ aug_transform = A.Rotate(limit=(rotation_angle, rotation_angle), p=1.0, border_mode=cv2.BORDER_CONSTANT, value=0)
427
  logger.info(f"Applying rotation: {rotation_angle} degrees")
428
  elif aug_type == "horizontal_flip":
429
  aug_transform = A.HorizontalFlip(p=1.0 if aug_param == 1 else 0.0)
 
747
  def create_download_package(self):
748
  """Create a zip file with all augmented images and proper LabelMe JSON files"""
749
  if not self.augmented_results:
750
+ logger.warning("No augmented results available for download")
751
  return None
752
 
753
+ logger.info(f"Creating download package with {len(self.augmented_results)} results")
754
  zip_buffer = io.BytesIO()
755
 
756
+ try:
757
+ with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
758
+ # Add all augmented images and their corresponding LabelMe JSON files
759
+ for idx, result in enumerate(self.augmented_results):
760
+ filename = result['metadata']['filename']
761
+
762
+ # Save augmented image
763
+ try:
764
+ # Convert PIL image to RGB if needed
765
+ if result['image'].mode != 'RGB':
766
+ img_rgb = result['image'].convert('RGB')
767
+ else:
768
+ img_rgb = result['image']
769
+
770
+ # Save as PNG bytes
771
+ img_buffer = io.BytesIO()
772
+ img_rgb.save(img_buffer, format='PNG', optimize=True)
773
+ zip_file.writestr(filename, img_buffer.getvalue())
774
+ logger.info(f"Added image: {filename}")
775
+
776
+ except Exception as e:
777
+ logger.error(f"Error saving image {filename}: {str(e)}")
778
+ continue
779
+
780
+ # Save corresponding LabelMe JSON file
781
+ json_filename = filename.replace('.png', '.json')
782
+
783
+ try:
784
+ # Create a clean LabelMe JSON structure
785
+ clean_json_data = {
786
+ "version": "5.0.1",
787
+ "flags": {},
788
+ "shapes": [],
789
+ "imagePath": filename,
790
+ "imageData": None, # No embedded image data as requested
791
+ "imageHeight": result['json_data']['imageHeight'],
792
+ "imageWidth": result['json_data']['imageWidth'],
793
+ "imageDepth": 3
794
+ }
795
+
796
+ # Copy shapes with proper LabelMe format
797
+ for shape in result['json_data']['shapes']:
798
+ clean_shape = {
799
+ "label": shape['label'],
800
+ "points": shape['points'],
801
+ "group_id": shape.get('group_id'),
802
+ "shape_type": "polygon",
803
+ "flags": shape.get('flags', {}),
804
+ "description": shape.get('description', ''),
805
+ "iscrowd": shape.get('iscrowd', 0),
806
+ "attributes": shape.get('attributes', {})
807
+ }
808
+ clean_json_data['shapes'].append(clean_shape)
809
+
810
+ # Write JSON file
811
+ json_str = json.dumps(clean_json_data, indent=2, ensure_ascii=False)
812
+ zip_file.writestr(json_filename, json_str)
813
+ logger.info(f"Added JSON: {json_filename} with {len(clean_json_data['shapes'])} shapes")
814
+
815
+ except Exception as e:
816
+ logger.error(f"Error saving JSON {json_filename}: {str(e)}")
817
+ continue
818
 
819
+ # Add comprehensive summary metadata
820
+ summary = {
821
+ 'package_info': {
822
+ 'total_augmentations': len(self.augmented_results),
823
+ 'generation_timestamp': datetime.now().isoformat(),
824
+ 'generator': 'PolygonAugmentation v1.0',
825
+ 'format': 'LabelMe JSON + PNG images'
826
+ },
827
+ 'augmentation_summary': [
828
+ {
829
+ 'filename': result['metadata']['filename'],
830
+ 'json_file': result['metadata']['filename'].replace('.png', '.json'),
831
+ 'augmentation_type': result['metadata']['augmentation_type'],
832
+ 'parameter_value': result['metadata']['parameter_value'],
833
+ 'polygon_count': len(result['json_data']['shapes']),
834
+ 'image_size': f"{result['json_data']['imageWidth']}x{result['json_data']['imageHeight']}",
835
+ 'timestamp': result['metadata']['timestamp'],
836
+ 'labels': list(set([shape['label'] for shape in result['json_data']['shapes']]))
837
+ }
838
+ for result in self.augmented_results
839
+ ],
840
+ 'statistics': {
841
+ 'unique_augmentation_types': list(set([r['metadata']['augmentation_type'] for r in self.augmented_results])),
842
+ 'total_polygons': sum([len(r['json_data']['shapes']) for r in self.augmented_results]),
843
+ 'unique_labels': list(set([
844
+ shape['label']
845
+ for result in self.augmented_results
846
+ for shape in result['json_data']['shapes']
847
+ ])),
848
+ 'average_polygons_per_image': sum([len(r['json_data']['shapes']) for r in self.augmented_results]) / len(self.augmented_results) if self.augmented_results else 0
849
  }
 
 
 
 
 
 
 
 
 
 
 
850
  }
851
+ zip_file.writestr('augmentation_summary.json', json.dumps(summary, indent=2, ensure_ascii=False))
852
+
853
+ # Add README for the package
854
+ readme_content = f"""# Augmented Dataset Package
 
855
 
856
  ## Overview
857
  This package contains {len(self.augmented_results)} augmented images with their corresponding LabelMe annotation files.
858
 
859
  ## Contents
860
  - **Images**: PNG format augmented images
861
+ - **Annotations**: LabelMe JSON format annotation files (standard format)
862
  - **Summary**: augmentation_summary.json with detailed metadata
863
 
864
  ## File Structure
865
  - Each image file (*.png) has a corresponding annotation file (*.json) with the same base name
866
  - All annotations are in standard LabelMe format without embedded image data
867
+ - Compatible with LabelMe, CVAT, and other annotation tools
868
 
869
  ## Statistics
870
  - Total augmented images: {len(self.augmented_results)}
 
880
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
881
  Tool: PolygonAugmentation v1.0
882
  """
883
+ zip_file.writestr('README.md', readme_content)
884
+
885
+ logger.info("Successfully created ZIP package with all files")
886
+
887
+ zip_buffer.seek(0)
888
+ logger.info(f"Created download package with {len(self.augmented_results)} image-annotation pairs")
889
+ return zip_buffer.getvalue()
890
+
891
+ except Exception as e:
892
+ logger.error(f"Error creating ZIP package: {str(e)}")
893
+ import traceback
894
+ logger.error(traceback.format_exc())
895
+ return None
896
 
897
  def create_interface():
898
  augmenter = PolygonAugmentation(tolerance=2.0, area_threshold=0.01, debug=True)
 
996
  return [], error_msg, None
997
 
998
  def download_package():
999
+ """Handle download package creation and return proper file data"""
1000
+ try:
1001
+ package_data = augmenter.create_download_package()
1002
+ if package_data is None:
1003
+ return None
1004
+
1005
+ # Save the package to a temporary file for download
1006
+ import tempfile
1007
+ import os
1008
+
1009
+ # Create temporary file with proper name
1010
+ temp_file = tempfile.NamedTemporaryFile(
1011
+ delete=False,
1012
+ suffix='.zip',
1013
+ prefix='augmented_dataset_'
1014
+ )
1015
+
1016
+ with open(temp_file.name, 'wb') as f:
1017
+ f.write(package_data)
1018
+
1019
+ logger.info(f"Created download package: {temp_file.name}")
1020
+ return temp_file.name
1021
+
1022
+ except Exception as e:
1023
+ logger.error(f"Error creating download package: {str(e)}")
1024
+ import traceback
1025
+ logger.error(traceback.format_exc())
1026
+ return None
1027
 
1028
  def show_mask_overlay(evt: gr.SelectData):
1029
  if evt.index < len(augmenter.augmented_results):
 
1108
 
1109
  with gr.Row():
1110
  download_btn = gr.Button("📥 Download All (ZIP)", variant="secondary")
1111
+ download_file = gr.File(label="Download Package", visible=True)
1112
 
1113
  gr.Markdown("## 📋 Augmentation Metadata")
1114
  json_output = gr.Code(