imseldrith commited on
Commit
be6c755
1 Parent(s): 37485ad

Upload folder using huggingface_hub (#1)

Browse files

- Upload folder using huggingface_hub (81984557c151c3b6fe28fc91b4fca23988812e04)

.dockerignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Dockerfile
2
+ README.md
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ __pycache__
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ static/sample_images/twitter_image.png filter=lfs diff=lfs merge=lfs -text
37
+ white_box_cartoonizer/saved_models/model-33999.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ __pycache__/
2
+ .vscode/*
3
+ static/uploaded_videos/*.mp4
4
+ static/cartoonized_images/*.jpg
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official lightweight Python image.
2
+ # https://hub.docker.com/_/python
3
+ FROM python:3.7-slim
4
+
5
+ # Copy local code to the container image.
6
+ ENV APP_HOME /app
7
+ WORKDIR $APP_HOME
8
+ COPY . ./
9
+
10
+ ENV GOOGLE_APPLICATION_CREDENTIALS "./token.json"
11
+
12
+ RUN apt-get update && apt-get install -y \
13
+ libglib2.0-0 \
14
+ libsm6 \
15
+ libxext6 \
16
+ libxrender-dev \
17
+ ffmpeg
18
+ # Install production dependencies.
19
+ RUN pip install -r requirements.txt
20
+
21
+ # Run the web service on container startup. Here we use the gunicorn
22
+ # webserver, with one worker process and 8 threads.
23
+ # For environments with multiple CPU cores, increase the number of workers
24
+ # to be equal to the cores available.
25
+ CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 --timeout 0 app:app
LICENSE ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License
2
+
3
+ By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
4
+
5
+ Section 1 – Definitions.
6
+
7
+ Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
8
+ Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
9
+ BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License.
10
+ Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
11
+ Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
12
+ Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
13
+ License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution, NonCommercial, and ShareAlike.
14
+ Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
15
+ Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
16
+ Licensor means the individual(s) or entity(ies) granting rights under this Public License.
17
+ NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange.
18
+ Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
19
+ Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
20
+ You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
21
+
22
+ Section 2 – Scope.
23
+
24
+ License grant.
25
+ Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
26
+ reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and
27
+ produce, reproduce, and Share Adapted Material for NonCommercial purposes only.
28
+ Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
29
+ Term. The term of this Public License is specified in Section 6(a).
30
+ Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
31
+ Downstream recipients.
32
+ Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
33
+ Additional offer from the Licensor – Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply.
34
+ No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
35
+ No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
36
+
37
+ Other rights.
38
+ Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
39
+ Patent and trademark rights are not licensed under this Public License.
40
+ To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes.
41
+
42
+ Section 3 – License Conditions.
43
+
44
+ Your exercise of the Licensed Rights is expressly made subject to the following conditions.
45
+
46
+ Attribution.
47
+
48
+ If You Share the Licensed Material (including in modified form), You must:
49
+ retain the following if it is supplied by the Licensor with the Licensed Material:
50
+ identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
51
+ a copyright notice;
52
+ a notice that refers to this Public License;
53
+ a notice that refers to the disclaimer of warranties;
54
+ a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
55
+ indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
56
+ indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
57
+ You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
58
+ If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
59
+ ShareAlike.
60
+
61
+ In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply.
62
+ The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-NC-SA Compatible License.
63
+ You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material.
64
+ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply.
65
+
66
+ Section 4 – Sui Generis Database Rights.
67
+
68
+ Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
69
+
70
+ for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only;
71
+ if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and
72
+ You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
73
+
74
+ For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
75
+
76
+ Section 5 – Disclaimer of Warranties and Limitation of Liability.
77
+
78
+ Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
79
+ To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
80
+
81
+ The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
82
+
83
+ Section 6 – Term and Termination.
84
+
85
+ This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
86
+
87
+ Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
88
+ automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
89
+ upon express reinstatement by the Licensor.
90
+ For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
91
+ For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
92
+ Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
93
+
94
+ Section 7 – Other Terms and Conditions.
95
+
96
+ The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
97
+ Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
98
+
99
+ Section 8 – Interpretation.
100
+
101
+ For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
102
+ To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
103
+ No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
104
+ Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
README.md CHANGED
@@ -1,11 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Cartoonize
3
- emoji: 📈
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: static
7
- pinned: false
8
- license: mit
 
 
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cartoonizer
2
+
3
+ > Convert images and videos into a cartoon!
4
+
5
+ The webapp is deployed here - https://cartoonize-lkqov62dia-de.a.run.app
6
+ <div style="text-align:center"><img height="100" alt="Powered by Algorithmia" style="border-width:0" src="static/sample_images/algorithmia.jpeg" /></div>
7
+
8
+ You can find a writeup on this webapp's architecture [here](https://medium.com/@Niraj_pandkar/how-we-built-an-inexpensive-scalable-architecture-to-cartoonize-the-world-8610050f90a0)!
9
+
10
+ ---
11
+
12
+ ## Contents
13
+
14
+ - [Prerequisites for Google Cloud and Algorithmia](#prerequisites-for-google-cloud-and-algorithmia)
15
+ - [Installation](#installation)
16
+ - [Docker](#using-docker)
17
+ - [VirtualEnv](#using-virtualenv)
18
+ - [Google Colab](#using-google-colab)
19
+ - [Sample Image and Video](#sample-image-and-video)
20
+
21
+ ---
22
+
23
+ ## Prerequisites for Google Cloud and Algorithmia
24
+
25
+ **These are important steps if you want to leverage Google buckets, signed URLs and Algorithmia's platform. Skip this if you want to run locally / colab.**
26
+
27
+ ### Cloud Run authentication
28
+ To use any functionalities pertaining to Google Cloud, you'll need a global authentication file (JSON). You can obtain this JSON by following the steps given here - [Getting started with authentication](https://cloud.google.com/docs/authentication/getting-started)
29
+
30
+ After you get the JSON file, rename it to `token.json` (so that it's compatible with the codebase).
31
+
32
+ Set the environment variable in your terminal -
33
+ ```
34
+ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/token.json"
35
+ ```
36
+ **Notes**:
37
+ - You can set it permanently by adding this line to `~/.bashrc`.
38
+ - `Dockerfile` already includes the setting of this particular environment variable. :)
39
+
40
+
41
+ ### Algorithmia
42
+ We used the Serveless AI Layer product of [Algorithmia](https://algorithmia.com/serverless-ai-layer) for inference on videos.
43
+ To learn more on how to deploy your model in Algorithmia, check here - https://algorithmia.com/developers
44
+
45
+ ---
46
+
47
+ ## Installation
48
+
49
+ ### Application tested on:
50
+
51
+ - python 3.7
52
+ - tensorflow 2.1.0
53
+ - tf_slim 1.1.0
54
+ - ffmpeg 3.4.8
55
+ - Cuda version 10.1
56
+ - OS: Linux (Ubuntu 18.04)
57
+
58
+ ### Using Docker
59
+
60
+ The easiest way to get the webapp running is by using the Dockerfile:
61
+
62
+ 1. `cd` into the root directory and build the image
63
+ ```
64
+ docker build -t cartoonize .
65
+ ```
66
+ **Note**: Set the appropriate values in `config.yaml` before building the image.
67
+
68
+ 2. Run the container by exposing the appropriate ports
69
+ ```
70
+ docker run -p 8080:8080 cartoonize
71
+ ```
72
+
73
+
74
+ ### Using `virtualenv`
75
+
76
+ 1. Make a virtual environment using `virutalenv` and activate it
77
+ ```
78
+ virtualenv -p python3 cartoonize
79
+ source cartoonize/bin/activate
80
+ ```
81
+ 2. Install python dependencies
82
+ ```
83
+ pip install -r requirements.txt
84
+ ```
85
+ 3. Run the webapp. Be sure to set the appropriate values in `config.yaml` file before running the application.
86
+ ```
87
+ python app.py
88
+ ```
89
+
90
+ ### Using [Google Colab](https://colab.research.google.com/drive/1oDhMEVMcsRbe7bt-2A7cDsx44KQpQwuB?usp=sharing)
91
+ 1. Clone the repository using either of the below mentioned way:
92
+ - Using Command:
93
+ - Create a new Notebook in Colab and in the cell execute the below command.
94
+
95
+ ```
96
+ ! git clone https://github.com/experience-ml/cartoonize.git
97
+ ```
98
+ **Note:** Don't forget to add `!` at the beginning of the command
99
+
100
+ - From Colab User Interface
101
+ ```
102
+ Open Colab
103
+ └── File
104
+ └── Open Notebook
105
+ └── Github
106
+ └── paste the Url of the repository
107
+ ```
108
+ Note : Before running the application change the runtime to GPU for processing videos but you for images CPU shall also work just fine.
109
+ ```
110
+ Runtime
111
+ └── Change runtime type
112
+ └── Select GPU
113
+ ```
114
+ 2. After cloning the repository navigate to the `/cartoonize` using below command in the notebook cell:
115
+
116
+ ```
117
+ %cd cartoonize
118
+ ```
119
+ 3. Run the below commands in the notebook cell to install the requirements.
120
+
121
+ ```
122
+ !pip install -r requirements.txt
123
+ ```
124
+
125
+
126
+ 4. In config.yaml file set:
127
+
128
+ ```
129
+ colab-mode: true
130
+ ```
131
+
132
+ 5. Launch the flask app on ngrok
133
+
134
+ ```
135
+ !python app.py
136
+ ```
137
+
138
+ #### Note : Sample [Google Colab Notebook](https://colab.research.google.com/drive/1oDhMEVMcsRbe7bt-2A7cDsx44KQpQwuB?usp=sharing) for reference
139
+
140
  ---
141
+
142
+ ## Sample Image and Video
143
+
144
+ ### Emma Watson Cartoonized
145
+ <img alt="Emma Watson Cartoonized" style="border-width:0" src="static/sample_images/twitter_image.png" />
146
+
147
+ ### Youtube Video of Avenger's Bar Scene Cartoonized
148
+ [![Cartoonized version of Avenger's bar scene](http://img.youtube.com/vi/GqduSLcmhto/0.jpg)](http://www.youtube.com/watch?v=GqduSLcmhto "AVENGERS BAR SCENE [Cartoonized Version]")
149
+
150
  ---
151
 
152
+ ## License
153
+
154
+ 1. Copyright © Cartoonizer ([Demo webapp](https://cartoonize-lkqov62dia-de.a.run.app/))
155
+
156
+ - Authors: [Niraj Pandkar](https://twitter.com/Niraj_pandkar) and [Tejas Mahajan](https://twitter.com/tjdevWorks).
157
+
158
+ - Licensed under the [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode)
159
+ - Commercial application is prohibited by license
160
+
161
+
162
+ 2. Copyright (C) Xinrui Wang, Jinze Yu. ([White box cartoonization](https://github.com/SystemErrorWang/White-box-Cartoonization))
163
+ - All rights reserved.
164
+ - Licensed under the CC BY-NC-SA 4.0
165
+ - Also, Commercial application is prohibited license (https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
app.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import uuid
4
+ import sys
5
+ import yaml
6
+ import traceback
7
+
8
+ with open('./config.yaml', 'r') as fd:
9
+ opts = yaml.safe_load(fd)
10
+
11
+ sys.path.insert(0, './white_box_cartoonizer/')
12
+
13
+ import cv2
14
+ from flask import Flask, render_template, make_response, flash
15
+ import flask
16
+ from PIL import Image
17
+ import numpy as np
18
+ import skvideo.io
19
+ if opts['colab-mode']:
20
+ from flask_ngrok import run_with_ngrok #to run the application on colab using ngrok
21
+
22
+
23
+ from cartoonize import WB_Cartoonize
24
+
25
+ if not opts['run_local']:
26
+ if 'GOOGLE_APPLICATION_CREDENTIALS' in os.environ:
27
+ from gcloud_utils import upload_blob, generate_signed_url, delete_blob, download_video
28
+ else:
29
+ raise Exception("GOOGLE_APPLICATION_CREDENTIALS not set in environment variables")
30
+ from video_api import api_request
31
+ # Algorithmia (GPU inference)
32
+ import Algorithmia
33
+
34
+ app = Flask(__name__)
35
+ if opts['colab-mode']:
36
+ run_with_ngrok(app) #starts ngrok when the app is run
37
+
38
+ app.config['UPLOAD_FOLDER_VIDEOS'] = 'static/uploaded_videos'
39
+ app.config['CARTOONIZED_FOLDER'] = 'static/cartoonized_images'
40
+
41
+ app.config['OPTS'] = opts
42
+
43
+ ## Init Cartoonizer and load its weights
44
+ wb_cartoonizer = WB_Cartoonize(os.path.abspath("white_box_cartoonizer/saved_models/"), opts['gpu'])
45
+
46
+ def convert_bytes_to_image(img_bytes):
47
+ """Convert bytes to numpy array
48
+
49
+ Args:
50
+ img_bytes (bytes): Image bytes read from flask.
51
+
52
+ Returns:
53
+ [numpy array]: Image numpy array
54
+ """
55
+
56
+ pil_image = Image.open(io.BytesIO(img_bytes))
57
+ if pil_image.mode=="RGBA":
58
+ image = Image.new("RGB", pil_image.size, (255,255,255))
59
+ image.paste(pil_image, mask=pil_image.split()[3])
60
+ else:
61
+ image = pil_image.convert('RGB')
62
+
63
+ image = np.array(image)
64
+
65
+ return image
66
+
67
+ @app.route('/')
68
+ @app.route('/cartoonize', methods=["POST", "GET"])
69
+ def cartoonize():
70
+ opts = app.config['OPTS']
71
+ if flask.request.method == 'POST':
72
+ try:
73
+ if flask.request.files.get('image'):
74
+ img = flask.request.files["image"].read()
75
+
76
+ ## Read Image and convert to PIL (RGB) if RGBA convert appropriately
77
+ image = convert_bytes_to_image(img)
78
+
79
+ img_name = str(uuid.uuid4())
80
+
81
+ cartoon_image = wb_cartoonizer.infer(image)
82
+
83
+ cartoonized_img_name = os.path.join(app.config['CARTOONIZED_FOLDER'], img_name + ".jpg")
84
+ cv2.imwrite(cartoonized_img_name, cv2.cvtColor(cartoon_image, cv2.COLOR_RGB2BGR))
85
+
86
+ if not opts["run_local"]:
87
+ # Upload to bucket
88
+ output_uri = upload_blob("cartoonized_images", cartoonized_img_name, img_name + ".jpg", content_type='image/jpg')
89
+
90
+ # Delete locally stored cartoonized image
91
+ os.system("rm " + cartoonized_img_name)
92
+ cartoonized_img_name = generate_signed_url(output_uri)
93
+
94
+
95
+ return render_template("index_cartoonized.html", cartoonized_image=cartoonized_img_name)
96
+
97
+ if flask.request.files.get('video'):
98
+
99
+ filename = str(uuid.uuid4()) + ".mp4"
100
+ video = flask.request.files["video"]
101
+ original_video_path = os.path.join(app.config['UPLOAD_FOLDER_VIDEOS'], filename)
102
+ video.save(original_video_path)
103
+
104
+ modified_video_path = os.path.join(app.config['UPLOAD_FOLDER_VIDEOS'], filename.split(".")[0] + "_modified.mp4")
105
+
106
+ ## Fetch Metadata and set frame rate
107
+ file_metadata = skvideo.io.ffprobe(original_video_path)
108
+ original_frame_rate = None
109
+ if 'video' in file_metadata:
110
+ if '@r_frame_rate' in file_metadata['video']:
111
+ original_frame_rate = file_metadata['video']['@r_frame_rate']
112
+
113
+ if opts['original_frame_rate']:
114
+ output_frame_rate = original_frame_rate
115
+ else:
116
+ output_frame_rate = opts['output_frame_rate']
117
+
118
+ output_frame_rate_number = int(output_frame_rate.split('/')[0])
119
+
120
+ #change the size if you want higher resolution :
121
+ ############################
122
+ # Recommnded width_resize #
123
+ ############################
124
+ #width_resize = 1920 for 1080p: 1920x1080.
125
+ #width_resize = 1280 for 720p: 1280x720.
126
+ #width_resize = 854 for 480p: 854x480.
127
+ #width_resize = 640 for 360p: 640x360.
128
+ #width_resize = 426 for 240p: 426x240.
129
+ width_resize=opts['resize-dim']
130
+
131
+ # Slice, Resize and Convert Video as per settings
132
+ if opts['trim-video']:
133
+ #change the variable value to change the time_limit of video (In Seconds)
134
+ time_limit = opts['trim-video-length']
135
+ if opts['original_resolution']:
136
+ os.system("ffmpeg -hide_banner -loglevel warning -ss 0 -i '{}' -t {} -filter:v scale=-1:-2 -r {} -c:a copy '{}'".format(os.path.abspath(original_video_path), time_limit, output_frame_rate_number, os.path.abspath(modified_video_path)))
137
+ else:
138
+ os.system("ffmpeg -hide_banner -loglevel warning -ss 0 -i '{}' -t {} -filter:v scale={}:-2 -r {} -c:a copy '{}'".format(os.path.abspath(original_video_path), time_limit, width_resize, output_frame_rate_number, os.path.abspath(modified_video_path)))
139
+ else:
140
+ if opts['original_resolution']:
141
+ os.system("ffmpeg -hide_banner -loglevel warning -ss 0 -i '{}' -filter:v scale=-1:-2 -r {} -c:a copy '{}'".format(os.path.abspath(original_video_path), output_frame_rate_number, os.path.abspath(modified_video_path)))
142
+ else:
143
+ os.system("ffmpeg -hide_banner -loglevel warning -ss 0 -i '{}' -filter:v scale={}:-2 -r {} -c:a copy '{}'".format(os.path.abspath(original_video_path), width_resize, output_frame_rate_number, os.path.abspath(modified_video_path)))
144
+
145
+ audio_file_path = os.path.join(app.config['UPLOAD_FOLDER_VIDEOS'], filename.split(".")[0] + "_audio_modified.mp4")
146
+ os.system("ffmpeg -hide_banner -loglevel warning -i '{}' -map 0:1 -vn -acodec copy -strict -2 '{}'".format(os.path.abspath(modified_video_path), os.path.abspath(audio_file_path)))
147
+
148
+ if opts["run_local"]:
149
+ cartoon_video_path = wb_cartoonizer.process_video(modified_video_path, output_frame_rate)
150
+ else:
151
+ data_uri = upload_blob("processed_videos_cartoonize", modified_video_path, filename, content_type='video/mp4', algo_unique_key='cartoonizeinput')
152
+ response = api_request(data_uri)
153
+ # Delete the processed video from Cloud storage
154
+ delete_blob("processed_videos_cartoonize", filename)
155
+ cartoon_video_path = download_video('cartoonized_videos', os.path.basename(response['output_uri']), os.path.join(app.config['UPLOAD_FOLDER_VIDEOS'], filename.split(".")[0] + "_cartoon.mp4"))
156
+
157
+ ## Add audio to the cartoonized video
158
+ final_cartoon_video_path = os.path.join(app.config['UPLOAD_FOLDER_VIDEOS'], filename.split(".")[0] + "_cartoon_audio.mp4")
159
+ os.system("ffmpeg -hide_banner -loglevel warning -i '{}' -i '{}' -codec copy -shortest '{}'".format(os.path.abspath(cartoon_video_path), os.path.abspath(audio_file_path), os.path.abspath(final_cartoon_video_path)))
160
+
161
+ # Delete the videos from local disk
162
+ os.system("rm {} {} {} {}".format(original_video_path, modified_video_path, audio_file_path, cartoon_video_path))
163
+
164
+ return render_template("index_cartoonized.html", cartoonized_video=final_cartoon_video_path)
165
+
166
+ except Exception:
167
+ print(traceback.print_exc())
168
+ flash("Our server hiccuped :/ Please upload another file! :)")
169
+ return render_template("index_cartoonized.html")
170
+ else:
171
+ return render_template("index_cartoonized.html")
172
+
173
+ if __name__ == "__main__":
174
+ # Commemnt the below line to run the Appication on Google Colab using ngrok
175
+ if opts['colab-mode']:
176
+ app.run()
177
+ else:
178
+ app.run(debug=False, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
config.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ run_local: true #Set this to true if you are running locally, false if you have configured the Google buckets and algorithmia code.
3
+ gpu: true #Set this to true if you want to use the GPU
4
+ trim-video: true #Set this to false if you want to process full video
5
+ trim-video-length: 15 #Max number of seconds you want to trim the video from start
6
+ original_frame_rate: false #If False output_frame_rate will be used else original video detected frame rate will be used, if no metadata found will use output_frame_rate
7
+ output_frame_rate: '24/1' #Set the output frame rate, if original resolution
8
+ colab-mode: false #Set true if you are executing in colab mode
9
+ original_resolution: false # Set to true if you don't want to resize the original video
10
+ resize-dim: 720 #The width of the video will be resized to specified number maintaining aspect ratio
gcloud_utils.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Google Cloud Util Functions:
3
+ - Upload to Google Storage Bucket
4
+ - Delete from Google Storage Bucket
5
+ - Generate signed URL
6
+ """
7
+ import os
8
+ import datetime
9
+
10
+ from google.cloud import storage
11
+ from google.cloud.storage.blob import Blob
12
+
13
+ ## Google Storage Client
14
+ client = storage.Client()
15
+
16
+ def upload_blob(bucket_name, source_file_name, destination_blob_name, content_type='', algo_unique_key=''):
17
+ """Uploading File to Google Storage Bucket
18
+
19
+ Args:
20
+ bucket_name (str): Google Storage Bucket Name
21
+ source_file_name (str): Local Absolute Filpath to upload
22
+ destination_blob_name (str): File Name used to store in bucket
23
+ content_type (str, optional): The content type of the file being uploaded
24
+ algo_unique_key (str, optional): [description]. Defaults to ''. Algorithmia Data Source Bucket Unique Key
25
+
26
+ Returns:
27
+ [str]: Google Storage Object URI, if algorithmia key is given the same is modified.
28
+ """
29
+
30
+ bucket = client.get_bucket(bucket_name)
31
+ blob = bucket.blob(destination_blob_name)
32
+ blob.upload_from_filename(source_file_name, content_type=content_type)
33
+
34
+ data_uri = blob.self_link
35
+
36
+ if algo_unique_key!="":
37
+ return os.path.join("gs+{}://{}".format(algo_unique_key, bucket_name), data_uri.split("/")[-1])
38
+
39
+ return os.path.join("gs://{}".format(bucket_name), data_uri.split("/")[-1])
40
+
41
+ def delete_blob(bucket_name, blob_name):
42
+ """Deletes a blob from the bucket."""
43
+ # bucket_name = "your-bucket-name"
44
+ # blob_name = "your-object-name"
45
+
46
+ bucket = client.bucket(bucket_name)
47
+ blob = bucket.blob(blob_name)
48
+ blob.delete()
49
+
50
+ print("Blob {} deleted.".format(blob_name))
51
+
52
+ def download_video(bucket_name, filename, output_filename):
53
+ bucket = client.get_bucket(bucket_name)
54
+ # Create a blob object from the filepath
55
+ blob = bucket.blob(filename)
56
+ # Download the file to a destination
57
+ blob.download_to_filename(output_filename)
58
+
59
+ return output_filename
60
+
61
+ def generate_signed_url(output_uri):
62
+ expiration_time = datetime.timedelta(minutes=5)
63
+
64
+ blob = Blob.from_string(output_uri, client=client)
65
+
66
+ signed_url = blob.generate_signed_url(expiration=expiration_time, version='v4', response_disposition='attachment')
67
+
68
+ return signed_url
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Flask==1.0.2
2
+ gunicorn==20.0.4
3
+ Pillow==6.2.0
4
+ opencv_python==4.2.0.34
5
+ tensorflow==2.1.0
6
+ google-cloud-storage==1.29.0
7
+ algorithmia==1.3.0
8
+ scikit-video==1.1.11
9
+ tf_slim==1.1.0
10
+ PyYaml==5.3.1
11
+ flask-ngrok
static/cartoonized_images/folder.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ when the days are cold
2
+ and the cards all fold
3
+ and the saints we see are made of gold!
static/sample_images/algorithmia.jpeg ADDED
static/sample_images/cake.jpeg ADDED
static/sample_images/cake_cartoonized.jpeg ADDED
static/sample_images/emma.jpg ADDED
static/sample_images/emma2.jpg ADDED
static/sample_images/emma2_cartoonized.jpg ADDED
static/sample_images/emma3.jpg ADDED
static/sample_images/emma3_cartoonized.jpg ADDED
static/sample_images/emma_cartoonized.jpg ADDED
static/sample_images/spice.jpeg ADDED
static/sample_images/spice2.jpeg ADDED
static/sample_images/spice2_cartoonized.jpeg ADDED
static/sample_images/spice_cartoonized.jpeg ADDED
static/sample_images/tenor.gif ADDED
static/sample_images/twitter_image.png ADDED

Git LFS Details

  • SHA256: f46c06d7c8874904f4cb205b755a7e7bc2fe25513984ee76c91d5df1380dfac6
  • Pointer size: 132 Bytes
  • Size of remote file: 1.96 MB
static/upload.js ADDED
File without changes
static/uploaded_videos/folder_required.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Required for purposes of github.
templates/index_cartoonized.html ADDED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <!-- Global site tag (gtag.js) - Google Analytics -->
5
+ <script async src="https://www.googletagmanager.com/gtag/js?id=UA-173468417-1"></script>
6
+ <script>
7
+ window.dataLayer = window.dataLayer || [];
8
+ function gtag(){dataLayer.push(arguments);}
9
+ gtag('js', new Date());
10
+
11
+ gtag('config', 'UA-173468417-1');
12
+ </script>
13
+
14
+ <meta charset="utf-8" />
15
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
16
+
17
+ <meta name="twitter:card" content="summary_large_image">
18
+ <meta name="twitter:site" content="@Niraj_pandkar">
19
+ <meta name="twitter:title" content="Cartoonized your world!">
20
+ <meta name="twitter:description" content="Want to see your cartoonized self? You can try image or video.">
21
+ <meta name="twitter:creator" content="@Niraj_pandkar">
22
+ <meta name="twitter:image" content="static/sample_images/twitter_image.png">
23
+ <meta name="twitter:domain" content="https://cartoonize-lkqov62dia-de.a.run.app/cartoonize">
24
+
25
+ <title>Cartoonizer</title>
26
+ <meta name="viewport" content="width=device-width, initial-scale=1">
27
+
28
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.3.3/dist/semantic.min.css">
29
+ <script
30
+ src="https://code.jquery.com/jquery-3.1.1.min.js"
31
+ integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
32
+ crossorigin="anonymous">
33
+ </script>
34
+ <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.3.3/dist/semantic.min.js"></script>
35
+ <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
36
+ <style>
37
+ html {
38
+ box-sizing: border-box;
39
+ }
40
+ *, *:before, *:after {
41
+ box-sizing: inherit;
42
+ }
43
+ body{
44
+ background-color: whitesmoke;
45
+ }
46
+
47
+ iframe[src*=youtube] {
48
+ display: block;
49
+ margin: 0 auto;
50
+ max-width: 100%;
51
+ padding-bottom: 10px;
52
+ }
53
+ </style>
54
+ </head>
55
+
56
+ <body>
57
+ <div id="loader" class="ui disabled dimmer">
58
+ <div class="ui text loader">Preparing your cartoon! May take an extra few seconds for video :)</div>
59
+ </div>
60
+
61
+
62
+ <div class='ui padded centered grid'>
63
+ <!-- Messaging system -->
64
+ <div class="row">
65
+ <div class="center aligned column">
66
+ {% with messages = get_flashed_messages(with_categories=true) %}
67
+ {% if messages %}
68
+ <div style="height:10%; display:flex; align-items: center; justify-content: center">
69
+ {% for category, message in messages %}
70
+ {% if category == error%}
71
+ <h3 style="color:red">{{ message }}</h3>
72
+ {% else %}
73
+ <h3 style="color:green">{{ message }}</h3>
74
+ {% endif %}
75
+ {% endfor %}
76
+ </div>
77
+ {% endif %}
78
+ {% endwith %}
79
+ </div>
80
+ </div>
81
+
82
+
83
+ <!-- Heading of the page -->
84
+ <div class="row">
85
+ <div class='center aligned column'>
86
+ <h1>Cartoonize your world!</h1>
87
+ </div>
88
+ </div>
89
+
90
+ <!-- Submission form -->
91
+ <div class="row">
92
+ <div class='center aligned column'>
93
+ <form id='formsubmit' method="post" action="cartoonize" enctype = "multipart/form-data">
94
+
95
+ <div class="ui buttons">
96
+ <div id='uploadimage' class="ui button" style="align-items: center;">
97
+ <i class="image icon"></i>
98
+ Image
99
+ </div>
100
+ <div class="or"></div>
101
+ <div id='uploadvideo' class="ui button" style="align-items: center;">
102
+ <i class="video icon"></i>
103
+ Video
104
+ <span style="font-size: 10px;">(Max 30MB)</span>
105
+ </div>
106
+ </div>
107
+
108
+ <input type='file' id='hiddeninputfile' accept="image/*" name = 'image' style="display: none"/>
109
+ <input type="file" id="hiddeninputvideo" accept="video/*" name = 'video' style="display: none">
110
+ <!-- <input id='submitbutton' class='ui button' type='submit'/> -->
111
+ </form>
112
+ </div>
113
+ </div>
114
+ {%if cartoonized_image or cartoonized_video%}
115
+ <div class="row">
116
+ <div class="column">
117
+ <!-- Nested grid -->
118
+ <div class="ui centered grid">
119
+ <div class="row">
120
+ <div class="center aligned column">
121
+ {%if cartoonized_image%}
122
+ <div class="ui centered card">
123
+ <div class="image">
124
+ <img src="{{ cartoonized_image }}">
125
+ </div>
126
+ </div>
127
+ {%endif%}
128
+
129
+ {%if cartoonized_video%}
130
+ <video id="player" width="320" height="240" controls>
131
+ <source type="video/mp4" src="{{cartoonized_video}}">
132
+ </video>
133
+ {%endif%}
134
+ </div>
135
+ </div>
136
+ <div class="row">
137
+ {%if cartoonized_video%}
138
+ <a href={{cartoonized_video}} download>
139
+
140
+ <button class="ui primary button">
141
+ <i class="download icon"></i>
142
+ Download
143
+ </button>
144
+ </a>
145
+ {%endif%}
146
+ {%if cartoonized_image%}
147
+ <a href={{cartoonized_image}} download>
148
+ <button class="ui primary button">
149
+ <i class="download icon"></i>
150
+ Download
151
+ </button><br>
152
+ (Valid for 5 minutes only)
153
+ </a>
154
+ {%endif%}
155
+
156
+ </div>
157
+ <div class="row">
158
+ <div class="ui stackable three column grid">
159
+ <div class="three column row">
160
+ <div class="center aligned column">
161
+ <a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-text="Check your cartoonized version using the link below!" data-url="https://bit.ly/2CjaaJs" data-hashtags="cartoon" data-show-count="false" data-size="large">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
162
+ </div>
163
+
164
+ <div class="center aligned column">
165
+ <a href="https://api.whatsapp.com/send?text=Try%20this%20awesome%20AI%20cartoonizer%20using%20-%20https%3A%2F%2Fbit.ly%2F2CjaaJs" target="_blank">
166
+ <button class="mini ui green button">
167
+ <i class="whatsapp icon"></i>Share
168
+ </button>
169
+ </a>
170
+ </div>
171
+ <div class="center aligned column"">
172
+ <iframe src="https://www.facebook.com/plugins/share_button.php?href=https%3A%2F%2Fbit.ly%2F2CjaaJs&layout=button&size=large&width=77&height=28&appId" width="77" height="28" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>
173
+ </div>
174
+ </div>
175
+
176
+ </div>
177
+ </div>
178
+
179
+ </div>
180
+ </div>
181
+ </div>
182
+ {%endif%}
183
+
184
+ <div class="ui divider"></div>
185
+ <!-- Sample Images -->
186
+ <div class="row">
187
+ <!-- <div class="ui stackable grid">
188
+ <div class="five wide column">
189
+ <img class="ui medium centered image" src="/static/sample_images/emma2.jpg">
190
+ </div>
191
+ <div class="five wide column">
192
+ <img class="ui medium centered image" src="/static/sample_images/emma2_cartoonized.jpg">
193
+ </div>
194
+ </div> -->
195
+ <div class="five wide column">
196
+ <img class="ui medium centered image" src="/static/sample_images/emma2.jpg">
197
+ </div>
198
+ <div class="five wide column">
199
+ <img class="ui medium centered image" src="/static/sample_images/emma2_cartoonized.jpg">
200
+ </div>
201
+ </div>
202
+ <div class="row">
203
+ <div class="five wide column">
204
+ <img class="ui medium centered image" src="/static/sample_images/spice.jpeg">
205
+ </div>
206
+ <div class="five wide column">
207
+ <img class="ui medium centered image" src="/static/sample_images/spice_cartoonized.jpeg">
208
+ </div>
209
+ </div>
210
+ <div class="row">
211
+ <div class="five wide column">
212
+ <img class="ui medium centered image" src="/static/sample_images/cake.jpeg">
213
+ </div>
214
+ <div class="five wide column">
215
+ <img class="ui medium centered image" src="/static/sample_images/cake_cartoonized.jpeg">
216
+ </div>
217
+ </div>
218
+ <div class="row">
219
+ <div class="center aligned column">
220
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/omenajmDBm8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
221
+ </div>
222
+ </div>
223
+ <div class="row">
224
+ <div class="center aligned column">
225
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/GqduSLcmhto" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
226
+ </div>
227
+ </div>
228
+ <div class="row">
229
+ <div class="center aligned column">
230
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/0Y29Z7-urqA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
231
+ </div>
232
+ </div>
233
+ <!-- <div class="row">
234
+ <div class="five wide column">
235
+ <img src="/static/sample_images/tenor.gif">
236
+ </div>
237
+ <div class="five wide column">
238
+ <img src="/static/sample_images/tenor.gif">
239
+ </div>
240
+ </div> -->
241
+ <!-- FAQs -->
242
+ <div class="row">
243
+ <div class="column" style="padding-right: 25px; padding-left: 25px;">
244
+ <div class="ui centered styled accordion" style="margin:auto;">
245
+ <div class="title">
246
+ <i class="dropdown icon"></i>
247
+ Which paper is this demo based on?
248
+ </div>
249
+ <div class="content">
250
+ <p class="transition hidden">Due credits to the incredible paper - <a target="_blank" href="http://openaccess.thecvf.com/content_CVPR_2020/papers/Wang_Learning_to_Cartoonize_Using_White-Box_Cartoon_Representations_CVPR_2020_paper.pdf">Learning to Cartoonize Using White-box Cartoon Representations</a>
251
+ <p>Official implementation of the paper by the author - <a target="_blank" href="https://github.com/SystemErrorWang/White-box-Cartoonization">Github Link</a></p>
252
+ </div>
253
+
254
+ <div class="title">
255
+ <i class="dropdown icon"></i>
256
+ What are the restrictions of video processing and image processing?
257
+ </div>
258
+ <div class="content">
259
+ <ul class="ui list">
260
+ <li>We are currently processing only upto <b>10 second</b> videos, if you happened to upload a video greater than 10 seconds, only <b>first 10 seconds</b> will be considered.</li>
261
+ <li>Video File Size Limitation: <b>30MB</b></li>
262
+ <li>Image File Formats Supported: <b>jpeg, png</b></li>
263
+ <li>Video File Formats Supported: <b>mp4, webm, avi, mkv</b></li>
264
+ <li>GIF/TIFF Images are not supported.</li>
265
+ </ul>
266
+ </div>
267
+
268
+ <div class="title">
269
+ <i class="dropdown icon"></i>
270
+ Is my data stored on your servers?
271
+ </div>
272
+ <div class="content">
273
+ Your data is deleted in the pipeline as you run the demo.
274
+ </div>
275
+
276
+ <div class="title">
277
+ <i class="dropdown icon"></i>
278
+ Where could be Cartoonizer used?
279
+ </div>
280
+ <div class="content">
281
+ <p>Some of the areas where we think it could be applied to -</p>
282
+ <ul class="ui list">
283
+ <li>Churn out <b>quick prototypes</b> or sprites for animes, cartoons and games</li>
284
+ <li>Since it subdues facial features and information in general, it can be used to generate <b>minimal art</b></li>
285
+ <li>Games can import short <b>cut scenes</b> very easily <b>without using motion-capture</b></li>
286
+ <li>Can be modelled as an assistant to graphic designers or animators.</li>
287
+ </ul>
288
+ </div>
289
+
290
+
291
+ <div class="title">
292
+ <i class="dropdown icon"></i>
293
+ Video and Image attributes?
294
+ </div>
295
+ <div class="content">
296
+ <p>Cake and food assortment photos are OC (Original Content). Other than that -</p>
297
+ <ul class="ui list">
298
+ <li>Emma Watson Image: <a target="_blank" href="https://static.independent.co.uk/s3fs-public/thumbnails/image/2019/12/20/15/emma-watson-little-women.jpg?w968">Independent UK</a></li>
299
+ <li>Rick Astley - Never Gonna Give You Up (Original Video): <a target="_blank" href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">YouTube Link</a></li>
300
+ <li>Avengers (Original Video): <a target="_blank" href="https://www.youtube.com/watch?v=u7JO1RCE3Zk">YouTube Link</a></li>
301
+ <li>Joey (Original Video): <a target="_blank" href="https://www.youtube.com/watch?v=tHuQiUP-kyQ">YouTube Link</a></li>
302
+ </ul>
303
+ </div>
304
+
305
+ <div class="title">
306
+ <i class="dropdown icon"></i>
307
+ I want to know more about cartoonization using AI.
308
+ </div>
309
+ <div class="content">
310
+ <p>The <a href="">author</a> of the above mentioned paper can probably indulge you in some detailed resoursces. Other than that here are some we found - </p>
311
+ <ul class="ui list">
312
+ <li>CartoonGAN
313
+ <ul>
314
+ <li><a target="_blank" href="https://openaccess.thecvf.com/content_cvpr_2018/papers/Chen_CartoonGAN_Generative_Adversarial_CVPR_2018_paper.pdf">Paper</a></li>
315
+ <li><a target="_blank" href="https://github.com/mnicnc404/CartoonGan-tensorflow">Github Link</a></li>
316
+ </ul>
317
+ </li>
318
+ <li>AnimeGAN
319
+ <ul>
320
+ <li><a target="_blank" href="https://link.springer.com/chapter/10.1007/978-981-15-5577-0_18">Paper</a></li>
321
+ <li><a target="_blank" href="https://github.com/TachibanaYoshino/AnimeGAN">Github Link</a></li>
322
+ </ul>
323
+ </li>
324
+ </ul>
325
+ </div>
326
+
327
+ <div class="title">
328
+ <i class="dropdown icon"></i>
329
+ Why did we make this demo?
330
+ </div>
331
+ <div class="content">
332
+ <p>Honestly we thought this was a cool application of GAN but didn't find any demo available.
333
+ Our friends wanted to try it so we made a quick demo for images; which then later got extended to videos.</p>
334
+ <p>Also we wanted to learn the deployment architecture which would allow us to serve such power hungry inference in the least money hogging method possible. (Blog post coming soon!)</p>
335
+ </div>
336
+
337
+ <div class="title">
338
+ <i class="dropdown icon"></i>
339
+ Help us pay the bills?
340
+ </div>
341
+ <div class="content">
342
+ If you liked our demo and want to support us, please donate - <a href="https://www.paypal.me/tjdevworks">Paypal Link</a>
343
+ </div>
344
+
345
+ <div class="title">
346
+ <i class="dropdown icon"></i>
347
+ Do you want to share your feedback?
348
+ </div>
349
+ <div class="content">
350
+ <iframe src="https://docs.google.com/forms/d/e/1FAIpQLSevnAJeRc0JvoXAY_wNOu4jKb5tM3PKmwZMzH5tDnxVr1bXzQ/viewform?embedded=true" width="550" height="605" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
351
+ </div>
352
+
353
+
354
+
355
+
356
+ <!-- <div class="title">
357
+ <i class="dropdown icon"></i>
358
+ What is the deployment architecture of this project?
359
+ </div>
360
+ <div class="content">
361
+ <p>This is a Flask app which resides on a Cloud Run instance with Cloud Storage integration. We've leveraged Algorithmia's community cloud AI layer for our inference.</p>
362
+ <!-- <p><a href="https://github.com/nirajpandkar/x-ize/tree/wb_cartoonizer">Github Link</a></p> -->
363
+ <!-- </div> -->
364
+ </div>
365
+ </div>
366
+ </div>
367
+
368
+ <div class="row">
369
+ <div class="center aligned column">
370
+ <h3><i class="copyright outline icon"></i> 2020 Cartoonizer</h3>
371
+ <h3>Made with <i class="heart icon"></i> by <a target="_blank" href="https://twitter.com/Niraj_pandkar">Niraj</a> and <a target="_blank" href="https://twitter.com/tjdevWorks">Tejas</a></h3>
372
+ </div>
373
+
374
+ </div>
375
+ <!-- <div class="row">
376
+ <h3>Made with <i class="heart icon"></i> by <a href="https://www.linkedin.com/in/nirajpandkar/">Niraj</a> and <a href="https://www.linkedin.com/in/tejas-mahajan-21175a118/">Tejas</a></h3>
377
+ </div> -->
378
+
379
+ </div>
380
+
381
+
382
+ <script>
383
+ $('.ui.accordion')
384
+ .accordion()
385
+ ;
386
+ $("#uploadimage").on("click", function() {
387
+ $('#hiddeninputfile').click();
388
+ });
389
+
390
+ $("#uploadvideo").on("click", function() {
391
+ $('#hiddeninputvideo').click();
392
+ });
393
+
394
+ document.getElementById("hiddeninputfile").onchange = function() {
395
+ $('#loader').removeClass('disabled').addClass('active');
396
+ document.getElementById("formsubmit").submit();
397
+
398
+ };
399
+ document.getElementById("hiddeninputvideo").onchange = function() {
400
+ const fi = document.getElementById('hiddeninputvideo');
401
+ // Check if any file is selected.
402
+ if (fi.files.length > 0) {
403
+ for (const i = 0; i <= fi.files.length - 1; i++) {
404
+
405
+ const fsize = fi.files.item(i).size;
406
+ const file = Math.round((fsize / 1024));
407
+ // The size of the file.
408
+ //Change the max_file_size as per your need
409
+ const max_file_size = 30720;
410
+ if (file >= max_file_size) {
411
+ alert(
412
+ "File too Big, please select a file less than 30mb (10 sec at 1080p or 5 sec at 4k)");
413
+ } else {
414
+ $('#loader').removeClass('disabled').addClass('active');
415
+ document.getElementById("formsubmit").submit();
416
+ }
417
+ }
418
+ }
419
+
420
+
421
+ };
422
+ var recorder = document.getElementById('recorder');
423
+ </script>
424
+ </body>
425
+ </html>
video_api.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Algorithmia
2
+
3
+ with open("algo.txt", "r") as infile:
4
+ client_key = infile.read()
5
+
6
+ client = Algorithmia.client(client_key)
7
+ algo = client.algo('tjdevworks/cartoonizer/2.2.2')
8
+ algo.set_options(timeout=300)
9
+
10
+ def api_request(input_file_uri):
11
+ # API call for cartoonization.
12
+ input = {"data_uri": input_file_uri,
13
+ "data_type": 1,
14
+ "datastore": ""
15
+ }
16
+
17
+ response = algo.pipe(input).result
18
+
19
+ return response
white_box_cartoonizer/cartoonize.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Internal code snippets were obtained from https://github.com/SystemErrorWang/White-box-Cartoonization/
3
+
4
+ For it to work tensorflow version 2.x changes were obtained from https://github.com/steubk/White-box-Cartoonization
5
+ """
6
+ import os
7
+ import uuid
8
+ import time
9
+ import subprocess
10
+ import sys
11
+
12
+ import cv2
13
+ import numpy as np
14
+ import skvideo.io
15
+ try:
16
+ import tensorflow.compat.v1 as tf
17
+ except ImportError:
18
+ import tensorflow as tf
19
+
20
+ import network
21
+ import guided_filter
22
+
23
+ class WB_Cartoonize:
24
+ def __init__(self, weights_dir, gpu):
25
+ if not os.path.exists(weights_dir):
26
+ raise FileNotFoundError("Weights Directory not found, check path")
27
+ self.load_model(weights_dir, gpu)
28
+ print("Weights successfully loaded")
29
+
30
+ def resize_crop(self, image):
31
+ h, w, c = np.shape(image)
32
+ if min(h, w) > 720:
33
+ if h > w:
34
+ h, w = int(720*h/w), 720
35
+ else:
36
+ h, w = 720, int(720*w/h)
37
+ image = cv2.resize(image, (w, h),
38
+ interpolation=cv2.INTER_AREA)
39
+ h, w = (h//8)*8, (w//8)*8
40
+ image = image[:h, :w, :]
41
+ return image
42
+
43
+ def load_model(self, weights_dir, gpu):
44
+ try:
45
+ tf.disable_eager_execution()
46
+ except:
47
+ None
48
+
49
+ tf.reset_default_graph()
50
+
51
+
52
+ self.input_photo = tf.placeholder(tf.float32, [1, None, None, 3], name='input_image')
53
+ network_out = network.unet_generator(self.input_photo)
54
+ self.final_out = guided_filter.guided_filter(self.input_photo, network_out, r=1, eps=5e-3)
55
+
56
+ all_vars = tf.trainable_variables()
57
+ gene_vars = [var for var in all_vars if 'generator' in var.name]
58
+ saver = tf.train.Saver(var_list=gene_vars)
59
+
60
+ if gpu:
61
+ gpu_options = tf.GPUOptions(allow_growth=True)
62
+ device_count = {'GPU':1}
63
+ else:
64
+ gpu_options = None
65
+ device_count = {'GPU':0}
66
+
67
+ config = tf.ConfigProto(gpu_options=gpu_options, device_count=device_count)
68
+
69
+ self.sess = tf.Session(config=config)
70
+
71
+ self.sess.run(tf.global_variables_initializer())
72
+ saver.restore(self.sess, tf.train.latest_checkpoint(weights_dir))
73
+
74
+ def infer(self, image):
75
+ image = self.resize_crop(image)
76
+ batch_image = image.astype(np.float32)/127.5 - 1
77
+ batch_image = np.expand_dims(batch_image, axis=0)
78
+
79
+ ## Session Run
80
+ output = self.sess.run(self.final_out, feed_dict={self.input_photo: batch_image})
81
+
82
+ ## Post Process
83
+ output = (np.squeeze(output)+1)*127.5
84
+ output = np.clip(output, 0, 255).astype(np.uint8)
85
+
86
+ return output
87
+
88
+ def process_video(self, fname, frame_rate):
89
+ ## Capture video using opencv
90
+ cap = cv2.VideoCapture(fname)
91
+
92
+ target_size = (int(cap.get(3)),int(cap.get(4)))
93
+ output_fname = os.path.abspath('{}/{}-{}.mp4'.format(fname.replace(os.path.basename(fname), ''),str(uuid.uuid4())[:7],os.path.basename(fname).split('.')[0]))
94
+
95
+ out = skvideo.io.FFmpegWriter(output_fname, inputdict={'-r':frame_rate}, outputdict={'-r':frame_rate})
96
+
97
+ while True:
98
+ ret, frame = cap.read()
99
+
100
+ if ret:
101
+
102
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
103
+
104
+ frame = self.infer(frame)
105
+
106
+ frame = cv2.resize(frame, target_size)
107
+
108
+ out.writeFrame(frame)
109
+
110
+ else:
111
+ break
112
+ cap.release()
113
+ out.close()
114
+
115
+ final_name = '{}final_{}'.format(fname.replace(os.path.basename(fname), ''), os.path.basename(output_fname))
116
+
117
+ p = subprocess.Popen(['ffmpeg','-i','{}'.format(output_fname), "-pix_fmt", "yuv420p", final_name])
118
+ p.communicate()
119
+ p.wait()
120
+
121
+ os.system("rm "+output_fname)
122
+
123
+ return final_name
124
+
125
+ if __name__ == '__main__':
126
+ gpu = len(sys.argv) < 2 or sys.argv[1] != '--cpu'
127
+ wbc = WB_Cartoonize(os.path.abspath('white_box_cartoonizer/saved_models'), gpu)
128
+ img = cv2.imread('white_box_cartoonizer/test.jpg')
129
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
130
+ cartoon_image = wbc.infer(img)
131
+ import matplotlib.pyplot as plt
132
+ plt.imshow(cartoon_image)
133
+ plt.show()
white_box_cartoonizer/guided_filter.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Code copyrights are with: https://github.com/SystemErrorWang/White-box-Cartoonization/
3
+
4
+ To adapt the code with tensorflow v2 changes obtained from: https://github.com/steubk/White-box-Cartoonization
5
+ """
6
+ try:
7
+ import tensorflow.compat.v1 as tf
8
+ except ImportError:
9
+ import tensorflow as tf
10
+
11
+ import numpy as np
12
+
13
+
14
+ def tf_box_filter(x, r):
15
+ k_size = int(2*r+1)
16
+ ch = x.get_shape().as_list()[-1]
17
+ weight = 1/(k_size**2)
18
+ box_kernel = weight*np.ones((k_size, k_size, ch, 1))
19
+ box_kernel = np.array(box_kernel).astype(np.float32)
20
+ output = tf.nn.depthwise_conv2d(x, box_kernel, [1, 1, 1, 1], 'SAME')
21
+ return output
22
+
23
+
24
+
25
+ def guided_filter(x, y, r, eps=1e-2):
26
+
27
+ x_shape = tf.shape(x)
28
+ #y_shape = tf.shape(y)
29
+
30
+ N = tf_box_filter(tf.ones((1, x_shape[1], x_shape[2], 1), dtype=x.dtype), r)
31
+
32
+ mean_x = tf_box_filter(x, r) / N
33
+ mean_y = tf_box_filter(y, r) / N
34
+ cov_xy = tf_box_filter(x * y, r) / N - mean_x * mean_y
35
+ var_x = tf_box_filter(x * x, r) / N - mean_x * mean_x
36
+
37
+ A = cov_xy / (var_x + eps)
38
+ b = mean_y - A * mean_x
39
+
40
+ mean_A = tf_box_filter(A, r) / N
41
+ mean_b = tf_box_filter(b, r) / N
42
+
43
+ output = tf.add(mean_A * x, mean_b, name='final_add')
44
+
45
+ return output
46
+
47
+
48
+
49
+ def fast_guided_filter(lr_x, lr_y, hr_x, r=1, eps=1e-8):
50
+
51
+ #assert lr_x.shape.ndims == 4 and lr_y.shape.ndims == 4 and hr_x.shape.ndims == 4
52
+
53
+ lr_x_shape = tf.shape(lr_x)
54
+ #lr_y_shape = tf.shape(lr_y)
55
+ hr_x_shape = tf.shape(hr_x)
56
+
57
+ N = tf_box_filter(tf.ones((1, lr_x_shape[1], lr_x_shape[2], 1), dtype=lr_x.dtype), r)
58
+
59
+ mean_x = tf_box_filter(lr_x, r) / N
60
+ mean_y = tf_box_filter(lr_y, r) / N
61
+ cov_xy = tf_box_filter(lr_x * lr_y, r) / N - mean_x * mean_y
62
+ var_x = tf_box_filter(lr_x * lr_x, r) / N - mean_x * mean_x
63
+
64
+ A = cov_xy / (var_x + eps)
65
+ b = mean_y - A * mean_x
66
+
67
+ mean_A = tf.image.resize_images(A, hr_x_shape[1: 3])
68
+ mean_b = tf.image.resize_images(b, hr_x_shape[1: 3])
69
+
70
+ output = mean_A * hr_x + mean_b
71
+
72
+ return output
73
+
74
+
75
+ if __name__ == '__main__':
76
+ import cv2
77
+ from tqdm import tqdm
78
+
79
+ input_photo = tf.placeholder(tf.float32, [1, None, None, 3])
80
+ #input_superpixel = tf.placeholder(tf.float32, [16, 256, 256, 3])
81
+ output = guided_filter(input_photo, input_photo, 5, eps=1)
82
+ image = cv2.imread('output_figure1/cartoon2.jpg')
83
+ image = image/127.5 - 1
84
+ image = np.expand_dims(image, axis=0)
85
+
86
+ config = tf.ConfigProto()
87
+ config.gpu_options.allow_growth = True
88
+ sess = tf.Session(config=config)
89
+ sess.run(tf.global_variables_initializer())
90
+
91
+ out = sess.run(output, feed_dict={input_photo: image})
92
+ out = (np.squeeze(out)+1)*127.5
93
+ out = np.clip(out, 0, 255).astype(np.uint8)
94
+ cv2.imwrite('output_figure1/cartoon2_filter.jpg', out)
white_box_cartoonizer/network.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Code copyrights are with: https://github.com/SystemErrorWang/White-box-Cartoonization/
3
+
4
+ To adapt the code with tensorflow v2 changes obtained from: https://github.com/steubk/White-box-Cartoonization
5
+ """
6
+ try:
7
+ import tensorflow.compat.v1 as tf
8
+ import tf_slim as slim
9
+ except ImportError:
10
+ import tensorflow as tf
11
+ import tensorflow.contrib.slim as slim
12
+
13
+ import numpy as np
14
+
15
+
16
+
17
+ def resblock(inputs, out_channel=32, name='resblock'):
18
+
19
+ with tf.variable_scope(name):
20
+
21
+ x = slim.convolution2d(inputs, out_channel, [3, 3],
22
+ activation_fn=None, scope='conv1')
23
+ x = tf.nn.leaky_relu(x)
24
+ x = slim.convolution2d(x, out_channel, [3, 3],
25
+ activation_fn=None, scope='conv2')
26
+
27
+ return x + inputs
28
+
29
+
30
+
31
+
32
+ def unet_generator(inputs, channel=32, num_blocks=4, name='generator', reuse=False):
33
+ with tf.variable_scope(name, reuse=reuse):
34
+
35
+ x0 = slim.convolution2d(inputs, channel, [7, 7], activation_fn=None)
36
+ x0 = tf.nn.leaky_relu(x0)
37
+
38
+ x1 = slim.convolution2d(x0, channel, [3, 3], stride=2, activation_fn=None)
39
+ x1 = tf.nn.leaky_relu(x1)
40
+ x1 = slim.convolution2d(x1, channel*2, [3, 3], activation_fn=None)
41
+ x1 = tf.nn.leaky_relu(x1)
42
+
43
+ x2 = slim.convolution2d(x1, channel*2, [3, 3], stride=2, activation_fn=None)
44
+ x2 = tf.nn.leaky_relu(x2)
45
+ x2 = slim.convolution2d(x2, channel*4, [3, 3], activation_fn=None)
46
+ x2 = tf.nn.leaky_relu(x2)
47
+
48
+ for idx in range(num_blocks):
49
+ x2 = resblock(x2, out_channel=channel*4, name='block_{}'.format(idx))
50
+
51
+ x2 = slim.convolution2d(x2, channel*2, [3, 3], activation_fn=None)
52
+ x2 = tf.nn.leaky_relu(x2)
53
+
54
+ h1, w1 = tf.shape(x2)[1], tf.shape(x2)[2]
55
+ x3 = tf.image.resize_bilinear(x2, (h1*2, w1*2))
56
+ x3 = slim.convolution2d(x3+x1, channel*2, [3, 3], activation_fn=None)
57
+ x3 = tf.nn.leaky_relu(x3)
58
+ x3 = slim.convolution2d(x3, channel, [3, 3], activation_fn=None)
59
+ x3 = tf.nn.leaky_relu(x3)
60
+
61
+ h2, w2 = tf.shape(x3)[1], tf.shape(x3)[2]
62
+ x4 = tf.image.resize_bilinear(x3, (h2*2, w2*2))
63
+ x4 = slim.convolution2d(x4+x0, channel, [3, 3], activation_fn=None)
64
+ x4 = tf.nn.leaky_relu(x4)
65
+ x4 = slim.convolution2d(x4, 3, [7, 7], activation_fn=None)
66
+
67
+ return x4
68
+
69
+ if __name__ == '__main__':
70
+
71
+
72
+ pass
white_box_cartoonizer/saved_models/checkpoint ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ model_checkpoint_path: "model-33999"
2
+ all_model_checkpoint_paths: "model-33999"
3
+ all_model_checkpoint_paths: "model-37499"
white_box_cartoonizer/saved_models/model-33999.data-00000-of-00001 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e2df1a5aa86faa4f979720bfc2436f79333a480876f8d6790b7671cf50fe75b
3
+ size 5868300
white_box_cartoonizer/saved_models/model-33999.index ADDED
Binary file (1.56 kB). View file
 
white_box_cartoonizer/test.jpg ADDED