Upload 8 files
Browse files- Objectdetection/__pycache__/model_loader.cpython-310.pyc +0 -0
- Objectdetection/__pycache__/utils.cpython-310.pyc +0 -0
- Objectdetection/model_loader.py +14 -0
- Objectdetection/objectdetection.py +35 -0
- Objectdetection/objectdetection_model.pth +3 -0
- Objectdetection/static/style.css +45 -0
- Objectdetection/templates/index.html +48 -0
- Objectdetection/utils.py +54 -0
Objectdetection/__pycache__/model_loader.cpython-310.pyc
ADDED
|
Binary file (671 Bytes). View file
|
|
|
Objectdetection/__pycache__/utils.cpython-310.pyc
ADDED
|
Binary file (1.55 kB). View file
|
|
|
Objectdetection/model_loader.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torchvision
|
| 3 |
+
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
|
| 4 |
+
|
| 5 |
+
def get_model(num_classes):
|
| 6 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 7 |
+
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
|
| 8 |
+
|
| 9 |
+
in_features = model.roi_heads.box_predictor.cls_score.in_features
|
| 10 |
+
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
|
| 11 |
+
|
| 12 |
+
model.to(device)
|
| 13 |
+
model.eval()
|
| 14 |
+
return model, device
|
Objectdetection/objectdetection.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Flask, render_template, request, send_from_directory
|
| 2 |
+
import os
|
| 3 |
+
from model_loader import get_model
|
| 4 |
+
from utils import process_video
|
| 5 |
+
|
| 6 |
+
app = Flask(__name__)
|
| 7 |
+
UPLOAD_FOLDER = 'static/uploads'
|
| 8 |
+
RESULT_FOLDER = 'static/results'
|
| 9 |
+
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
| 10 |
+
os.makedirs(RESULT_FOLDER, exist_ok=True)
|
| 11 |
+
|
| 12 |
+
num_classes = 21
|
| 13 |
+
model, device = get_model(num_classes)
|
| 14 |
+
|
| 15 |
+
@app.route('/', methods=['GET', 'POST'])
|
| 16 |
+
def index():
|
| 17 |
+
if request.method == 'POST':
|
| 18 |
+
file = request.files['video']
|
| 19 |
+
if file:
|
| 20 |
+
filepath = os.path.join(UPLOAD_FOLDER, file.filename)
|
| 21 |
+
file.save(filepath)
|
| 22 |
+
|
| 23 |
+
output_path = os.path.join(RESULT_FOLDER, 'result_' + file.filename)
|
| 24 |
+
result_path = process_video(filepath, model, output_path, device)
|
| 25 |
+
|
| 26 |
+
return render_template('index.html', video_result=result_path)
|
| 27 |
+
|
| 28 |
+
return render_template('index.html', video_result=None)
|
| 29 |
+
|
| 30 |
+
@app.route('/static/<path:path>')
|
| 31 |
+
def send_static(path):
|
| 32 |
+
return send_from_directory('static', path)
|
| 33 |
+
|
| 34 |
+
if __name__ == '__main__':
|
| 35 |
+
app.run(debug=True)
|
Objectdetection/objectdetection_model.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f516fd07beeb67a4a5939b8778f0b17c9fd6a70965ccc30ea9d84c845e5182e7
|
| 3 |
+
size 166116798
|
Objectdetection/static/style.css
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
body {
|
| 2 |
+
font-family: Arial, sans-serif;
|
| 3 |
+
background-color: #f8f9fa;
|
| 4 |
+
padding: 40px;
|
| 5 |
+
text-align: center;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
h1, h2 {
|
| 9 |
+
color: #333;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
form {
|
| 13 |
+
background-color: #fff;
|
| 14 |
+
padding: 20px;
|
| 15 |
+
margin: 0 auto 30px;
|
| 16 |
+
border-radius: 8px;
|
| 17 |
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
| 18 |
+
display: inline-block;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
input[type="file"],
|
| 22 |
+
select,
|
| 23 |
+
input[type="submit"] {
|
| 24 |
+
margin: 10px;
|
| 25 |
+
padding: 10px;
|
| 26 |
+
font-size: 16px;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
input[type="submit"] {
|
| 30 |
+
background-color: #007bff;
|
| 31 |
+
color: white;
|
| 32 |
+
border: none;
|
| 33 |
+
cursor: pointer;
|
| 34 |
+
border-radius: 5px;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
input[type="submit"]:hover {
|
| 38 |
+
background-color: #0056b3;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
img, video {
|
| 42 |
+
margin-top: 15px;
|
| 43 |
+
border-radius: 10px;
|
| 44 |
+
border: 2px solid #ccc;
|
| 45 |
+
}
|
Objectdetection/templates/index.html
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>Object Detection</title>
|
| 6 |
+
<style>
|
| 7 |
+
body {
|
| 8 |
+
font-family: Arial, sans-serif;
|
| 9 |
+
background: #f5f5f5;
|
| 10 |
+
padding: 30px;
|
| 11 |
+
text-align: center;
|
| 12 |
+
}
|
| 13 |
+
.container {
|
| 14 |
+
background: white;
|
| 15 |
+
padding: 20px;
|
| 16 |
+
border-radius: 8px;
|
| 17 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
| 18 |
+
display: inline-block;
|
| 19 |
+
}
|
| 20 |
+
input[type="file"], input[type="submit"] {
|
| 21 |
+
margin: 10px;
|
| 22 |
+
padding: 8px 12px;
|
| 23 |
+
border-radius: 4px;
|
| 24 |
+
}
|
| 25 |
+
video {
|
| 26 |
+
max-width: 100%;
|
| 27 |
+
margin-top: 20px;
|
| 28 |
+
}
|
| 29 |
+
</style>
|
| 30 |
+
</head>
|
| 31 |
+
<body>
|
| 32 |
+
<div class="container">
|
| 33 |
+
<h1>Object Detection (Video)</h1>
|
| 34 |
+
<form method="POST" enctype="multipart/form-data">
|
| 35 |
+
<input type="file" name="video" accept="video/*" required>
|
| 36 |
+
<br>
|
| 37 |
+
<input type="submit" value="Upload & Detect">
|
| 38 |
+
</form>
|
| 39 |
+
{% if video_result %}
|
| 40 |
+
<h2>Result Video</h2>
|
| 41 |
+
<video controls>
|
| 42 |
+
<source src="{{ video_result }}" type="video/mp4">
|
| 43 |
+
Your browser does not support the video tag.
|
| 44 |
+
</video>
|
| 45 |
+
{% endif %}
|
| 46 |
+
</div>
|
| 47 |
+
</body>
|
| 48 |
+
</html>
|
Objectdetection/utils.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cv2
|
| 2 |
+
import torch
|
| 3 |
+
import os
|
| 4 |
+
import numpy as np
|
| 5 |
+
from torchvision import transforms
|
| 6 |
+
|
| 7 |
+
def process_video(video_path, model, output_path, device):
|
| 8 |
+
transform = transforms.Compose([
|
| 9 |
+
transforms.ToTensor()
|
| 10 |
+
])
|
| 11 |
+
|
| 12 |
+
cap = cv2.VideoCapture(str(video_path))
|
| 13 |
+
if not cap.isOpened():
|
| 14 |
+
raise IOError(f"Cannot open video: {video_path}")
|
| 15 |
+
|
| 16 |
+
fourcc = cv2.VideoWriter_fourcc(*'XVID')
|
| 17 |
+
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 18 |
+
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 19 |
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
| 20 |
+
|
| 21 |
+
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
|
| 22 |
+
|
| 23 |
+
frame_skip = 2
|
| 24 |
+
frame_count = 0
|
| 25 |
+
|
| 26 |
+
while cap.isOpened():
|
| 27 |
+
ret, frame = cap.read()
|
| 28 |
+
if not ret:
|
| 29 |
+
break
|
| 30 |
+
|
| 31 |
+
resized_frame = cv2.resize(frame, (640, 480))
|
| 32 |
+
|
| 33 |
+
if frame_count % frame_skip == 0:
|
| 34 |
+
rgb_frame = cv2.cvtColor(resized_frame, cv2.COLOR_BGR2RGB)
|
| 35 |
+
img_tensor = transform(rgb_frame).to(device)
|
| 36 |
+
|
| 37 |
+
with torch.no_grad():
|
| 38 |
+
prediction = model([img_tensor])[0]
|
| 39 |
+
|
| 40 |
+
for box, score, label in zip(prediction["boxes"], prediction["scores"], prediction["labels"]):
|
| 41 |
+
if score > 0.5:
|
| 42 |
+
x1, y1, x2, y2 = map(int, box)
|
| 43 |
+
cv2.rectangle(resized_frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
| 44 |
+
cv2.putText(resized_frame, f"{label.item()}:{score:.2f}", (x1, y1 - 10),
|
| 45 |
+
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
|
| 46 |
+
|
| 47 |
+
output_frame = cv2.resize(resized_frame, (width, height))
|
| 48 |
+
out.write(output_frame)
|
| 49 |
+
|
| 50 |
+
frame_count += 1
|
| 51 |
+
|
| 52 |
+
cap.release()
|
| 53 |
+
out.release()
|
| 54 |
+
return output_path
|