Commit e1013a69 authored by LiniEisha's avatar LiniEisha

Merge branch 'QA_RELEASE' into summarization_changes

# Conflicts:
#	LectureSummarizingApp/urls.py
#	integrated_slpes/urls.py
parents 02e000a2 efa7d37c
......@@ -16,6 +16,7 @@
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="canvasjs" level="application" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{canvasjs}" />
</component>
</project>
\ No newline at end of file
......@@ -128,7 +128,7 @@ class LectureActivity(models.Model):
# Lecture emotion report
class LectureEmotionReport(models.Model):
lecture_emotion_id = models.CharField(max_length=10)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE, default=0)
happy_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
sad_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
angry_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
......
# Generated by Django 3.0.3 on 2020-03-04 11:15
# Generated by Django 2.2.11 on 2020-09-07 07:56
import FirstApp.MongoModels
from django.db import migrations, models
import django.db.models.deletion
import djongo.models.fields
class Migration(migrations.Migration):
......@@ -11,6 +14,44 @@ class Migration(migrations.Migration):
]
operations = [
migrations.CreateModel(
name='Faculty',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('faculty_id', models.CharField(max_length=10)),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Lecture',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_created=True, default=None)),
('lecture_id', models.CharField(max_length=10)),
],
),
migrations.CreateModel(
name='Lecturer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_id', models.CharField(max_length=7)),
('fname', models.TextField()),
('lname', models.TextField()),
('email', models.EmailField(max_length=254)),
('telephone', models.CharField(max_length=10)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='RegisterUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firstName', models.CharField(max_length=20)),
('lastName', models.CharField(max_length=30)),
('email', models.CharField(max_length=30)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Teachers',
fields=[
......@@ -20,4 +61,116 @@ class Migration(migrations.Migration):
('age', models.IntegerField()),
],
),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('path', models.CharField(max_length=100)),
('duration', models.CharField(max_length=100)),
('hours', models.IntegerField()),
('minutes', models.IntegerField()),
('seconds', models.IntegerField()),
],
),
migrations.CreateModel(
name='VideoMeta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()),
('frame_count', models.IntegerField()),
('happy_count', models.IntegerField()),
('sad_count', models.IntegerField()),
('angry_count', models.IntegerField()),
('neutral_count', models.IntegerField()),
('surprise_count', models.IntegerField()),
('happy_perct', models.IntegerField()),
('sad_perct', models.IntegerField()),
('angry_perct', models.IntegerField()),
('neutral_perct', models.IntegerField()),
('surprise_perct', models.IntegerField()),
],
),
migrations.CreateModel(
name='Subject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject_code', models.TextField()),
('name', models.TextField()),
('year', models.IntegerField()),
('faculty', models.ForeignKey(default={}, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='LectureVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_video_id', models.CharField(max_length=10)),
('date', models.DateField()),
('video_name', models.CharField(max_length=50)),
('video_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerSubject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lec_subject_id', models.CharField(max_length=10)),
('lecturer_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subjects', models.ManyToManyField(to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerCredentials',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=15)),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
],
),
migrations.CreateModel(
name='LecturePoseEstimation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_pose_id', models.CharField(max_length=10)),
('lecture_video_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='LectureEmotionReport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_emotion_id', models.CharField(max_length=10)),
('happy_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('sad_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('angry_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('disgust_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('surprise_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('neutral_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('lecture_video_id', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='LectureActivity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_activity_id', models.CharField(max_length=10)),
('talking_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('listening_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('writing_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('phone_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('lecture_video_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='FacultyTimetable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timetable_id', models.CharField(max_length=10)),
('timetable', djongo.models.fields.ArrayField(model_container=FirstApp.MongoModels.DateTimeTable)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
]
# Generated by Django 2.2.11 on 2020-03-16 12:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='RegisterUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firstName', models.CharField(max_length=20)),
('lastName', models.CharField(max_length=30)),
('email', models.CharField(max_length=30)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('path', models.CharField(max_length=100)),
('duration', models.CharField(max_length=100)),
('hours', models.IntegerField()),
('minutes', models.IntegerField()),
('seconds', models.IntegerField()),
],
),
migrations.CreateModel(
name='VideoMeta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()),
('frame_count', models.IntegerField()),
('happy_count', models.IntegerField()),
('sad_count', models.IntegerField()),
('angry_count', models.IntegerField()),
('neutral_count', models.IntegerField()),
('surprise_count', models.IntegerField()),
('happy_perct', models.IntegerField()),
('sad_perct', models.IntegerField()),
('angry_perct', models.IntegerField()),
('neutral_perct', models.IntegerField()),
('surprise_perct', models.IntegerField()),
],
),
]
# Generated by Django 2.2.11 on 2020-05-10 15:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0002_registeruser_video_videometa'),
]
operations = [
migrations.CreateModel(
name='LectureEmotionReport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_id', models.CharField(max_length=10)),
('happy_perct', models.FloatField()),
('sad_perct', models.FloatField()),
('angry_perct', models.FloatField()),
('surprise_perct', models.FloatField()),
('disgust_perct', models.FloatField()),
('neutral_perct', models.FloatField()),
],
),
]
# Generated by Django 2.2.11 on 2020-05-11 16:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0003_lectureemotionreport'),
]
operations = [
migrations.CreateModel(
name='Lecture',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_created=True)),
('lecture_id', models.CharField(max_length=10)),
],
),
]
# Generated by Django 2.2.11 on 2020-05-13 10:21
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0004_lecture'),
]
operations = [
migrations.CreateModel(
name='Faculty',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('faculty_id', models.CharField(max_length=10)),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Lecturer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_id', models.CharField(max_length=7)),
('fname', models.TextField()),
('lname', models.TextField()),
('email', models.EmailField(max_length=254)),
('telephone', models.CharField(max_length=10)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.AlterField(
model_name='lecture',
name='date',
field=models.DateTimeField(auto_created=True, default=None),
),
migrations.CreateModel(
name='Subject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject_code', models.TextField()),
('name', models.TextField()),
('year', models.IntegerField()),
('faculty', models.ForeignKey(default={}, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.CreateModel(
name='LecturerSubject',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lec_subject_id', models.CharField(max_length=10)),
('lecturer_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subjects', models.ManyToManyField(to='FirstApp.Subject')),
],
),
]
# Generated by Django 2.2.11 on 2020-05-13 15:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0005_auto_20200513_1551'),
]
operations = [
migrations.CreateModel(
name='LecturerCredentials',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=15)),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
],
),
]
from django.contrib import admin
# Register your models here.
from LectureSummarizingApp.models import *
admin.site.register(LectureAudio)
admin.site.register(LectureAudioSummary)
from rest_framework.views import APIView
from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudio
from LectureSummarizingApp.serializer import LectureAudioSerializer
# this API will retrieve lecture audio details
class LectureAudioAPI(APIView):
def get(self, request):
lecture_audio = LectureAudio.objects.all()
lecture_audio_serializer = LectureAudioSerializer(lecture_audio, many=True)
data = lecture_audio_serializer.data
return Response({
"response": data
})
\ No newline at end of file
from django.apps import AppConfig
class LecturesummarizingappConfig(AppConfig):
class LectureSummarizingAppConfig(AppConfig):
name = 'LectureSummarizingApp'
# Generated by Django 2.2.11 on 2020-09-15 07:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('FirstApp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='LectureAudio',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_audio_id', models.CharField(max_length=10)),
('lecturer_date', models.DateField()),
('lecture_audio_name', models.CharField(max_length=50)),
('lecture_audio_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LectureAudioSummary',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_audio_summary_id', models.CharField(max_length=10)),
('audio_original_text', models.TextField()),
('audio_summary', models.TextField()),
('lecture_audio_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='LectureSummarizingApp.LectureAudio')),
],
),
]
from django.db import models
# from django.db import models
from djongo import models
# Create your models here.
from FirstApp.MongoModels import Lecturer, Subject
class LectureAudio (models.Model):
lecture_audio_id = models.CharField(max_length=10)
lecturer_date = models.DateField()
lecture_audio_name = models.CharField(max_length=50)
lecture_audio_length = models.DurationField()
lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.lecture_audio_id
class LectureAudioSummary (models.Model):
lecture_audio_summary_id = models.CharField(max_length=10)
lecture_audio_id = models.ForeignKey(LectureAudio, on_delete=models.CASCADE)
audio_original_text = models.TextField()
audio_summary = models.TextField()
def __str__(self):
return self.lecture_audio_summary_id
from rest_framework import serializers
from FirstApp.serializers import LecturerSerializer, SubjectSerializer
from . models import *
class LectureAudioSerializer(serializers.ModelSerializer):
lecturer = LecturerSerializer()
subject = SubjectSerializer()
class Meta:
model = LectureAudio
fields = '__all__'
class LectureAudioSummarySerializer(serializers.ModelSerializer):
lecture_audio_id = LectureAudioSerializer()
class Meta:
model = LectureAudioSummary
fields = '__all__'
\ No newline at end of file
from django.urls import path, re_path, include
from django.conf.urls import url
from rest_framework import routers
from . import views
# from . import api
from rest_framework import routers
from django.conf.urls import url
from . import api
router = routers.DefaultRouter()
# router.register(r'^register', views.RegisterViewSet)
# router.register(r'^createImage', views.ImageViewSet)
# router.register(r'^register', views.register)
urlpatterns = [
path('/summarization', views.summarization),
# path('', views.hello),
# path('login', views.login),
# path('register', views.register),
# path('404', views.view404),
# path('blank', views.blank),
# path('buttons', views.buttons),
# path('cards', views.cards),
# path('charts', views.charts),
# path('forgot-password', views.forget_password),
# # path('webcam', views.webcam),
# path('template', views.template),
# path('base', views.base),
# path('child', views.child),
# path('lecture-video', views.lecVideo),
# # path('Video', views.hello)
# API to retrieve activity recognition
url(r'^get-lecture-audio/$', api.LectureAudioAPI.as_view()),
# # API to retrieve audio analysis
# url(r'^get-audio-analysis', api.GetLectureAudioAnalysis.as_view()),
#
# # API to retrieve lecture audio text
# url(r'^get-lecture-audio-text', api.LectureAudioTextAPI.as_view()),
#
# # test API
# url(r'^test-api', api.TestAPI.as_view()),
# routers
# path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
from rest_framework.urlpatterns import format_suffix_patterns
from django.contrib import admin
from . models import RegisterTeacher
from .models import *
# Register your models here.
admin.site.register(RegisterTeacher)
\ No newline at end of file
admin.site.register(LecturerVideo)
admin.site.register(LecturerAudioText)
admin.site.register(LecturerVideoMetaData)
admin.site.register(LectureRecordedVideo)
\ No newline at end of file
from rest_framework.views import APIView
from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudioSummary
from LectureSummarizingApp.serializer import LectureAudioSummarySerializer
from . logic import classroom_activity, text_analysis as ta
from .models import LecturerVideo, LecturerAudioText
from .serializers import LecturerVideoSerializer, LecturerAudioTextSerializer
import datetime
class ActivityRecognitionAPI(APIView):
......@@ -14,12 +21,139 @@ class ActivityRecognitionAPI(APIView):
pass
# class ActivityRecognitionAPI(APIView):
#
# def get(self, request):
# video_name = request.query_params.get('video_name')
# percentages = classroom_activity.activity_recognition(video_name)
# return Response({"response": percentages})
#
# def post(self, request):
# pass
# this class will be used to retrieve audio analysis for a lecture
class GetLectureAudioAnalysis(APIView):
def get(self, request):
analysis = ta.run()
lec_audio_id = request.query_params.get("audio_id")
int_audio_id = int(lec_audio_id)
lec_audio_summary = LectureAudioSummary.objects.filter(lecture_audio_id=int_audio_id)
lec_audio_summary_serializer = LectureAudioSummarySerializer(lec_audio_summary, many=True)
audio_summary_data = lec_audio_summary_serializer.data
lec_audio_summary_id = 0
for audio in audio_summary_data:
lec_audio_summary_id = audio['id']
# retrieve summary text data
lec_audio_text = LecturerAudioText.objects.filter(lecturer_audio_original_text__id=lec_audio_summary_id)
lec_audio_text_serializer = LecturerAudioTextSerializer(lec_audio_text, many=True)
lec_audio_text_data = lec_audio_text_serializer.data
audio_text = []
if len(lec_audio_text_data) > 0:
audio_text = lec_audio_text_data[0]
print('audio text: ', audio_text)
return Response({
"response":audio_text
})
# test api
class TestAPI(APIView):
# retrieve all the details
def get(self, request):
lecturer_videos = LecturerVideo.objects.all()
lecturer_vidoe_serializer = LecturerVideoSerializer(lecturer_videos, many=True)
data = lecturer_vidoe_serializer.data
return Response({
"response": data
})
def post(self, request):
name = request.data['name']
path = request.data['path']
duration = request.data['duration']
hours = request.data['hours']
minutes = request.data['minutes']
seconds = request.data['seconds']
# create the LecturerVideo details
LecturerVideo(
id=2,
name=name,
path=path,
duration=duration,
hours=hours,
minutes=minutes,
seconds=seconds
).save()
return Response({
"response": "Success"
})
# this API will retrieve lecture audio text details
class LectureAudioTextAPI(APIView):
def get(self, request):
lecture_audio_text = LecturerAudioText.objects.all()
lecture_audio_text_serializer = LecturerAudioTextSerializer(lecture_audio_text, many=True)
data = lecture_audio_text_serializer.data
return Response({
"response": data
})
# this API will retrieve lectuer audio summary for given period
class LecturerAudioSummaryPeriodAPI(APIView):
def get(self, request):
print('hello')
option = request.query_params.get('option')
int_option = int(option)
# i cheated here (remove this once you have many recent records) - ok
int_option = 150
isRecordFound = False
lec_audio_text_stats = []
labels = []
current_date = datetime.datetime.now().date()
option_date = datetime.timedelta(days=int_option)
previous_date = current_date - option_date
lec_audio_text = LecturerAudioText.objects.filter(
lecturer_audio_original_text__lecture_audio_id__lecturer_date__gte=previous_date,
lecturer_audio_original_text__lecture_audio_id__lecturer_date__lte=current_date
)
# if there are records
if len(lec_audio_text) > 0:
isRecordFound = True
lec_audio_text_ser = LecturerAudioTextSerializer(lec_audio_text, many=True)
lec_audio_text_data = lec_audio_text_ser.data
lec_audio_text_stats, labels = ta.get_lecturer_audio_summary_for_period(lec_audio_text_data)
return Response({
"response":analysis
"statistics": lec_audio_text_stats,
"labels": labels,
"isRecordFound": isRecordFound
})
......@@ -8,11 +8,18 @@ import os
def activity_recognition(video_name):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
CLASSIFIER_DIR = os.path.join(BASE_DIR, "MonitorLecturerApp\\models")
VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\lecturer_videos\\{}".format(video_name))
# VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\lecturer_videos\\{}".format(video_name)) -> Uncomment after integration
VIDEO_PATH = os.path.join(BASE_DIR, "static\\FirstApp\\lecturer_videos\\{}".format(video_name))
print('video name: ', video_name)
detector_path = os.path.join(CLASSIFIER_DIR, "keras_model.h5")
# detector_path = os.path.join(CLASSIFIER_DIR, "keras_model.h5")
detector_path = os.path.join(CLASSIFIER_DIR, "keras_model_updated.h5")
# Disable scientific notation for clarity
np.set_printoptions(suppress=True)
......@@ -50,9 +57,9 @@ def activity_recognition(video_name):
# getting the number of frames using CAP_PROP_FRAME_COUNT method
no_of_frames = video.get(cv2.CAP_PROP_FRAME_COUNT)
frame_count = 0
seated_count = 0
standing_count = 0
walking_count = 0
seated_count = 0.0
standing_count = 0.0
walking_count = 0.0
# while loop is conditioned like this to avoid the termination of the loop with an exception
while (frame_count < no_of_frames):
......@@ -88,13 +95,15 @@ def activity_recognition(video_name):
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
cv2.destroyAllWindows()
print("No of frames: ", frame_count)
print("No of frames in seated_count: ", seated_count)
print("No of frames in standing_count: ", standing_count)
print("No of frames in walking_count: ", walking_count)
# calculating the percentages
sit_perct = (seated_count / no_of_frames) * 100
stand_perct = (standing_count / no_of_frames) * 100
walk_perct = (walking_count / no_of_frames) * 100
......
......@@ -46,7 +46,7 @@ def run():
else:
d[word] = 1
# the key words are "extraneous filler words(ok, well, like, Actually, Basically, that, jest, only, really, very, now, simply, maybe, perhaps, somehow, almost, slightly, seemed ....)"
# the key words are "extraneous filler words (ok, well, like, Actually, Basically, that, jest, only, really, very, now, simply, maybe, perhaps, somehow, almost, slightly, seemed ....)"
for key in list(d.keys()):
if (key == "like"):
......@@ -170,3 +170,46 @@ def run():
analysis['non_lexical_count'] = non_lexical_count
return analysis
# this method will return the lecturer audio summary for period
def get_lecturer_audio_summary_for_period(lecture_audio_text_data):
# declare variables to add percentage values
word_count = 0
lexical_count_combined = 0
non_lexical_count_combined = 0
# get the number of activties to calculate average
no_of_data = len(lecture_audio_text_data)
individual_lec_data = []
labels = ["lexical_wordcount", "non_lexical_wordcount", "wordcount"]
# iterate through the activities
for audio_data in lecture_audio_text_data:
ind_word_count = int(audio_data["lecturer_audio_text_lexical_wordcount"])
ind_lexical_count = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
ind_non_lexical_count = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
individual_lecture = {}
individual_lecture["lexical_wordcount"] = int(audio_data["lecturer_audio_text_lexical_wordcount"])
individual_lecture["non_lexical_wordcount"] = int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
individual_lecture["wordcount"] = int(audio_data["lecturer_audio_text_wordcount"])
lexical_count_combined += int(audio_data["lecturer_audio_text_lexical_wordcount"])
non_lexical_count_combined += int(audio_data["lecturer_audio_text_non_lexical_wordcount"])
word_count += int(audio_data["lecturer_audio_text_wordcount"])
# calculate the percentages
# individual_lecture["lexical_perct"] = round((ind_lexical_count / ind_word_count), 1)
# individual_lecture["non_lexical_perct"] = round((ind_non_lexical_count / ind_word_count), 1)
# append to the list
individual_lec_data.append(individual_lecture)
return individual_lec_data, labels
\ No newline at end of file
# Generated by Django 3.0.4 on 2020-04-01 15:45
# Generated by Django 2.2.11 on 2020-09-15 07:59
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
......@@ -8,22 +9,13 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('FirstApp', '0001_initial'),
('LectureSummarizingApp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='RegisterTeacher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fName', models.CharField(max_length=15)),
('lName', models.CharField(max_length=15)),
('subject', models.CharField(max_length=50)),
('email', models.CharField(max_length=50)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='tVideo',
name='LecturerVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
......@@ -35,7 +27,7 @@ class Migration(migrations.Migration):
],
),
migrations.CreateModel(
name='tVideoMetaData',
name='LecturerVideoMetaData',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fps', models.IntegerField()),
......@@ -45,4 +37,38 @@ class Migration(migrations.Migration):
('walking_count', models.IntegerField()),
],
),
migrations.CreateModel(
name='RegisterTeacher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fName', models.CharField(max_length=15)),
('lName', models.CharField(max_length=15)),
('subject', models.CharField(max_length=50)),
('email', models.CharField(max_length=50)),
('password', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='LectureRecordedVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_video_id', models.CharField(max_length=10)),
('lecturer_date', models.DateField()),
('lecture_video_name', models.CharField(max_length=50)),
('lecture_video_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LecturerAudioText',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecturer_audio_text_id', models.CharField(max_length=10)),
('lecturer_audio_text_wordcount', models.IntegerField()),
('lecturer_audio_text_lexical_wordcount', models.IntegerField()),
('lecturer_audio_text_non_lexical_wordcount', models.IntegerField()),
('lecturer_audio_original_text', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='LectureSummarizingApp.LectureAudioSummary')),
],
),
]
# Generated by Django 2.2.11 on 2020-09-15 09:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('MonitorLecturerApp', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='lectureraudiotext',
name='lecturer_audio_text_status',
field=models.CharField(choices=[(1, 'Below'), (2, 'Average'), (3, 'Excellent')], default='Average', max_length=15),
),
]
# Generated by Django 2.2.11 on 2020-09-15 09:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('MonitorLecturerApp', '0002_lectureraudiotext_lecturer_audio_text_status'),
]
operations = [
migrations.AlterField(
model_name='lectureraudiotext',
name='lecturer_audio_text_status',
field=models.CharField(choices=[('Below', 'Below'), ('Average', 'Average'), ('Excellent', 'Excellent')], default='Average', max_length=15),
),
]
......@@ -2,6 +2,9 @@ from django.db import models
from djongo import models
# Create your models here.
from FirstApp.MongoModels import Subject, Lecturer
from LectureSummarizingApp.models import LectureAudioSummary
class RegisterTeacher(models.Model):
fName = models.CharField(max_length = 15)
......@@ -14,7 +17,7 @@ class RegisterTeacher(models.Model):
return self.fName
class tVideo(models.Model):
class LecturerVideo(models.Model):
name = models.CharField(max_length=100)
path = models.CharField(max_length=100)
duration = models.CharField(max_length=100)
......@@ -26,7 +29,7 @@ class tVideo(models.Model):
return self.name
class tVideoMetaData(models.Model):
class LecturerVideoMetaData(models.Model):
fps = models.IntegerField()
frame_count = models.IntegerField()
seated_count = models.IntegerField()
......@@ -51,18 +54,32 @@ class tVideoMetaData(models.Model):
self.calWalkPercent()
class lectureAudio (models.Model):
lecture_audio_id = models.CharField(max_length=10)
lecturer_date = models.DateField()
lecture_audio_name = models.CharField(max_length=50)
lecture_audio_length = models.DurationField()
# lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
# subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
class LecturerAudioText (models.Model):
lecturer_audio_text_id = models.CharField(max_length=10)
lecturer_audio_text_wordcount = models.IntegerField()
lecturer_audio_text_lexical_wordcount = models.IntegerField()
lecturer_audio_text_non_lexical_wordcount = models.IntegerField()
lecturer_audio_text_status = models.CharField(
max_length=15,
choices=(
("Below", "Below"),
("Average", "Average"),
("Excellent", "Excellent")
),
default="Average"
)
lecturer_audio_original_text = models.ForeignKey(LectureAudioSummary, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.lecturer_audio_text_id
class lectureRecordedVideo (models.Model):
class LectureRecordedVideo (models.Model):
lecture_video_id = models.CharField(max_length=10)
lecturer_date = models.DateField()
lecture_video_name = models.CharField(max_length=50)
lecture_video_length = models.DurationField()
# lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
# subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
\ No newline at end of file
lecturer = models.ForeignKey(Lecturer, on_delete=models.CASCADE, default=0)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.lecture_video_id
\ No newline at end of file
from rest_framework import serializers
from .models import RegisterTeacher, tVideoMetaData
class RegisterTeacherSerializer(serializers.ModelSerializer):
from FirstApp.serializers import LecturerSerializer, SubjectSerializer
from LectureSummarizingApp.models import LectureAudioSummary
from .models import RegisterTeacher
from .models import LecturerAudioText, LecturerVideoMetaData, LecturerVideo, LectureRecordedVideo
class RegisterTeacherSerializer(serializers.ModelSerializer):
class Meta:
model = RegisterTeacher
fields = {'fName', 'lName', 'subject', 'email', 'password'}
class LecturerVideoSerializer(serializers.ModelSerializer):
class Meta:
model = LecturerVideo
fields = '__all__'
class LecturerVideoMetaDataSerializer(serializers.ModelSerializer):
class Meta:
model = LecturerVideoMetaData
fields = '__all__'
class LecturerAudioTextSerializer(serializers.ModelSerializer):
lecturer_audio_original_text = LectureAudioSummary()
class Meta:
model = LecturerAudioText
fields = '__all__'
class LectureRecordedVideoSerializer(serializers.ModelSerializer):
lecturer = LecturerSerializer()
subject = SubjectSerializer()
class Meta:
model = LectureRecordedVideo
fields = '__all__'
<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title:{
text: "Daily High Temperature at Different Beaches"
},
axisX: {
valueFormatString: "DD MMM,YY"
},
axisY: {
title: "Temperature (in °C)",
suffix: " °C"
},
legend:{
cursor: "pointer",
fontSize: 16,
itemclick: toggleDataSeries
},
toolTip:{
shared: true
},
data: [{
name: "Myrtle Beach",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 31 },
{ x: new Date(2017,6,25), y: 31 },
{ x: new Date(2017,6,26), y: 29 },
{ x: new Date(2017,6,27), y: 29 },
{ x: new Date(2017,6,28), y: 31 },
{ x: new Date(2017,6,29), y: 30 },
{ x: new Date(2017,6,30), y: 29 }
]
},
{
name: "Martha Vineyard",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 20 },
{ x: new Date(2017,6,25), y: 20 },
{ x: new Date(2017,6,26), y: 25 },
{ x: new Date(2017,6,27), y: 25 },
{ x: new Date(2017,6,28), y: 25 },
{ x: new Date(2017,6,29), y: 25 },
{ x: new Date(2017,6,30), y: 25 }
]
},
{
name: "Nantucket",
type: "spline",
yValueFormatString: "#0.## °C",
showInLegend: true,
dataPoints: [
{ x: new Date(2017,6,24), y: 22 },
{ x: new Date(2017,6,25), y: 19 },
{ x: new Date(2017,6,26), y: 23 },
{ x: new Date(2017,6,27), y: 24 },
{ x: new Date(2017,6,28), y: 24 },
{ x: new Date(2017,6,29), y: 23 },
{ x: new Date(2017,6,30), y: 23 }
]
}]
});
chart.render();
function toggleDataSeries(e){
if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
}
else{
e.dataSeries.visible = true;
}
chart.render();
}
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 300px; max-width: 1400px; margin: 0px auto;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
\ No newline at end of file
......@@ -142,7 +142,7 @@
</div>
<!-- Card Body -->
<div class="card-body">
<div class="card-body" style="overflow-y: scroll">
<div class="chart-pie pt-4 pb-2">
<table class="table table-striped">
<thead>
......
......@@ -28,7 +28,16 @@ urlpatterns = [
url(r'^activities/$', api.ActivityRecognitionAPI.as_view()),
# API to retrieve audio analysis
url(r'^get-audio-analysis', api.GetLectureAudioAnalysis.as_view()),
url(r'^get-audio-analysis/$', api.GetLectureAudioAnalysis.as_view()),
# API to retrieve lecture audio text
url(r'^get-lecture-audio-text', api.LectureAudioTextAPI.as_view()),
# API to retrieve lecture audio text
url(r'^get-lecturer-audio-summary-for-period', api.LecturerAudioSummaryPeriodAPI.as_view()),
# test API
url(r'^test-api', api.TestAPI.as_view()),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
......
......@@ -4,13 +4,17 @@ from django.conf.urls import url
from rest_framework import routers
from rest_framework.views import APIView
from rest_framework.response import Response
from LectureSummarizingApp.models import LectureAudio
from LectureSummarizingApp.serializer import LectureAudioSerializer
from . import views
from . models import RegisterTeacher, tVideo
from .models import RegisterTeacher, LecturerVideo
from . serializers import RegisterTeacherSerializer
import cv2
import os
import datetime
from datetime import datetime as dt
......@@ -45,8 +49,29 @@ def hello(request):
videos = []
durations = []
# retrieve audio details from db
lecture_audio = LectureAudio.objects.all()
lec_audio_serializer = LectureAudioSerializer(lecture_audio, many=True)
lec_audio_data = lec_audio_serializer.data
lec_list = []
for audio in lec_audio_data:
lec_audio_object = {}
lec_audio_object["id"] = audio["id"]
lec_audio_object["date"] = audio["lecturer_date"]
lec_audio_object["subject"] = audio["subject"]["name"]
lec_audio_object["lecturer"] = audio["lecturer"]["fname"] + " " + audio["lecturer"]["lname"]
lec_audio_object["lecturer_id"] = audio["lecturer"]["id"]
# append to the list
lec_list.append(lec_audio_object)
# the list needs to be sorted by the date
lec_list.sort(key=lambda date: dt.strptime(str(date['date']), "%Y-%m-%d"), reverse=True)
for videoPath in videoPaths:
video = tVideo()
video = LecturerVideo()
cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
......@@ -60,7 +85,7 @@ def hello(request):
video.duration = str(durationObj)
videos.append(video)
print('Video Name: ', video.name)
context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'MonitorLecturerApp/template.html'}
context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'MonitorLecturerApp/template.html', 'lec_list': lec_list}
return render(request, 'MonitorLecturerApp/index.html', context)
......@@ -108,7 +133,7 @@ def lecVideo(request):
durations = []
for videoPath in videoPaths:
video = tVideo()
video = LecturerVideo()
cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
......
#SLPES Mobile Application
# # 2020-101
## Introduction
This project will be created under the guidelines provided by the Research Project module offered in 4th Year by the Faculty of Computing. The title of the project is "Student and Lecturer Performance Enhancement System". This Research Project comes under the domain of Artifical Intelligence and Machine Learning along with the support of Computer Vision.
## Main Objective
Main Objectives that will be targetted in this Research Project will be listed as follows.
* Tracking student attendance using facial detection and facial recognition and notify and getting opinion from the students who are absent and students who are leaving the lecture in the during a specified time period (Attendance Register).
* Monitoring student behavior within the classroom during lecture periods to identify potential problem areas in retaining student attention and adapting the lecturing styles to suit the student needs (Monitoring Student Behavior).
* Summarize the converted text and present as a document and identify the important points of the lecture to display them highlighted (Lecture Summarizing).
* Monitoring lecturers’ behavior by analyzing the teaching style in a lecture hall during the lecture hours (Monitor Lecturer Performance).
## Main Research Questions
This Research Project will be conducted to find answers for the following 4 research questions.
* “What is the optimum way of tracking student attendance in a much efficient way and how does the lecturer analyze reasons for student absenteeism?” (Q1).
* “Does a correlation exist between lecturing style and student behavior in the classroom and how can Computer Vision and Artificial Intelligence be incorporated in determining this relationship?” (Q2).
* “How to summarize the lecture content to enable students to pay more attention to the lecture and reduce time spend for taking notes?” (Q3).
* “How to evaluate lecture performance by tracking their behavior during a lecture and analyzing the quality of the lecture content which is delivered by the lecturer?” (Q4).
## Individual Research Questions
The main research questions came up for the project were based on each individual component that will be implemented through the course of the project. Hence, the individual research questions could be listed down as follows.
### Attendance Register
*What is the optimum way of tracking student attendance in a much efficient way and how does the lecturer analyze reasons for student absenteeism?*
### Monitoring Student Behavior
*Does a correlation exist between lecturing style and student behavior in the classroom and how can Computer Vision and Artificial Intelligence be incorporated in determining this relationship?.*
### Lecture Summarizing
*How to summarize the lecture content to enable students to pay more attention to the lecture and reduce time spend for taking notes?*
### Monitoring Lecturer Performance
*How to evaluate lecture performance by tracking their behavior during a lecture and analyzing the quality of the lecture content which is delivered by the lecturer?”*
## Individual Objectives
The main objectives of the research project could be further split into individual objectives which elaborates purpose of the project in much detail.
### Attendance Register
* Tracking student attendance using facial detection and facial recognition.
* Notify and getting opinion from the students who are absent and students who are leaving the lecture in the during a specified time period.
* Setting up student data and respective course data in an adaptive manner.
* Provide an overview for the lecturer regarding student attendance through a dashboard and predicting future attendance.
### Monitoring Student Behavior
* Monitoring student behavior within the classroom during lecture periods to identify potential problem areas in retaining student attention and adapting the lecturing styles to suit the student needs.
* Identifying the concentration level, emotion expressions and general behavior of students within 2-hour lecture duration using facial recognition, emotion recognition and motion detection employing computer vision technologies.
* Determining the dependency between student behavior and the lecturer behavior by analyzing overall behavior status of students and lecturer for a given time frame during the lecture.
### Lecture Summarizing
* Understand lecturer’s voice and filter the lecturer’s voice by removing background noises and silent pauses
* Convert the noise-filtered audio into text
* Summarize the converted text and present as a document.
* Identify the important points of the lecture to display them highlighted.
* Display important notices mentioned in the lecture.
### Monitoring Lecturer Performance
* Monitoring lecturers’ behavior by analyzing the teaching style in a lecture hall during the lecture hours.
* Identifying the lectures emotional state when the lecture is conducting.
* Generating an end-semester feedback of the lecturer giving a summary of their performance.
SLPES Mobile Application
Introduction
......
......@@ -35,6 +35,7 @@ INSTALLED_APPS = [
'FirstApp.apps.FirstappConfig',
'AttendanceApp.apps.AttendanceappConfig',
'MonitorLecturerApp.apps.MonitorlecturerappConfig',
'LectureSummarizingApp.apps.LectureSummarizingAppConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
......
......@@ -23,4 +23,6 @@ urlpatterns = [
path('', include('FirstApp.urls')),
path('attendance/', include('AttendanceApp.urls')),
path('lecturer/', include('MonitorLecturerApp.urls')),
path('lecturer/', include('MonitorLecturerApp.urls')),
path('summary/', include('LectureSummarizingApp.urls'))
]
absl-py==0.9.0
alabaster==0.7.12
anaconda-client==1.7.2
anaconda-navigator==1.9.7
anaconda-project==0.8.3
asgiref==3.2.3
asn1crypto==1.0.1
astor==0.8.1
astroid==2.3.1
astropy==3.2.1
atomicwrites==1.3.0
attrs==19.2.0
Babel==2.7.0
backcall==0.1.0
backports.functools-lru-cache==1.5
backports.os==0.1.1
backports.shutil-get-terminal-size==1.0.0
backports.tempfile==1.0
backports.weakref==1.0.post1
beautifulsoup4==4.8.0
bitarray==1.0.1
bkcharts==0.2
bleach==3.1.0
bokeh==1.3.4
bootstrap4==0.1.0
boto==2.49.0
Bottleneck==1.2.1
bson==0.5.8
cachetools==4.0.0
certifi==2019.9.11
cffi==1.12.3
chardet==3.0.4
Click==7.0
cloudpickle==1.2.2
clyent==1.2.2
colorama==0.4.1
comtypes==1.1.7
conda==4.7.12
conda-build==3.18.9
conda-package-handling==1.6.0
conda-verify==3.4.2
contextlib2==0.6.0
cryptography==2.7
cycler==0.10.0
Cython==0.29.13
cytoolz==0.10.0
dask==2.5.2
dataclasses==0.6
decorator==4.4.0
deepspeech==0.7.1
defusedxml==0.6.0
distributed==2.5.2
Django==2.2.12
djangorestframework==3.11.0
djongo==1.3.1
dnspython==1.16.0
docopt==0.6.2
docutils==0.15.2
entrypoints==0.3
et-xmlfile==1.0.1
fastcache==1.1.0
filelock==3.0.12
Flask==1.1.1
fsspec==0.5.2
future==0.17.1
gast==0.2.2
gevent==1.4.0
glob2==0.7
google-auth==1.11.3
google-auth-oauthlib==0.4.1
google-pasta==0.2.0
greenlet==0.4.15
grpcio==1.27.2
h5py==2.9.0
HeapDict==1.0.1
html5lib==1.0.1
idna==2.8
imageio==2.6.0
imagesize==1.1.0
importlib-metadata==0.23
imutils==0.5.3
ipykernel==5.1.2
ipython==7.8.0
ipython-genutils==0.2.0
ipywidgets==7.5.1
isort==4.3.21
itsdangerous==1.1.0
jdcal==1.4.1
jedi==0.15.1
Jinja2==2.10.3
joblib==0.13.2
Js2Py==0.67
json5==0.8.5
jsonschema==3.0.2
jupyter==1.0.0
jupyter-client==5.3.3
jupyter-console==6.0.0
jupyter-core==4.5.0
jupyterlab==1.1.4
jupyterlab-server==1.0.6
Keras==2.3.1
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.0
keyring==18.0.0
kiwisolver==1.1.0
lazy-object-proxy==1.4.2
libarchive-c==2.8
llvmlite==0.29.0
locket==0.2.0
lxml==4.4.1
Markdown==3.2.1
MarkupSafe==1.1.1
matplotlib==3.1.1
mccabe==0.6.1
menuinst==1.4.16
mistune==0.8.4
mkl-fft==1.0.14
mkl-random==1.1.0
mkl-service==2.3.0
mock==3.0.5
more-itertools==7.2.0
mpmath==1.1.0
msgpack==0.6.1
multipledispatch==0.6.0
navigator-updater==0.2.1
nbconvert==5.6.0
nbformat==4.4.0
networkx==2.3
nltk==3.4.5
nose==1.3.7
notebook==6.0.1
numba==0.45.1
numexpr==2.7.0
numpy==1.16.5
numpydoc==0.9.1
oauthlib==3.1.0
olefile==0.46
opencv-python==4.2.0.32
openpyxl==3.0.0
opt-einsum==3.2.0
packaging==19.2
pandas==0.25.1
pandocfilters==1.4.2
parso==0.5.1
partd==1.0.0
path.py==12.0.1
pathlib2==2.3.5
patsy==0.5.1
pep8==1.7.1
pickleshare==0.7.5
Pillow==6.2.0
pipwin==0.4.6
pkginfo==1.5.0.1
pluggy==0.13.0
ply==3.11
prometheus-client==0.7.1
prompt-toolkit==2.0.10
protobuf==3.11.3
psutil==5.6.3
py==1.8.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
PyAudio==0.2.11
pycodestyle==2.5.0
pycosat==0.6.3
pycparser==2.19
pycrypto==2.6.1
pycurl==7.43.0.3
pyflakes==2.1.1
Pygments==2.4.2
pyjsparser==2.7.1
pylint==2.4.2
pymongo==3.10.1
pyodbc==4.0.27
pyOpenSSL==19.0.0
pyparsing==2.4.2
PyPrind==2.11.2
pyreadline==2.1
pyrsistent==0.15.4
PySocks==1.7.1
pytest==5.2.1
pytest-arraydiff==0.3
pytest-astropy==0.5.0
pytest-doctestplus==0.4.0
pytest-openfiles==0.4.0
pytest-remotedata==0.3.2
python-dateutil==2.8.0
pytz==2019.3
PyWavelets==1.0.3
pywin32==223
pywinpty==0.5.5
PyYAML==5.1.2
pyzmq==18.1.0
QtAwesome==0.6.0
qtconsole==4.5.5
QtPy==1.9.0
requests==2.22.0
requests-oauthlib==1.3.0
robobrowser==0.5.3
rope==0.14.0
rsa==4.0
ruamel-yaml==0.15.46
scikit-image==0.15.0
scikit-learn==0.21.3
scipy==1.4.1
seaborn==0.9.0
Send2Trash==1.5.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.14.0
snowballstemmer==2.0.0
sortedcollections==1.1.2
sortedcontainers==2.1.0
soupsieve==1.9.3
Sphinx==2.2.0
sphinxcontrib-applehelp==1.0.1
sphinxcontrib-devhelp==1.0.1
sphinxcontrib-htmlhelp==1.0.2
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.2
sphinxcontrib-serializinghtml==1.1.3
sphinxcontrib-websupport==1.1.2
spyder==3.3.6
spyder-kernels==0.5.2
SQLAlchemy==1.3.9
sqlparse==0.2.4
statsmodels==0.10.1
sympy==1.4
tables==3.5.2
tblib==1.4.0
tensorboard==2.1.1
tensorflow==2.1.0
tensorflow-estimator==2.1.0
termcolor==1.1.0
terminado==0.8.2
testpath==0.4.2
toolz==0.10.0
tornado==6.0.3
tqdm==4.36.1
traitlets==4.3.3
tzlocal==2.0.0
unicodecsv==0.14.1
urllib3==1.24.2
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.16.0
widgetsnbextension==3.5.1
win-inet-pton==1.1.0
win-unicode-console==0.5
wincertstore==0.2
wrapt==1.11.2
xlrd==1.2.0
XlsxWriter==1.2.1
xlwings==0.15.10
xlwt==1.3.0
zict==1.0.0
zipp==0.6.0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment