dixisouls commited on
Commit
65c0c50
·
verified ·
1 Parent(s): 89ee5b3

Changed saving file location to /tmp

Browse files
Files changed (1) hide show
  1. api.py +93 -30
api.py CHANGED
@@ -15,9 +15,13 @@ from app.scene_graph_service import process_image
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
 
 
 
 
18
  # Create necessary directories
19
- os.makedirs("uploads", exist_ok=True)
20
- os.makedirs("outputs", exist_ok=True)
21
  os.makedirs("app/models", exist_ok=True)
22
 
23
  # Initialize FastAPI app
@@ -47,10 +51,21 @@ async def generate_scene_graph(
47
  use_fixed_boxes: bool = Form(False),
48
  ) -> Dict[str, Any]:
49
  try:
50
- # Input validation
 
 
 
 
 
 
 
 
 
 
 
51
  if not image.content_type.startswith("image/"):
52
  raise HTTPException(
53
- status_code=400, detail="Uploaded file must be an image"
54
  )
55
 
56
  if not (0 <= confidence_threshold <= 1):
@@ -62,27 +77,57 @@ async def generate_scene_graph(
62
  job_id = str(uuid.uuid4())
63
  short_id = job_id.split("-")[0]
64
 
65
- # Create directories for this job
66
- upload_dir = os.path.join("uploads", job_id)
67
- output_dir = os.path.join("outputs", job_id)
68
- os.makedirs(upload_dir, exist_ok=True)
69
- os.makedirs(output_dir, exist_ok=True)
70
-
71
- # Save the uploaded image
72
- original_filename = image.filename
73
- _, ext = os.path.splitext(original_filename)
74
- image_filename = f"{short_id}{ext}"
75
- image_path = os.path.join(upload_dir, image_filename)
76
-
77
- # Save the file
78
- with open(image_path, "wb") as buffer:
79
- shutil.copyfileobj(image.file, buffer)
80
-
81
- logger.info(f"Image saved to {image_path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
  # Define model paths
84
  model_path = "app/models/model.pth"
85
  vocabulary_path = "app/models/vocabulary.json"
 
 
 
 
 
 
 
 
 
86
 
87
  # Process the image
88
  objects, relationships, annotated_image_path, graph_path = process_image(
@@ -91,16 +136,33 @@ async def generate_scene_graph(
91
  vocabulary_path=vocabulary_path,
92
  confidence_threshold=confidence_threshold,
93
  use_fixed_boxes=use_fixed_boxes,
94
- output_dir=output_dir,
95
  base_filename=short_id,
96
  )
 
 
 
 
 
 
 
 
 
 
 
97
 
98
  # Read the generated images as base64
99
- with open(annotated_image_path, "rb") as img_file:
100
- annotated_image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
101
-
102
- with open(graph_path, "rb") as img_file:
103
- graph_image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
 
 
 
 
 
 
104
 
105
  # Prepare response with base64 encoded images
106
  response = {
@@ -112,15 +174,16 @@ async def generate_scene_graph(
112
 
113
  # Clean up
114
  try:
115
- shutil.rmtree(upload_dir)
116
- shutil.rmtree(output_dir)
 
117
  except Exception as e:
118
  logger.warning(f"Error cleaning up temporary files: {str(e)}")
119
 
120
  return response
121
 
122
  except Exception as e:
123
- logger.error(f"Error processing image: {str(e)}")
124
  raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
125
 
126
 
 
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
+ # Use /tmp directory which should be writable
19
+ UPLOAD_DIR = "/tmp/uploads"
20
+ OUTPUT_DIR = "/tmp/outputs"
21
+
22
  # Create necessary directories
23
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
24
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
25
  os.makedirs("app/models", exist_ok=True)
26
 
27
  # Initialize FastAPI app
 
51
  use_fixed_boxes: bool = Form(False),
52
  ) -> Dict[str, Any]:
53
  try:
54
+ # Debug information
55
+ logger.info(f"Received file: {image.filename}, content_type: {image.content_type}")
56
+
57
+ # Input validation with improved error handling
58
+ if image is None:
59
+ raise HTTPException(status_code=400, detail="No image file provided")
60
+
61
+ if not image.content_type:
62
+ # Set a default content type if none provided
63
+ logger.warning("No content type provided, assuming image/jpeg")
64
+ image.content_type = "image/jpeg"
65
+
66
  if not image.content_type.startswith("image/"):
67
  raise HTTPException(
68
+ status_code=400, detail=f"Uploaded file must be an image, got {image.content_type}"
69
  )
70
 
71
  if not (0 <= confidence_threshold <= 1):
 
77
  job_id = str(uuid.uuid4())
78
  short_id = job_id.split("-")[0]
79
 
80
+ # Create directories for this job in /tmp which should be writable
81
+ upload_job_dir = os.path.join(UPLOAD_DIR, job_id)
82
+ output_job_dir = os.path.join(OUTPUT_DIR, job_id)
83
+
84
+ # Create directories with explicit permission setting
85
+ os.makedirs(upload_job_dir, exist_ok=True, mode=0o777)
86
+ os.makedirs(output_job_dir, exist_ok=True, mode=0o777)
87
+
88
+ logger.info(f"Created upload directory: {upload_job_dir}")
89
+ logger.info(f"Created output directory: {output_job_dir}")
90
+
91
+ # Determine file extension
92
+ file_ext = os.path.splitext(image.filename)[1] if image.filename else ".jpg"
93
+ if not file_ext:
94
+ file_ext = ".jpg"
95
+
96
+ # Save the uploaded image to /tmp
97
+ image_filename = f"{short_id}{file_ext}"
98
+ image_path = os.path.join(upload_job_dir, image_filename)
99
+
100
+ # Save the file with error handling
101
+ try:
102
+ # Explicitly open with write permissions
103
+ with open(image_path, "wb") as buffer:
104
+ contents = await image.read()
105
+ buffer.write(contents)
106
+
107
+ # Check if file was created and has size
108
+ if not os.path.exists(image_path):
109
+ raise HTTPException(status_code=400, detail=f"Failed to save uploaded file to {image_path}")
110
+
111
+ if os.path.getsize(image_path) == 0:
112
+ raise HTTPException(status_code=400, detail="Uploaded file is empty")
113
+
114
+ logger.info(f"Image saved to {image_path} ({os.path.getsize(image_path)} bytes)")
115
+ except Exception as e:
116
+ logger.error(f"Error saving file: {str(e)}")
117
+ raise HTTPException(status_code=500, detail=f"Error saving uploaded file: {str(e)}")
118
 
119
  # Define model paths
120
  model_path = "app/models/model.pth"
121
  vocabulary_path = "app/models/vocabulary.json"
122
+
123
+ # Check if model files exist
124
+ if not os.path.exists(model_path):
125
+ logger.error(f"Model file not found: {model_path}")
126
+ raise HTTPException(status_code=500, detail=f"Model file not found: {model_path}")
127
+
128
+ if not os.path.exists(vocabulary_path):
129
+ logger.error(f"Vocabulary file not found: {vocabulary_path}")
130
+ raise HTTPException(status_code=500, detail=f"Vocabulary file not found: {vocabulary_path}")
131
 
132
  # Process the image
133
  objects, relationships, annotated_image_path, graph_path = process_image(
 
136
  vocabulary_path=vocabulary_path,
137
  confidence_threshold=confidence_threshold,
138
  use_fixed_boxes=use_fixed_boxes,
139
+ output_dir=output_job_dir,
140
  base_filename=short_id,
141
  )
142
+
143
+ logger.info(f"Processing complete. Annotated image: {annotated_image_path}, Graph: {graph_path}")
144
+
145
+ # Verify output files exist
146
+ if not os.path.exists(annotated_image_path):
147
+ logger.error(f"Annotated image not generated: {annotated_image_path}")
148
+ raise HTTPException(status_code=500, detail="Failed to generate annotated image")
149
+
150
+ if not os.path.exists(graph_path):
151
+ logger.error(f"Graph image not generated: {graph_path}")
152
+ raise HTTPException(status_code=500, detail="Failed to generate graph image")
153
 
154
  # Read the generated images as base64
155
+ try:
156
+ with open(annotated_image_path, "rb") as img_file:
157
+ annotated_image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
158
+
159
+ with open(graph_path, "rb") as img_file:
160
+ graph_image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
161
+
162
+ logger.info("Successfully encoded images as base64")
163
+ except Exception as e:
164
+ logger.error(f"Error reading output images: {str(e)}")
165
+ raise HTTPException(status_code=500, detail=f"Error reading output images: {str(e)}")
166
 
167
  # Prepare response with base64 encoded images
168
  response = {
 
174
 
175
  # Clean up
176
  try:
177
+ shutil.rmtree(upload_job_dir)
178
+ shutil.rmtree(output_job_dir)
179
+ logger.info("Cleaned up temporary directories")
180
  except Exception as e:
181
  logger.warning(f"Error cleaning up temporary files: {str(e)}")
182
 
183
  return response
184
 
185
  except Exception as e:
186
+ logger.error(f"Error processing image: {str(e)}", exc_info=True)
187
  raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
188
 
189