diff --git a/api/models.py b/api/models.py index 5578d62..b377183 100644 --- a/api/models.py +++ b/api/models.py @@ -34,7 +34,7 @@ class Video(models.Model): else: raise TooLargeFile() - def create_comic(self, frames_mode=0, rl_mode=0, image_assessment_mode=0, style_transfer_mode=0): + def create_comix(self, yt_url='', frames_mode=0, rl_mode=0, image_assessment_mode=0, style_transfer_mode=0): (keyframes, keyframes_timings), keyframes_extraction_time = KeyFramesExtractor.get_keyframes( video=self, frames_mode=frames_mode, @@ -45,29 +45,49 @@ class Video(models.Model): style_transfer_mode=style_transfer_mode) comic_image, layout_generation_time = LayoutGenerator.get_layout(frames=stylized_keyframes) + comic, from_nparray_time = Comic.create_from_nparray(nparray=comic_image, + video=self, + yt_url=yt_url, + frames_mode=frames_mode, + rl_mode=rl_mode, + image_assessment_mode=image_assessment_mode, + style_transfer_mode=style_transfer_mode) + timings = { + 'from_nparray_time': from_nparray_time, 'keyframes_extraction_time': keyframes_extraction_time, 'stylization_time': stylization_time, 'layout_generation_time': layout_generation_time, 'keyframes_extraction_time_details': keyframes_timings } - return comic_image, timings + return comic, timings class Comic(models.Model): file = models.FileField(blank=False, null=False, upload_to="comic") video = models.ForeignKey(Video, on_delete=models.CASCADE, related_name="comic") + yt_url = models.URLField(blank=True, null=True) + frames_mode = models.PositiveIntegerField(default=0) + rl_mode = models.PositiveIntegerField(default=0) + image_assessment_mode = models.PositiveIntegerField(default=0) + style_transfer_mode = models.PositiveIntegerField(default=0) @classmethod @profile - def create_from_nparray(cls, nparray_file, video): - if nparray_file.max() <= 1: - nparray_file = (nparray_file).astype(int) + def create_from_nparray(cls, nparray, video, yt_url, frames_mode, rl_mode, image_assess_mode, style_transfer_mode): + # if nparray.max() <= 1: + # nparray = nparray.astype(int) tmp_name = uuid.uuid4().hex + ".png" - cv2.imwrite(jj(settings.TMP_DIR, tmp_name), nparray_file) + cv2.imwrite(jj(settings.TMP_DIR, tmp_name), nparray) with open(jj(settings.TMP_DIR, tmp_name), mode="rb") as tmp_file: comic_image = File(tmp_file, name=tmp_name) - comic = Comic.objects.create(file=comic_image, video=video) + comic = Comic.objects.create(file=comic_image, + video=video, + yt_url=yt_url, + frames_mode=frames_mode, + rl_mode=rl_mode, + image_assessment_mode=image_assess_mode, + style_transfer_mode=style_transfer_mode) os.remove(jj(settings.TMP_DIR, tmp_name)) return comic diff --git a/api/serializers.py b/api/serializers.py index 5510527..04977ef 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -16,9 +16,9 @@ class VideoSerializer(serializers.Serializer): def validate(self, attrs): file = attrs.get("file") if file.name.split(".")[-1] not in settings.PERMITTED_VIDEO_EXTENSIONS: - raise FileExtensionError + raise FileExtensionError() if file.size > settings.MAX_FILE_SIZE: - raise TooLargeFile + raise TooLargeFile() return attrs diff --git a/api/views.py b/api/views.py index 9d6fdbe..37b2b43 100644 --- a/api/views.py +++ b/api/views.py @@ -16,21 +16,24 @@ class Comixify(APIView): serializer = VideoSerializer(data=request.data) serializer.is_valid(raise_exception=True) - video_file = serializer.validated_data["file"] + frames_mode = serializer.validated_data["frames_mode"], + rl_mode = serializer.validated_data["rl_mode"], + image_assessment_mode = serializer.validated_data["image_assessment_mode"], + style_transfer_mode = serializer.validated_data["style_transfer_mode"], + video = Video.objects.create(file=video_file) - comic_image, timings = video.create_comic( - frames_mode=serializer.validated_data["frames_mode"], - rl_mode=serializer.validated_data["rl_mode"], - image_assessment_mode=serializer.validated_data["image_assessment_mode"], - style_transfer_mode=serializer.validated_data["style_transfer_mode"], + comix, timings = video.create_comix( + yt_url='', + frames_mode=frames_mode, + rl_mode=rl_mode, + image_assessment_mode=image_assessment_mode, + style_transfer_mode=style_transfer_mode, ) - comic, from_nparray_time = Comic.create_from_nparray(comic_image, video) - timings['from_nparray_time'] = from_nparray_time response = { "status_message": "ok", - "comic": comic.file.url, + "comic": comix.file.url, "timings": timings, } # Remove to spare storage @@ -39,7 +42,6 @@ class Comixify(APIView): class ComixifyFromYoutube(APIView): - def post(self, request): """ Receives video, and returns comic image @@ -48,25 +50,40 @@ class ComixifyFromYoutube(APIView): serializer = YouTubeDownloadSerializer(data=request.data) serializer.is_valid(raise_exception=True) yt_url = serializer.validated_data["url"] + frames_mode = serializer.validated_data["frames_mode"], + rl_mode = serializer.validated_data["rl_mode"], + image_assessment_mode = serializer.validated_data["image_assessment_mode"], + style_transfer_mode = serializer.validated_data["style_transfer_mode"], - video = Video() - _, yt_download_time = video.download_from_youtube(yt_url) - video.save() - comic_image, timings = video.create_comic( - frames_mode=serializer.validated_data["frames_mode"], - rl_mode=serializer.validated_data["rl_mode"], - image_assessment_mode=serializer.validated_data["image_assessment_mode"], - style_transfer_mode=serializer.validated_data["style_transfer_mode"], - ) - comic, from_nparray_time = Comic.create_from_nparray(comic_image, video) - timings['from_nparray_time'] = from_nparray_time - timings['yt_download_time'] = yt_download_time + comix = Comic.objects.filter(yt_url=yt_url, + frames_mode=frames_mode, + rl_mode=rl_mode, + image_assessment_mode=image_assessment_mode, + style_transfer_mode=style_transfer_mode, + ).first() + if comix is not None: + response = { + "status_message": "ok", + "comic": comix.file.url, + } + else: + video = Video() + _, yt_download_time = video.download_from_youtube(yt_url) + video.save() + comix, timings = video.create_comix( + yt_url=yt_url, + frames_mode=frames_mode, + rl_mode=rl_mode, + image_assessment_mode=image_assessment_mode, + style_transfer_mode=style_transfer_mode, + ) - response = { - "status_message": "ok", - "comic": comic.file.url, - "timings": timings, - } - # Remove to spare storage - video.file.delete() + timings['yt_download_time'] = yt_download_time + response = { + "status_message": "ok", + "comic": comix.file.url, + "timings": timings, + } + # Remove to spare storage + video.file.delete() return Response(response) diff --git a/get_yt_comix_media_urls.py b/get_yt_comix_media_urls.py new file mode 100644 index 0000000..aafc991 --- /dev/null +++ b/get_yt_comix_media_urls.py @@ -0,0 +1,43 @@ +import pandas as pd +import requests + +yt_urls = {'pulp_fiction': 'https://www.youtube.com/watch?v=pvAhRcUofDk'} +base_comixify_url = 'https://comixify.ii.pw.edu.pl' + +frames_modes = [0, 1] +rl_modes = [0, 1] +image_assessment_modes = [0, 1] +style_transfer_modes = [0, 1, 2] + +results = {'clip_name': [], + 'clip_yt_url': [], + 'media_url': [], + 'frames_mode': [], + 'rl_mode': [], + 'image_assessment_mode': [], + 'style_transfer_mode': []} + +for clip_name in yt_urls.keys(): + for f_mode in frames_modes: + for rl_model in rl_modes: + for iam_mode in image_assessment_modes: + for st_mode in style_transfer_modes: + r = requests.post(base_comixify_url + '/comixify/from_yt/', + data={'url': yt_urls[clip_name], + 'frames_mode': f_mode, + 'rl_mode': rl_model, + 'image_assessment_mode': iam_mode, + 'style_transfer_mode': st_mode}) + + media_url = base_comixify_url + r.json()['comic'] + + results['clip_name'].append(clip_name) + results['clip_yt_url'].append(yt_urls[clip_name]) + results['media_url'].append(media_url) + results['frames_mode'].append(f_mode) + results['rl_mode'].append(rl_model) + results['image_assessment_mode'].append(iam_mode) + results['style_transfer_mode'].append(st_mode) + +df = pd.DataFrame(results) +df.to_csv('yt_comix_media_urls') diff --git a/requirements.txt b/requirements.txt index cc7af2b..0e4effe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,7 @@ +absl-py==0.6.1 astor==0.7.1 +certifi==2018.10.15 +chardet==3.0.4 cloudpickle==0.6.1 cycler==0.10.0 dask==0.20.0 @@ -10,6 +13,7 @@ gast==0.2.0 grpcio==1.16.0 gunicorn==19.9.0 h5py==2.8.0 +idna==2.7 Keras==2.2.4 Keras-Applications==1.0.6 Keras-Preprocessing==1.0.5 @@ -21,6 +25,7 @@ numpy==1.14.5 opencv-contrib-python==3.4.3.18 opencv-python==3.4.2.17 pafy==0.5.4 +pandas==0.23.4 Pillow==5.2.0 protobuf==3.6.1 psycopg2==2.7.5 @@ -29,6 +34,7 @@ python-dateutil==2.7.5 pytz==2018.5 PyWavelets==1.0.1 PyYAML==3.13 +requests==2.20.1 scikit-image==0.14.1 scikit-learn==0.20.0 scipy==1.1.0 @@ -40,6 +46,6 @@ termcolor==1.1.0 toolz==0.9.0 torch==0.4.1 torchvision==0.2.1 +urllib3==1.24.1 Werkzeug==0.14.1 youtube-dl==2018.11.7 -tensorflow-gpu==1.10.1 \ No newline at end of file