Skip to content
Open
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
155 changes: 155 additions & 0 deletions BACKEND/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
import requests
import cv2
import numpy as np
from flask import Flask, request, jsonify
from flask_cors import CORS
import base64
import io
from PIL import Image
import os

app = Flask(__name__)
CORS(app, origins=['https://frontend-recyclopedia.vercel.app', 'https://recyclopedia-xi.vercel.app', 'http://localhost:5173', 'http://localhost:3000', 'http://localhost:8080'])

model_url = "https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/float16/latest/efficientdet_lite0.tflite"
model_path = "efficientdet_lite0.tflite"

try:
with open(model_path, "rb") as model_file:
pass
except FileNotFoundError:
model_response = requests.get(model_url)
with open(model_path, "wb") as model_file:
model_file.write(model_response.content)

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

BaseOptions = mp.tasks.BaseOptions
ObjectDetector = mp.tasks.vision.ObjectDetector
ObjectDetectorOptions = mp.tasks.vision.ObjectDetectorOptions
VisionRunningMode = mp.tasks.vision.RunningMode

VISUALIZATION_MARGIN = 10
TEXT_ROW_SIZE = 10
TEXT_FONT_SIZE = 1
TEXT_FONT_THICKNESS = 1
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

Recyclable = {
"bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl",
"book", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "refrigerator", "clock"
}

Non_Recyclable = {
"car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench",
"backpack", "umbrella", "handbag", "tie", "suitcase",
"frisbee", "skis", "snowboard", "baseball bat", "baseball glove",
"skateboard", "surfboard", "tennis racket",
"chair", "couch", "bed", "dining table", "toilet", "potted plant",
"scissors", "teddy bear", "hair drier", "toothbrush"
}

Organic = {
"banana", "apple", "sandwich", "orange", "broccoli", "carrot",
"hot dog", "pizza", "donut", "cake",
"bird", "cat", "dog", "horse", "sheep", "cow", "elephant",
"bear", "zebra", "giraffe"
}

def visualize(input_image, detection_result):
for detection in detection_result.detections:
bounding_box = detection.bounding_box
box_start = bounding_box.origin_x, bounding_box.origin_y
box_end = bounding_box.origin_x + bounding_box.width, bounding_box.origin_y + bounding_box.height

detected_object = detection.categories[0]
object_name = detected_object.category_name
confidence_score = round(detected_object.score, 2)

box_color = RED if object_name in Non_Recyclable else BLUE if object_name in Recyclable else GREEN if object_name in Organic else (255, 255, 255)

cv2.rectangle(input_image, box_start, box_end, box_color, 3)

label_text = f"{object_name} ({confidence_score})"
text_position = (bounding_box.origin_x + VISUALIZATION_MARGIN, bounding_box.origin_y - VISUALIZATION_MARGIN)
cv2.putText(input_image, label_text, text_position, cv2.FONT_HERSHEY_PLAIN, TEXT_FONT_SIZE, box_color, TEXT_FONT_THICKNESS)

return input_image

def get_object_classification(object_name):
if object_name in Recyclable:
return "Recyclable"
elif object_name in Non_Recyclable:
return "Non-Recyclable"
elif object_name in Organic:
return "Organic"
return "Unknown"

@app.route('/detect', methods=['POST'])
def detect_objects():
try:
received_image_data = request.json.get('image')
if not received_image_data:
return jsonify({'error': 'No image data provided'}), 400

image_bytes = base64.b64decode(received_image_data.split(',')[1])
pil_image = Image.open(io.BytesIO(image_bytes))

opencv_image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
mediapipe_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB))

detector_options = ObjectDetectorOptions(
base_options=BaseOptions(model_asset_path=model_path),
max_results=5,
running_mode=VisionRunningMode.IMAGE,
score_threshold=0.5)

with ObjectDetector.create_from_options(detector_options) as object_detector:
detection_results = object_detector.detect(mediapipe_image)

if not detection_results.detections:
return jsonify({
'detections': [],
'annotated_image': received_image_data
})

processed_detections = []
for detection in detection_results.detections:
detected_category = detection.categories[0]
detected_box = detection.bounding_box
processed_detections.append({
'category': detected_category.category_name,
'classification': get_object_classification(detected_category.category_name),
'score': round(float(detected_category.score), 2),
'bbox': {
'x': detected_box.origin_x,
'y': detected_box.origin_y,
'width': detected_box.width,
'height': detected_box.height
}
})

image_for_visualization = np.copy(mediapipe_image.numpy_view())
annotated_result = visualize(image_for_visualization, detection_results)

_, encoded_buffer = cv2.imencode('.jpg', cv2.cvtColor(annotated_result, cv2.COLOR_BGR2RGB))
base64_image = base64.b64encode(encoded_buffer).decode('utf-8')

return jsonify({
'detections': processed_detections,
'annotated_image': f'data:image/jpeg;base64,{base64_image}'
})

except Exception as error:
print(f"Error in detection: {str(error)}")
return jsonify({'error': str(error)}), 500

if __name__ == '__main__':
app.run(debug=True, port=5002)
Binary file added BACKEND/efficientdet_lite0.tflite
Binary file not shown.
3 changes: 3 additions & 0 deletions BACKEND/gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bind = "0.0.0.0:10000"
workers = 2
timeout = 120
Binary file added BACKEND/images/img.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 BACKEND/images/img2.png
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 BACKEND/images/img3.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 BACKEND/images/img4.jpeg
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 BACKEND/images/img5.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 BACKEND/images/peel.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions BACKEND/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
flask==3.0.2
flask-cors==4.0.0
mediapipe==0.10.5
opencv-python==4.8.1.78
pillow==10.2.0
requests==2.31.0
numpy==1.24.3
gunicorn==21.2.0
69 changes: 69 additions & 0 deletions FRONTEND/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Welcome to your Lovable project

## Project info

**URL**: https://lovable.dev/projects/5fd8d356-14c6-4a8d-b53c-c2fb7cf89fa0

## How can I edit this code?

There are several ways of editing your application.

**Use Lovable**

Simply visit the [Lovable Project](https://lovable.dev/projects/5fd8d356-14c6-4a8d-b53c-c2fb7cf89fa0) and start prompting.

Changes made via Lovable will be committed automatically to this repo.

**Use your preferred IDE**

If you want to work locally using your own IDE, you can clone this repo and push changes. Pushed changes will also be reflected in Lovable.

The only requirement is having Node.js & npm installed - [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating)

Follow these steps:

```sh
# Step 1: Clone the repository using the project's Git URL.
git clone <YOUR_GIT_URL>

# Step 2: Navigate to the project directory.
cd <YOUR_PROJECT_NAME>

# Step 3: Install the necessary dependencies.
npm i

# Step 4: Start the development server with auto-reloading and an instant preview.
npm run dev
```

**Edit a file directly in GitHub**

- Navigate to the desired file(s).
- Click the "Edit" button (pencil icon) at the top right of the file view.
- Make your changes and commit the changes.

**Use GitHub Codespaces**

- Navigate to the main page of your repository.
- Click on the "Code" button (green button) near the top right.
- Select the "Codespaces" tab.
- Click on "New codespace" to launch a new Codespace environment.
- Edit files directly within the Codespace and commit and push your changes once you're done.

## What technologies are used for this project?

This project is built with .

- Vite
- TypeScript
- React
- shadcn-ui
- Tailwind CSS

## How can I deploy this project?

Simply open [Lovable](https://lovable.dev/projects/5fd8d356-14c6-4a8d-b53c-c2fb7cf89fa0) and click on Share -> Publish.

## I want to use a custom domain - is that possible?

We don't support custom domains (yet). If you want to deploy your project under your own domain then we recommend using Netlify. Visit our docs for more details: [Custom domains](https://docs.lovable.dev/tips-tricks/custom-domain/)
Binary file added FRONTEND/bun.lockb
Binary file not shown.
20 changes: 20 additions & 0 deletions FRONTEND/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
29 changes: 29 additions & 0 deletions FRONTEND/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
"@typescript-eslint/no-unused-vars": "off",
},
}
);
16 changes: 16 additions & 0 deletions FRONTEND/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Waste Segregation</title>
</head>

<body>
<div id="root"></div>
<!-- IMPORTANT: DO NOT REMOVE THIS SCRIPT TAG OR THIS VERY COMMENT! -->
<script src="https://cdn.gpteng.co/gptengineer.js" type="module"></script>
<script type="module" src="/src/main.tsx"></script>

</body>
</html>
8 changes: 8 additions & 0 deletions FRONTEND/netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[build]
command = "npm run build"
publish = "dist"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Loading