diff --git a/README.md b/README.md new file mode 100644 index 0000000..f9ed7ce --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ + +Live Face Detection using Opencv with Django or Tornado Framework +====================================== + +It'll capture image from your webcam and detect your face. It's also supported real time face detect from webcam video. + +Installation +============= + + * Please make sure you already installed Python3 and pip in your system, then Clone this repository :: + + git clone https://github.com/talhaanwarch/facedetect.git + + * Now install requirements of python libraries :: + + pip install -r requirements.txt + + * Now we need to run tornado server for create websocket :: + + python websocket.py + #It may be show popup for allow or not firewall , So click on allow to run websocket + + * Now run Django project using below command :: + + python manage.py runserver + + * Now you can access project :: + + http://127.0.0.1:8000/image/ # detect face from image + + http://127.0.0.1:8000/video/ # detect face from live webcam + + * **Note** + If you are on a windows machine, you can open two terminal one for websocket and the other for django server. + On linux server you may move tornado server to background and then lanuch django server. + + diff --git a/README.rst b/README.rst deleted file mode 100644 index 1e6c50d..0000000 --- a/README.rst +++ /dev/null @@ -1,34 +0,0 @@ -====================================== -Live Face Detection using Opencv with Django or Tornado Framework -====================================== - -It'll capture image from your webcam and detect your face. It's also supported real time face detect from webcam video. - -Installation -============= - - * Please make sure you already installed Python and pip in your system, then Clone this repository :: - - git clone https://github.com/sainipray/facedetect.git - - * Now install requirements of python libraries :: - - pip install -r requirements.txt - - * Now we need to run tornado server for create websocket :: - - python websocket.py #It may be show popup for allow or not firewall , So click on allow to run websocket - - * Now run Django project using below command :: - - python manage.py runserver - - * Now you can access project :: - - http://127.0.0.1:8000/face-detect/image/ # for detect face from image - - http://127.0.0.1:8000/face-detect/video/ # for detect face from live webcam - - - - diff --git a/liveface/urls.py b/liveface/urls.py deleted file mode 100644 index 56d12e3..0000000 --- a/liveface/urls.py +++ /dev/null @@ -1,22 +0,0 @@ -"""liveface URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.11/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf.urls import url, include -from django.contrib import admin - -urlpatterns = [ - url(r'^', include('main.urls', namespace='face-detect')), - url(r'^admin/', admin.site.urls), -] diff --git a/main/admin.py b/main/admin.py deleted file mode 100644 index 13be29d..0000000 --- a/main/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib import admin - -# Register your models here. diff --git a/main/apps.py b/main/apps.py deleted file mode 100644 index 3a2f9cd..0000000 --- a/main/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.apps import AppConfig - - -class MainConfig(AppConfig): - name = 'main' diff --git a/main/detect.py b/main/detect.py deleted file mode 100644 index cc9e39c..0000000 --- a/main/detect.py +++ /dev/null @@ -1,49 +0,0 @@ -import base64 -from io import BytesIO - -import cv2 -import dlib -import imutils -import numpy as np -from PIL import Image -from imutils import face_utils - -# FILE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -# SHAPE_PREDICTOR_FILE = os.path.join(FILE_DIR, 'files/shape_predictor_68_face_landmarks.dat') -# predictor = dlib.shape_predictor(SHAPE_PREDICTOR_FILE) - -detector = dlib.get_frontal_face_detector() - - -def base64_decode(data): - format, imgstr = data.split(';base64,') - return imgstr.decode('base64') - - -def base64_encode(data): - if data: - return 'data:image/png;base64,' + data - - -def get_face_detect_data(data): - nparr = np.fromstring(base64_decode(data), np.uint8) - img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) - image_data = detectImage(img) - return base64_encode(image_data) - - -def detectImage(image): - image = imutils.resize(image, width=500) - rects = detector(image, 1) - for (i, rect) in enumerate(rects): - (x, y, w, h) = face_utils.rect_to_bb(rect) - cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) - cv2.putText(image, "Face".format(i + 1), (x - 10, y - 10), - cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) - if rects: - output = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) - buffer = BytesIO() - img = Image.fromarray(output) - img.save(buffer, format="png") - encoded_string = base64.b64encode(buffer.getvalue()) - return encoded_string diff --git a/main/models.py b/main/models.py deleted file mode 100644 index 1dfab76..0000000 --- a/main/models.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models - -# Create your models here. diff --git a/main/urls.py b/main/urls.py deleted file mode 100644 index 36e6869..0000000 --- a/main/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.conf.urls import url - -from main.views import ImageFaceDetect, LiveVideoFaceDetect - -urlpatterns = [ - url(r'^face-detect/image/$', ImageFaceDetect.as_view(), name='image'), - url(r'^face-detect/video/$', LiveVideoFaceDetect.as_view(), name='live_video'), -] diff --git a/liveface/__init__.py b/main_app/__init__.py similarity index 100% rename from liveface/__init__.py rename to main_app/__init__.py diff --git a/main_app/asgi.py b/main_app/asgi.py new file mode 100644 index 0000000..247837b --- /dev/null +++ b/main_app/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for main_app project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'main_app.settings') + +application = get_asgi_application() diff --git a/liveface/settings.py b/main_app/settings.py similarity index 66% rename from liveface/settings.py rename to main_app/settings.py index 8b9039c..cd80122 100644 --- a/liveface/settings.py +++ b/main_app/settings.py @@ -1,26 +1,26 @@ """ -Django settings for liveface project. +Django settings for main_app project. -Generated by 'django-admin startproject' using Django 1.11.10. +Generated by 'django-admin startproject' using Django 3.1.7. For more information on this file, see -https://docs.djangoproject.com/en/1.11/topics/settings/ +https://docs.djangoproject.com/en/3.1/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.11/ref/settings/ +https://docs.djangoproject.com/en/3.1/ref/settings/ """ +from pathlib import Path import os - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '=70wzndlj)cfz#hs26s@%%_b_*i3(n5__&y5@#v#x7#1l&9&9%' +SECRET_KEY = '#do=m1@^a!br78ql!^$**3k=h@y7j-+5$&f#zo(4!o(yzd+nmt' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -37,7 +37,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'main.apps.MainConfig', + 'sub_app' ] MIDDLEWARE = [ @@ -50,12 +50,12 @@ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] -ROOT_URLCONF = 'liveface.urls' +ROOT_URLCONF = 'main_app.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR,'templates')], + 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -68,16 +68,22 @@ }, ] -WSGI_APPLICATION = 'liveface.wsgi.application' +WSGI_APPLICATION = 'main_app.wsgi.application' # Database -# https://docs.djangoproject.com/en/1.11/ref/settings/#databases +# https://docs.djangoproject.com/en/3.1/ref/settings/#databases +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} # Password validation -# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -96,7 +102,7 @@ # Internationalization -# https://docs.djangoproject.com/en/1.11/topics/i18n/ +# https://docs.djangoproject.com/en/3.1/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -110,12 +116,10 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.11/howto/static-files/ +# https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'sub_app','static') + +MEDIA_ROOT = os.path.join(BASE_DIR, 'sub_app','media') MEDIA_URL = '/media/' -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') -TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'templates'),) -STATICFILES_DIRS = [ - os.path.join(BASE_DIR, 'static') -] diff --git a/main_app/urls.py b/main_app/urls.py new file mode 100644 index 0000000..39dc8e0 --- /dev/null +++ b/main_app/urls.py @@ -0,0 +1,27 @@ +"""main_app URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path,include,re_path +from sub_app import views +from django.conf import settings +from django.conf.urls.static import static +from django.views.static import serve + +urlpatterns = [ + path('admin/', admin.site.urls), + path('',include('sub_app.urls')), + re_path(r'^media/(?P.*)$', serve, kwargs={'document_root': settings.MEDIA_ROOT}) +] \ No newline at end of file diff --git a/liveface/wsgi.py b/main_app/wsgi.py similarity index 58% rename from liveface/wsgi.py rename to main_app/wsgi.py index c4e5f45..69a2ff6 100644 --- a/liveface/wsgi.py +++ b/main_app/wsgi.py @@ -1,16 +1,16 @@ """ -WSGI config for liveface project. +WSGI config for main_app project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "liveface.settings") +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'main_app.settings') application = get_wsgi_application() diff --git a/manage.py b/manage.py index b811f7e..fee3561 100755 --- a/manage.py +++ b/manage.py @@ -1,22 +1,22 @@ #!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" import os import sys -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "liveface.settings") + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'main_app.settings') try: from django.core.management import execute_from_command_line - except ImportError: - # The above import may fail for some other reason. Ensure that the - # issue is really that Django is missing to avoid masking other - # exceptions on Python 2. - try: - import django - except ImportError: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) - raise + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc execute_from_command_line(sys.argv) + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt index 0ef3a60..d3fa0fc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,9 @@ -cmake==0.9.0 -Django==1.11.8 -dlib==19.9.0 -imutils==0.4.5 -numpy==1.13.3 -opencv-python==3.4.0.12 -Pillow==4.0.0 -pytz==2017.3 -six==1.10.0 -tornado==4.2 +asgiref==3.3.1 +cmake==3.18.4.post1 +Django==3.1.7 +numpy==1.20.1 +opencv-python-headless==4.5.1.48 +Pillow==8.1.2 +pytz==2021.1 +sqlparse==0.4.1 +tornado==6.1 diff --git a/main/__init__.py b/sub_app/__init__.py similarity index 100% rename from main/__init__.py rename to sub_app/__init__.py diff --git a/sub_app/admin.py b/sub_app/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/sub_app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/sub_app/apps.py b/sub_app/apps.py new file mode 100644 index 0000000..fd98491 --- /dev/null +++ b/sub_app/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class SubAppConfig(AppConfig): + name = 'sub_app' diff --git a/sub_app/migrations/__init__.py b/sub_app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sub_app/models.py b/sub_app/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/sub_app/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/sub_app/py_files/detect.py b/sub_app/py_files/detect.py new file mode 100644 index 0000000..1678003 --- /dev/null +++ b/sub_app/py_files/detect.py @@ -0,0 +1,54 @@ +import base64 +from io import BytesIO + +import cv2 + +import numpy as np +from PIL import Image + +# FILE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# SHAPE_PREDICTOR_FILE = os.path.join(FILE_DIR, 'files/shape_predictor_68_face_landmarks.dat') +# predictor = dlib.shape_predictor(SHAPE_PREDICTOR_FILE) + + + +def base64_decode(data): + # with open('sample.png', 'wb') as f: + # f.write(base64.decodestring(data.split(',')[1].encode())) + out=base64.decodestring(data.split(',')[1].encode()) + return out + + + +def base64_encode(data): + if data: + return 'data:image/png;base64,' + data + + +def get_face_detect_data(data): + nparr = np.fromstring(base64_decode(data), np.uint8) + img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) + image_data = detectImage(img) + # print('image_data',image_data) + + return base64_encode(image_data) + + +def detectImage(image): + face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + faces = face_cascade.detectMultiScale(gray) + print('number of faces',len(faces)) + for (x, y, w, h) in faces: + cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2) + output = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) + # print(output.shape) + # im = Image.fromarray(output) + # im.save('test.png') + + + buffer = BytesIO() + img = Image.fromarray(output) + img.save(buffer, format="png") + encoded_string = base64.b64encode(buffer.getvalue()).decode('ascii') + return encoded_string \ No newline at end of file diff --git a/static/css/materialize.min.css b/sub_app/static/css/materialize.min.css similarity index 100% rename from static/css/materialize.min.css rename to sub_app/static/css/materialize.min.css diff --git a/static/fonts/roboto/Roboto-Bold.woff b/sub_app/static/fonts/roboto/Roboto-Bold.woff similarity index 100% rename from static/fonts/roboto/Roboto-Bold.woff rename to sub_app/static/fonts/roboto/Roboto-Bold.woff diff --git a/static/fonts/roboto/Roboto-Bold.woff2 b/sub_app/static/fonts/roboto/Roboto-Bold.woff2 similarity index 100% rename from static/fonts/roboto/Roboto-Bold.woff2 rename to sub_app/static/fonts/roboto/Roboto-Bold.woff2 diff --git a/static/fonts/roboto/Roboto-Light.woff b/sub_app/static/fonts/roboto/Roboto-Light.woff similarity index 100% rename from static/fonts/roboto/Roboto-Light.woff rename to sub_app/static/fonts/roboto/Roboto-Light.woff diff --git a/static/fonts/roboto/Roboto-Light.woff2 b/sub_app/static/fonts/roboto/Roboto-Light.woff2 similarity index 100% rename from static/fonts/roboto/Roboto-Light.woff2 rename to sub_app/static/fonts/roboto/Roboto-Light.woff2 diff --git a/static/fonts/roboto/Roboto-Medium.woff b/sub_app/static/fonts/roboto/Roboto-Medium.woff similarity index 100% rename from static/fonts/roboto/Roboto-Medium.woff rename to sub_app/static/fonts/roboto/Roboto-Medium.woff diff --git a/static/fonts/roboto/Roboto-Medium.woff2 b/sub_app/static/fonts/roboto/Roboto-Medium.woff2 similarity index 100% rename from static/fonts/roboto/Roboto-Medium.woff2 rename to sub_app/static/fonts/roboto/Roboto-Medium.woff2 diff --git a/static/fonts/roboto/Roboto-Regular.woff b/sub_app/static/fonts/roboto/Roboto-Regular.woff similarity index 100% rename from static/fonts/roboto/Roboto-Regular.woff rename to sub_app/static/fonts/roboto/Roboto-Regular.woff diff --git a/static/fonts/roboto/Roboto-Regular.woff2 b/sub_app/static/fonts/roboto/Roboto-Regular.woff2 similarity index 100% rename from static/fonts/roboto/Roboto-Regular.woff2 rename to sub_app/static/fonts/roboto/Roboto-Regular.woff2 diff --git a/static/fonts/roboto/Roboto-Thin.woff b/sub_app/static/fonts/roboto/Roboto-Thin.woff similarity index 100% rename from static/fonts/roboto/Roboto-Thin.woff rename to sub_app/static/fonts/roboto/Roboto-Thin.woff diff --git a/static/fonts/roboto/Roboto-Thin.woff2 b/sub_app/static/fonts/roboto/Roboto-Thin.woff2 similarity index 100% rename from static/fonts/roboto/Roboto-Thin.woff2 rename to sub_app/static/fonts/roboto/Roboto-Thin.woff2 diff --git a/static/js/formsubmit.js b/sub_app/static/js/formsubmit.js similarity index 100% rename from static/js/formsubmit.js rename to sub_app/static/js/formsubmit.js diff --git a/static/js/jquery.min.js b/sub_app/static/js/jquery.min.js similarity index 100% rename from static/js/jquery.min.js rename to sub_app/static/js/jquery.min.js diff --git a/static/js/materialize.min.js b/sub_app/static/js/materialize.min.js similarity index 100% rename from static/js/materialize.min.js rename to sub_app/static/js/materialize.min.js diff --git a/templates/base.html b/sub_app/templates/base.html similarity index 96% rename from templates/base.html rename to sub_app/templates/base.html index d97c873..38eae82 100644 --- a/templates/base.html +++ b/sub_app/templates/base.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} diff --git a/templates/image.html b/sub_app/templates/image.html similarity index 89% rename from templates/image.html rename to sub_app/templates/image.html index b6195ea..2c00897 100644 --- a/templates/image.html +++ b/sub_app/templates/image.html @@ -2,15 +2,15 @@ {% block content %}
+ action="{% url 'image' %}"> {% csrf_token %}

Live Video

diff --git a/templates/video.html b/sub_app/templates/video.html similarity index 87% rename from templates/video.html rename to sub_app/templates/video.html index 9dde36b..ccefbba 100644 --- a/templates/video.html +++ b/sub_app/templates/video.html @@ -2,8 +2,8 @@ {% block content %}
@@ -21,7 +21,8 @@

Live Video

{% endblock %} {% block js %}