Skip to content

Commit

Permalink
Merge pull request TAHIR0110#36 from SAM-DEV007/Suicide_Detection
Browse files Browse the repository at this point in the history
Suicide attempt detection
  • Loading branch information
TAHIR0110 authored May 12, 2024
2 parents d675cf6 + d7af578 commit fbbb641
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 0 deletions.
175 changes: 175 additions & 0 deletions Suicide_Detection/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

Model/Datasets

Model/Model_Train.py
Model/Model_Data/logs/backup.txt
yolov8n.pt

Model/rope-detection-640.ipynb
Model/rope-detection-480.ipynb

Model/Model_Data/logs/runs/detect/SuicideDetection/*
Model/Model_Data/logs/runs/detect/SuicideDetection2/*

!Model/Model_Data/logs/runs/detect/SuicideDetection/weights
!Model/Model_Data/logs/runs/detect/SuicideDetection2/weights
6 changes: 6 additions & 0 deletions Suicide_Detection/Model/Model_Data/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
names:
0: rope
path: D:\Projects\Open Source\ThereForYou\ThereForYou\Suicide_Detection\Model\Datasets\Processed
test: test/images
train: train/images
val: val/images
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
34 changes: 34 additions & 0 deletions Suicide_Detection/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import detect
import cv2


if __name__ == '__main__':
vid = cv2.VideoCapture(0)
vid.set(3, 640)
vid.set(4, 640)

_, frame = vid.read()
h, w, _ = frame.shape

while vid.isOpened():
_, frame = vid.read()
frame = cv2.flip(frame, 1)

# Face
face_box = detect.face_detection(frame, w, h)

# Hands
hands_box = detect.hand_detection(frame, w, h)

# Rope
rope_box = detect.rope_detection(frame, (w, h))

# Add text
txt = detect.suicide_prevention(rope_box, face_box, hands_box)
cv2.putText(frame, txt, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 1, cv2.LINE_AA)

cv2.imshow('Cam', frame)

if cv2.waitKey(1) & 0xFF == ord('q'): break # Exit when 'q' is pressed
if cv2.waitKey(1) == 27: break # Exit when 'ESC' is pressed
if cv2.getWindowProperty('Cam', cv2.WND_PROP_VISIBLE) < 1: break # Exit when window is closed
147 changes: 147 additions & 0 deletions Suicide_Detection/detect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from ultralytics import YOLO
from pathlib import Path
from ultralytics.utils.plotting import Annotator

import cv2

import mediapipe as mp


_face_detection = mp.solutions.face_detection.FaceDetection()

mphands = mp.solutions.hands
hands = mphands.Hands()


def load_model():
'''Loads the YOLO model for detection'''

model_path = Path(__file__).resolve().parent / 'Model/Model_Data/logs/runs/detect/SuicideDetection2/weights/best.pt'

model = YOLO(model_path)
return model


def detect(model, frame, frame_size):
'''Detects objects in the image'''

results = model.predict(
source=frame,
verbose=False,
imgsz=frame_size,
conf=0.6,
iou=0.7,
save=False,
save_txt=False,
show_conf=False,
show_labels=False,
show_boxes=True,
stream=True
)

return results


def face_detection(frame, w, h):
'''Detection for face detection'''

global _face_detection

box_list = []

face_results = _face_detection.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
if face_results.detections:
for detection in face_results.detections:
face_data = detection.location_data
box_data = face_data.relative_bounding_box
x = round(box_data.xmin * w)
y = round(box_data.ymin * h)
wi = round(box_data.width * w)
he = round(box_data.height * h)

box_list.append((x, y, wi, he))

cv2.rectangle(frame, (x, y), (x + wi, y + he), (0, 255, 0), 2)

return box_list


def hand_detection(frame, w, h):
'''Detection for hand detection'''

global hands

box_list = []

hands_results = hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
hand_landmarks = hands_results.multi_hand_landmarks

if hand_landmarks:
for handLMs in hand_landmarks:
if handLMs:
x1 = round(min([val.x for val in handLMs.landmark]) * w)
y1 = round(min([val.y for val in handLMs.landmark]) * h)
x2 = round(max([val.x for val in handLMs.landmark]) * w)
y2 = round(max([val.y for val in handLMs.landmark]) * h)

box_list.append((x1, y1, x2, y2))

cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 255), 2)

return box_list


def rope_detection(frame, frame_size):
'''Processed output for the detection'''

model = load_model()
results = detect(model, frame, frame_size)

box_list = []

for r in results:
annotator = Annotator(frame)

boxes = r.boxes

for box in boxes:
b = box.xyxy[0]
annotator.box_label(b)

box_list.append(boxes.xyxy.tolist())

annotator.result()

return box_list


def suicide_prevention(rope_box, face_box, hands_box):
'''Return a string specifying the detected condition of threat'''

txt = 'None'

# Condition 1: Warning
if rope_box and face_box:
for boxes in rope_box:
for box in boxes:
x1, y1, x2, y2 = box

for face in face_box:
fy, fh = face[1], face[3]
if y2 < fy:
txt = 'Warning: Face detected below rope area'

# Condition 2: Danger
if hands_box:
for hand in hands_box:
hx1, hy1, hx2, hy2 = hand

if y1 < hy1 < y2:
return 'Danger: Face below rope area and hand near rope area detected'

return txt
# Condition 3: Critical Danger
elif y1 < fy + fh:
return 'Critical Danger: Face detected near rope area'

return txt
Loading

0 comments on commit fbbb641

Please sign in to comment.