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

integrate frontend with backend #28

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions api/src/routes/imageRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Router } from "express";
import { ImageController } from "../controllers/imageController";
import { upload } from "../middlewares/multerConfig";
import { ImageService } from "../services/imageService";

const router = Router();

Expand All @@ -12,4 +13,14 @@ router.post("/upload", upload.single("image"), async (req, res) => {
}
});

// In your imageRoutes.ts
router.get("/", async (req, res) => {
try {
const images = await ImageService.getAllImages(); // Implement this method in your ImageService
res.status(200).json(images);
} catch (error) {
res.status(500).json({ message: "Error fetching images", error: error });
}
});

export default router;
14 changes: 14 additions & 0 deletions api/src/services/imageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,18 @@ export class ImageService {
}

// Optional: You can create other methods for fetching or managing images.

static async getAllImages(): Promise<Image[]> {
const query = `SELECT * FROM images ORDER BY created_at DESC`; // Adjust the query as necessary
try {
const result = await pool.query(query);
return result.rows; // Return the array of images
} catch (error: unknown) {
if (error instanceof Error) {
throw new Error("Error fetching images from the database: " + error.message);
} else {
throw new Error("Unknown error occurred");
}
}
}
}
26 changes: 23 additions & 3 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 57 additions & 13 deletions app/src/Pages/Annotate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,76 @@ const Annotate = () => {

const handleUpload = async () => {
if (!selectedImage) return;

setIsUploading(true);
try {
// TODO: Implement actual backend upload
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulate upload
setUploadedImage(selectedImage);
setSelectedImage(null);
const formData = new FormData();
const blob = await fetch(selectedImage).then((res) => res.blob());
formData.append('image', blob);

const response = await fetch('http://127.0.0.1:5001/api/images/upload', { // Update the URL to match your backend
method: 'POST',
body: formData,
});

if (!response.ok) {
throw new Error(`Failed to upload. Status: ${response.status}`);
}

const uploadData = await response.json();
console.log('Fetched image metadata:', uploadData);
setUploadedImage(uploadData.image.url); // Save the uploaded image URL
alert(uploadData.message); // Display success message

// Fetch uploaded image metadata
await fetchImageMetadata(); // Call the function to fetch metadata
} catch (error) {
console.error('Upload failed:', error);
alert(`Error: ${error}`); // Display error message
} finally {
setIsUploading(false);
}
};

const fetchImageMetadata = async () => {
try {
const response = await fetch('http://127.0.0.1:5001/api/images'); // Update the URL to match your backend
if (!response.ok) {
throw new Error(`Failed to fetch metadata. Status: ${response.status}`);
}
const metadata = await response.json();
// Assuming metadata is an array of images
console.log('Fetched image metadata:', metadata);
// You can store this metadata in state to display it in your component
} catch (error) {
console.error('Failed to fetch metadata:', error);
alert(`Error: ${error}`); // Display error message
}
};

const handleDetection = async () => {
if (!uploadedImage) return;

setIsProcessing(true);
try {
// TODO: Implement actual object detection
await new Promise(resolve => setTimeout(resolve, 2000)); // Simulate processing
// Sample annotations
setAnnotations([
{ x: 100, y: 100, width: 200, height: 150, label: 'Object 1' },
{ x: 400, y: 300, width: 150, height: 100, label: 'Object 2' },
]);
const formData = new FormData();
const imageBlob = await fetch(uploadedImage).then(res => res.blob()); // Fetch the image as a blob
formData.append('image', imageBlob, 'image.jpg'); // Append the image blob to FormData

const response = await fetch('http://127.0.0.1:5001/api/detect', {
method: 'POST',
body: formData, // Send the FormData containing the image
});

if (!response.ok) {
throw new Error(`Detection failed. Status: ${response.status}`);
}

const detectionData = await response.json();
console.log('Detection successful:', detectionData);

// Assuming detectionData contains annotations
setAnnotations(detectionData.predictions); // Set the annotations from the response
} catch (error) {
console.error('Detection failed:', error);
} finally {
Expand Down
68 changes: 57 additions & 11 deletions object-detector/app.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,75 @@
from flask import Flask, request, jsonify
from flask import Flask, request, jsonify, send_from_directory, url_for
import os
import torch
from PIL import Image
from io import BytesIO
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

CORS(app, resources={r"/api/*": {"origins": "http://localhost:3000"}})

# Ensure you have a directory to save uploaded images
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# Set the folder to serve static files (images)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['STATIC_FOLDER'] = 'static'

# Load the YOLOv5 medium model (this will automatically download the weights)
model = torch.hub.load('ultralytics/yolov5', 'yolov5m')

@app.route('/predict', methods=['POST'])
def predict():
image_predictions = {}

@app.route('/api/images/upload', methods=['POST'])
def upload_image():
# Get the image from the request
file = request.files['image']
if not file:
return jsonify({"message": "No file uploaded"}), 400

# Open the image using PIL
img = Image.open(BytesIO(file.read()))

# Save the image
image_path = os.path.join(UPLOAD_FOLDER, file.filename)
file.save(image_path)

# Run inference with the model on the uploaded image
img = Image.open(image_path)
results = model(img)
# Get the results as a pandas DataFrame

# Get the results as a pandas DataFrame (if you want predictions)
predictions = results.pandas().xywh[0].to_dict(orient="records") # Get predictions as a list of dictionaries

# Return the predictions as a JSON response
return jsonify(predictions)

# Store predictions in the global dictionary
image_predictions[file.filename] = predictions

# Return the predictions and image path as a JSON response
return jsonify({
"message": "Image uploaded successfully",
"image": {
"url": url_for('uploaded_file', filename=file.filename), # Adjust URL using Flask's url_for
"predictions": predictions # Return predictions in response
}
}), 200

@app.route('/api/images', methods=['GET'])
def get_images():
# List all uploaded images
images = []
for filename in os.listdir(UPLOAD_FOLDER):
if filename.endswith(('.png', '.jpg', '.jpeg')):
predictions = image_predictions.get(filename, [])
images.append({
"url": url_for('uploaded_file', filename=filename), # Ensure proper URL for image
"filename": filename,
"predictions": predictions
})
return jsonify(images), 200

@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

if __name__ == '__main__':
app.run(debug=True, port=5001)
2 changes: 1 addition & 1 deletion object-detector/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Flask==3.1.0
requests==2.25.1
numpy==2.1.3
numpy
torch==2.5.1
torchvision==0.20.1
pillow==11.0.0
Expand Down
Binary file added object-detector/uploads/ana.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added object-detector/uploads/blob
Binary file not shown.
Binary file added object-detector/uploads/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.