├── .gitignore ├── LICENSE ├── README.md ├── data ├── 91-image │ ├── t1.bmp │ ├── t10.bmp │ ├── t11.bmp │ ├── t12.bmp │ ├── t13.bmp │ ├── t14.bmp │ ├── t15.bmp │ ├── t16.bmp │ ├── t17.bmp │ ├── t18.bmp │ ├── t19.bmp │ ├── t2.bmp │ ├── t20.bmp │ ├── t21.bmp │ ├── t22.bmp │ ├── t23.bmp │ ├── t24.bmp │ ├── t25.bmp │ ├── t26.bmp │ ├── t27.bmp │ ├── t28.bmp │ ├── t29.bmp │ ├── t3.bmp │ ├── t30.bmp │ ├── t31.bmp │ ├── t32.bmp │ ├── t33.bmp │ ├── t34.bmp │ ├── t35.bmp │ ├── t36.bmp │ ├── t37.bmp │ ├── t38.bmp │ ├── t39.bmp │ ├── t4.bmp │ ├── t40.bmp │ ├── t42.bmp │ ├── t43.bmp │ ├── t44.bmp │ ├── t45.bmp │ ├── t46.bmp │ ├── t47.bmp │ ├── t48.bmp │ ├── t49.bmp │ ├── t5.bmp │ ├── t50.bmp │ ├── t51.bmp │ ├── t52.bmp │ ├── t53.bmp │ ├── t54.bmp │ ├── t55.bmp │ ├── t56.bmp │ ├── t57.bmp │ ├── t58.bmp │ ├── t59.bmp │ ├── t6.bmp │ ├── t60.bmp │ ├── t61.bmp │ ├── t62.bmp │ ├── t63.bmp │ ├── t64.bmp │ ├── t65.bmp │ ├── t66.bmp │ ├── t7.bmp │ ├── t8.bmp │ ├── t9.bmp │ ├── tt1.bmp │ ├── tt10.bmp │ ├── tt12.bmp │ ├── tt13.bmp │ ├── tt14.bmp │ ├── tt15.bmp │ ├── tt16.bmp │ ├── tt17.bmp │ ├── tt18.bmp │ ├── tt19.bmp │ ├── tt2.bmp │ ├── tt20.bmp │ ├── tt21.bmp │ ├── tt22.bmp │ ├── tt23.bmp │ ├── tt24.bmp │ ├── tt25.bmp │ ├── tt26.bmp │ ├── tt27.bmp │ ├── tt3.bmp │ ├── tt4.bmp │ ├── tt5.bmp │ ├── tt6.bmp │ ├── tt7.bmp │ ├── tt8.bmp │ └── tt9.bmp ├── Set14 │ ├── baboon.bmp │ ├── barbara.bmp │ ├── bridge.bmp │ ├── coastguard.bmp │ ├── comic.bmp │ ├── face.bmp │ ├── flowers.bmp │ ├── foreman.bmp │ ├── lenna.bmp │ ├── man.bmp │ ├── monarch.bmp │ ├── pepper.bmp │ ├── ppt3.bmp │ └── zebra.bmp └── Set5 │ ├── baby_GT.bmp │ ├── bird_GT.bmp │ ├── butterfly_GT.bmp │ ├── head_GT.bmp │ └── woman_GT.bmp ├── experiments ├── bicubic-sc3.json ├── bicubic-sc4.json ├── espcn-example.json ├── espcn-sc3.json ├── espcn-sc4.json ├── fsrcnn-example.json ├── fsrcnn-sc3.json ├── fsrcnn-sc4.json ├── nsfsrcnn-pos0-sc3.json ├── nsfsrcnn-pos0-sc4.json ├── nsfsrcnn-pos1-sc3.json ├── nsfsrcnn-pos1-sc4.json ├── nsfsrcnn-pos2-sc3.json ├── nsfsrcnn-pos2-sc4.json ├── nsfsrcnn-pos3-sc3.json ├── nsfsrcnn-pos3-sc4.json ├── plot.py ├── run.py ├── run_all.py ├── srcnn-9-1-5-sc3.json ├── srcnn-9-1-5-sc4.json ├── srcnn-9-5-5-sc3.json ├── srcnn-9-5-5-sc4.json └── srcnn-example.json ├── install ├── create-env-cpu.sh ├── create-env-gpu.sh ├── env-cpu.yml ├── env-gpu.yml └── install-conda-on-linux.sh ├── setup.py └── toolbox ├── __init__.py ├── data.py ├── experiment.py ├── image.py ├── layers.py ├── metrics.py ├── models.py └── paths.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 The Deep Glasses Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Update on 2018-10-07 2 | 3 | Just find that fast.ai now has a fantastic [lecture on super resolution](http://course18.fast.ai/lessons/lesson14.html). Check it out! 4 | 5 | #### Update on 2018-03-30 6 | 7 | This 2-week course project got more visitors than we expected. Although we have since moved on to other things, with no intention to improve this work, we felt obliged to list some useful resources here for whoever stumbles on this page: 8 | 9 | - [huangzehao/Super-Resolution.Benckmark](https://github.com/huangzehao/Super-Resolution.Benckmark) 10 | - [IvoryCandy/super-resolution](https://github.com/IvoryCandy/super-resolution) 11 | - [LoSealL/VideoSuperResolution](https://github.com/LoSealL/VideoSuperResolution) 12 | - [YapengTian/Single-Image-Super-Resolution](https://github.com/YapengTian/Single-Image-Super-Resolution) 13 | 14 | What follows is the original README: 15 | 16 | # Convolutional Neural Networks for Single Image Super-Resolution 17 | 18 | We have implemented [SRCNN], [FSRCNN] and [ESPCN] in [Keras] with [TensorFlow] backend. The network architectures are implemented in [models.py](toolbox/models.py) and [layers.py](toolbox/layers.py). Our results are described in our [final report](https://github.com/qobilidop/srcnn/releases/download/final/final-report.pdf). The [experiments data](https://github.com/qobilidop/srcnn/releases/download/final/experiments-data.zip) used to get our results are also provided. To reduce the file size, weights files at each epoch are not included in the data file. But the final model file is included and there are enough data to reproduce all the plots in our final report. 19 | 20 | [SRCNN]: https://arxiv.org/abs/1501.00092 21 | [FSRCNN]: https://arxiv.org/abs/1608.00367 22 | [ESPCN]: https://arxiv.org/abs/1609.05158 23 | [Keras]: https://github.com/fchollet/keras 24 | [TensorFlow]: https://github.com/tensorflow/tensorflow 25 | 26 | ## Installation 27 | 28 | A Python package `toolbox` is developed to facilitate our experiments. You need to install it to reproduce our experiments. If the dependencies as defined in [env-gpu.yml](install/env-gpu.yml) or [env-cpu.yml](install/env-cpu.yml) are already satisfied, simply do 29 | 30 | ```bash 31 | pip install -e . 32 | ``` 33 | 34 | to install the package. Otherwise you can create a conda environment `srcnn` for all the dependencies by 35 | 36 | ```bash 37 | conda env create -f install/env-gpu.yml 38 | ``` 39 | 40 | or 41 | 42 | ```bash 43 | conda env create -f install/env-cpu.yml 44 | ``` 45 | 46 | We have also provided scripts to make it easy to set up an environment on a vanilla Ubuntu machine. Simply do 47 | 48 | ```bash 49 | eval "$(curl -fsSL https://raw.githubusercontent.com/qobilidop/srcnn/master/install/create-env-gpu.sh)" 50 | ``` 51 | 52 | or 53 | 54 | ```bash 55 | eval "$(curl -fsSL https://raw.githubusercontent.com/qobilidop/srcnn/master/install/create-env-cpu.sh)" 56 | ``` 57 | 58 | and you'll be in the ~/srcnn directory and the `srcnn` conda environment, ready to run any experiment. 59 | 60 | ## Experiments 61 | 62 | An experiment is configured by a json file in the [experiments](experiments) directory. To run an experiment, `cd` into the experiments directory and do 63 | 64 | ```bash 65 | python run.py {experiment-name}.json 66 | ``` 67 | 68 | You can also do 69 | 70 | ```bash 71 | python run_all.py 72 | ``` 73 | 74 | to run all the experiments at once. But note that it may take a very long time. 75 | 76 | Once some experiments are finished, diagnostic plots can be made by 77 | 78 | ```bash 79 | python plot.py 80 | ``` 81 | 82 | ## Authors 83 | 84 | The Deep Glasses Team :eyeglasses: 85 | * [Zhe An](https://github.com/JasonAn) 86 | * [Bili Dong](https://github.com/qobilidop) 87 | * [Zheng Fang](https://github.com/Catus61) 88 | * [Jiacong Li](https://github.com/jiacong1990) 89 | * [Liyang Xiong](https://github.com/xiongliyang219) 90 | -------------------------------------------------------------------------------- /data/91-image/t1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t1.bmp -------------------------------------------------------------------------------- /data/91-image/t10.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t10.bmp -------------------------------------------------------------------------------- /data/91-image/t11.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t11.bmp -------------------------------------------------------------------------------- /data/91-image/t12.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t12.bmp -------------------------------------------------------------------------------- /data/91-image/t13.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t13.bmp -------------------------------------------------------------------------------- /data/91-image/t14.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t14.bmp -------------------------------------------------------------------------------- /data/91-image/t15.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t15.bmp -------------------------------------------------------------------------------- /data/91-image/t16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t16.bmp -------------------------------------------------------------------------------- /data/91-image/t17.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t17.bmp -------------------------------------------------------------------------------- /data/91-image/t18.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t18.bmp -------------------------------------------------------------------------------- /data/91-image/t19.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t19.bmp -------------------------------------------------------------------------------- /data/91-image/t2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t2.bmp -------------------------------------------------------------------------------- /data/91-image/t20.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t20.bmp -------------------------------------------------------------------------------- /data/91-image/t21.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t21.bmp -------------------------------------------------------------------------------- /data/91-image/t22.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t22.bmp -------------------------------------------------------------------------------- /data/91-image/t23.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t23.bmp -------------------------------------------------------------------------------- /data/91-image/t24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t24.bmp -------------------------------------------------------------------------------- /data/91-image/t25.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t25.bmp -------------------------------------------------------------------------------- /data/91-image/t26.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t26.bmp -------------------------------------------------------------------------------- /data/91-image/t27.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t27.bmp -------------------------------------------------------------------------------- /data/91-image/t28.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t28.bmp -------------------------------------------------------------------------------- /data/91-image/t29.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t29.bmp -------------------------------------------------------------------------------- /data/91-image/t3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t3.bmp -------------------------------------------------------------------------------- /data/91-image/t30.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t30.bmp -------------------------------------------------------------------------------- /data/91-image/t31.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t31.bmp -------------------------------------------------------------------------------- /data/91-image/t32.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t32.bmp -------------------------------------------------------------------------------- /data/91-image/t33.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t33.bmp -------------------------------------------------------------------------------- /data/91-image/t34.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t34.bmp -------------------------------------------------------------------------------- /data/91-image/t35.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t35.bmp -------------------------------------------------------------------------------- /data/91-image/t36.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t36.bmp -------------------------------------------------------------------------------- /data/91-image/t37.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t37.bmp -------------------------------------------------------------------------------- /data/91-image/t38.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t38.bmp -------------------------------------------------------------------------------- /data/91-image/t39.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t39.bmp -------------------------------------------------------------------------------- /data/91-image/t4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t4.bmp -------------------------------------------------------------------------------- /data/91-image/t40.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t40.bmp -------------------------------------------------------------------------------- /data/91-image/t42.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t42.bmp -------------------------------------------------------------------------------- /data/91-image/t43.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t43.bmp -------------------------------------------------------------------------------- /data/91-image/t44.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t44.bmp -------------------------------------------------------------------------------- /data/91-image/t45.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t45.bmp -------------------------------------------------------------------------------- /data/91-image/t46.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t46.bmp -------------------------------------------------------------------------------- /data/91-image/t47.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t47.bmp -------------------------------------------------------------------------------- /data/91-image/t48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t48.bmp -------------------------------------------------------------------------------- /data/91-image/t49.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t49.bmp -------------------------------------------------------------------------------- /data/91-image/t5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t5.bmp -------------------------------------------------------------------------------- /data/91-image/t50.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t50.bmp -------------------------------------------------------------------------------- /data/91-image/t51.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t51.bmp -------------------------------------------------------------------------------- /data/91-image/t52.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t52.bmp -------------------------------------------------------------------------------- /data/91-image/t53.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t53.bmp -------------------------------------------------------------------------------- /data/91-image/t54.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t54.bmp -------------------------------------------------------------------------------- /data/91-image/t55.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t55.bmp -------------------------------------------------------------------------------- /data/91-image/t56.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t56.bmp -------------------------------------------------------------------------------- /data/91-image/t57.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t57.bmp -------------------------------------------------------------------------------- /data/91-image/t58.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t58.bmp -------------------------------------------------------------------------------- /data/91-image/t59.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t59.bmp -------------------------------------------------------------------------------- /data/91-image/t6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t6.bmp -------------------------------------------------------------------------------- /data/91-image/t60.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t60.bmp -------------------------------------------------------------------------------- /data/91-image/t61.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t61.bmp -------------------------------------------------------------------------------- /data/91-image/t62.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t62.bmp -------------------------------------------------------------------------------- /data/91-image/t63.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t63.bmp -------------------------------------------------------------------------------- /data/91-image/t64.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t64.bmp -------------------------------------------------------------------------------- /data/91-image/t65.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t65.bmp -------------------------------------------------------------------------------- /data/91-image/t66.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t66.bmp -------------------------------------------------------------------------------- /data/91-image/t7.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t7.bmp -------------------------------------------------------------------------------- /data/91-image/t8.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t8.bmp -------------------------------------------------------------------------------- /data/91-image/t9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/t9.bmp -------------------------------------------------------------------------------- /data/91-image/tt1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt1.bmp -------------------------------------------------------------------------------- /data/91-image/tt10.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt10.bmp -------------------------------------------------------------------------------- /data/91-image/tt12.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt12.bmp -------------------------------------------------------------------------------- /data/91-image/tt13.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt13.bmp -------------------------------------------------------------------------------- /data/91-image/tt14.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt14.bmp -------------------------------------------------------------------------------- /data/91-image/tt15.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt15.bmp -------------------------------------------------------------------------------- /data/91-image/tt16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt16.bmp -------------------------------------------------------------------------------- /data/91-image/tt17.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt17.bmp -------------------------------------------------------------------------------- /data/91-image/tt18.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt18.bmp -------------------------------------------------------------------------------- /data/91-image/tt19.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt19.bmp -------------------------------------------------------------------------------- /data/91-image/tt2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt2.bmp -------------------------------------------------------------------------------- /data/91-image/tt20.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt20.bmp -------------------------------------------------------------------------------- /data/91-image/tt21.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt21.bmp -------------------------------------------------------------------------------- /data/91-image/tt22.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt22.bmp -------------------------------------------------------------------------------- /data/91-image/tt23.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt23.bmp -------------------------------------------------------------------------------- /data/91-image/tt24.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt24.bmp -------------------------------------------------------------------------------- /data/91-image/tt25.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt25.bmp -------------------------------------------------------------------------------- /data/91-image/tt26.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt26.bmp -------------------------------------------------------------------------------- /data/91-image/tt27.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt27.bmp -------------------------------------------------------------------------------- /data/91-image/tt3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt3.bmp -------------------------------------------------------------------------------- /data/91-image/tt4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt4.bmp -------------------------------------------------------------------------------- /data/91-image/tt5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt5.bmp -------------------------------------------------------------------------------- /data/91-image/tt6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt6.bmp -------------------------------------------------------------------------------- /data/91-image/tt7.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt7.bmp -------------------------------------------------------------------------------- /data/91-image/tt8.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt8.bmp -------------------------------------------------------------------------------- /data/91-image/tt9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/91-image/tt9.bmp -------------------------------------------------------------------------------- /data/Set14/baboon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/baboon.bmp -------------------------------------------------------------------------------- /data/Set14/barbara.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/barbara.bmp -------------------------------------------------------------------------------- /data/Set14/bridge.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/bridge.bmp -------------------------------------------------------------------------------- /data/Set14/coastguard.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/coastguard.bmp -------------------------------------------------------------------------------- /data/Set14/comic.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/comic.bmp -------------------------------------------------------------------------------- /data/Set14/face.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/face.bmp -------------------------------------------------------------------------------- /data/Set14/flowers.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/flowers.bmp -------------------------------------------------------------------------------- /data/Set14/foreman.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/foreman.bmp -------------------------------------------------------------------------------- /data/Set14/lenna.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/lenna.bmp -------------------------------------------------------------------------------- /data/Set14/man.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/man.bmp -------------------------------------------------------------------------------- /data/Set14/monarch.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/monarch.bmp -------------------------------------------------------------------------------- /data/Set14/pepper.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/pepper.bmp -------------------------------------------------------------------------------- /data/Set14/ppt3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/ppt3.bmp -------------------------------------------------------------------------------- /data/Set14/zebra.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set14/zebra.bmp -------------------------------------------------------------------------------- /data/Set5/baby_GT.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set5/baby_GT.bmp -------------------------------------------------------------------------------- /data/Set5/bird_GT.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set5/bird_GT.bmp -------------------------------------------------------------------------------- /data/Set5/butterfly_GT.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set5/butterfly_GT.bmp -------------------------------------------------------------------------------- /data/Set5/head_GT.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set5/head_GT.bmp -------------------------------------------------------------------------------- /data/Set5/woman_GT.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/data/Set5/woman_GT.bmp -------------------------------------------------------------------------------- /experiments/bicubic-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "bicubic-sc3", 3 | "model": { 4 | "name": "bicubic", 5 | "params": {} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 1 14 | } 15 | -------------------------------------------------------------------------------- /experiments/bicubic-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "bicubic-sc4", 3 | "model": { 4 | "name": "bicubic", 5 | "params": {} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 1 14 | } 15 | -------------------------------------------------------------------------------- /experiments/espcn-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "espcn-example", 3 | "model": { 4 | "name": "espcn", 5 | "params": {"f": [5, 3, 3], "n": [64, 32]} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 20, 12 | "lr_sub_stride": 100, 13 | "epochs": 2 14 | } 15 | -------------------------------------------------------------------------------- /experiments/espcn-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "espcn-sc3", 3 | "model": { 4 | "name": "espcn", 5 | "params": {"f": [5, 3, 3], "n": [64, 32]} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 2000, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-3, 18 | "decay": 0 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/espcn-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "espcn-sc4", 3 | "model": { 4 | "name": "espcn", 5 | "params": {"f": [5, 3, 3], "n": [64, 32]} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 2000, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-3, 18 | "decay": 0 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/fsrcnn-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "fsrcnn-example", 3 | "model": { 4 | "name": "fsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 20, 12 | "lr_sub_stride": 100, 13 | "epochs": 2 14 | } 15 | -------------------------------------------------------------------------------- /experiments/fsrcnn-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "fsrcnn-sc3", 3 | "model": { 4 | "name": "fsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/fsrcnn-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "fsrcnn-sc4", 3 | "model": { 4 | "name": "fsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos0-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos0-sc3", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 0} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos0-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos0-sc4", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 0} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos1-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos1-sc3", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 1} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos1-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos1-sc4", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 1} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos2-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos2-sc3", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 2} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos2-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos2-sc4", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 2} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos3-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos3-sc3", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 3} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/nsfsrcnn-pos3-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "nsfsrcnn-pos3-sc4", 3 | "model": { 4 | "name": "nsfsrcnn", 5 | "params": {"d": 56, "s": 12, "m": 4, "pos": 3} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/plot.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import matplotlib.pyplot as plt 4 | import pandas as pd 5 | 6 | 7 | results_dir = Path('results') 8 | results_dir.mkdir(exist_ok=True) 9 | 10 | # Performance plot 11 | for scale in [3, 4]: 12 | for test_set in ['Set5', 'Set14']: 13 | time = [] 14 | psnr = [] 15 | model = [] 16 | for save_dir in sorted(Path('.').glob(f'*-sc{scale}')): 17 | if 'bicubic' not in save_dir.stem: 18 | model += [save_dir.stem.rsplit('-', 1)[0].upper()] 19 | metrics_file = save_dir / f'test/{test_set}/metrics.csv' 20 | metrics = pd.read_csv(str(metrics_file), index_col='name') 21 | time += [metrics.time.average] 22 | psnr += [metrics.psnr.average] 23 | plt.figure() 24 | plt.semilogx(time, psnr, '.') 25 | plt.grid(True, which='both') 26 | for x, y, s in zip(time, psnr, model): 27 | if 'NS' in s: 28 | s = s.split('-')[1] 29 | plt.text(x, y, s) 30 | plt.xlabel('Run time (sec)') 31 | plt.ylabel('PSNR (dB)') 32 | plt.title(f'Scale {scale} on {test_set}') 33 | plt.savefig(str(results_dir / f'performance-sc{scale}-{test_set}.png')) 34 | plt.close() 35 | 36 | # History plot 37 | for scale in [3, 4]: 38 | plt.figure() 39 | for save_dir in sorted(Path('.').glob(f'*-sc{scale}')): 40 | if 'bicubic' not in save_dir.stem: 41 | model = save_dir.stem.rsplit('-', 1)[0].upper() 42 | history_file = save_dir / f'train/history.csv' 43 | history = pd.read_csv(str(history_file)) 44 | plt.plot(history.epoch, history.val_psnr, label=model, alpha=0.8) 45 | plt.legend() 46 | plt.xlabel('Epochs') 47 | plt.ylabel('Average test PSNR (dB)') 48 | plt.savefig(str(results_dir / f'history-sc{scale}.png')) 49 | plt.xlim(0, 500) 50 | if scale == 3: 51 | plt.ylim(31.5, 34.5) 52 | if scale == 4: 53 | plt.ylim(29, 32) 54 | plt.savefig(str(results_dir / f'history-sc{scale}-zoom.png')) 55 | plt.close() 56 | -------------------------------------------------------------------------------- /experiments/run.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from functools import partial 3 | import json 4 | from keras import optimizers 5 | from pathlib import Path 6 | 7 | from toolbox.data import load_set 8 | from toolbox.models import get_model 9 | from toolbox.experiment import Experiment 10 | 11 | 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument('param_file', type=Path) 14 | args = parser.parse_args() 15 | param = json.load(args.param_file.open()) 16 | 17 | # Model 18 | scale = param['scale'] 19 | build_model = partial(get_model(param['model']['name']), 20 | **param['model']['params']) 21 | if 'optimizer' in param: 22 | optimizer = getattr(optimizers, param['optimizer']['name'].lower()) 23 | optimizer = optimizer(**param['optimizer']['params']) 24 | else: 25 | optimizer = 'adam' 26 | 27 | # Data 28 | load_set = partial(load_set, 29 | lr_sub_size=param['lr_sub_size'], 30 | lr_sub_stride=param['lr_sub_stride']) 31 | 32 | # Training 33 | expt = Experiment(scale=param['scale'], load_set=load_set, 34 | build_model=build_model,optimizer=optimizer, 35 | save_dir=param['save_dir']) 36 | expt.train(train_set=param['train_set'], val_set=param['val_set'], 37 | epochs=param['epochs'], resume=True) 38 | 39 | # Evaluation 40 | for test_set in param['test_sets']: 41 | expt.test(test_set=test_set) 42 | -------------------------------------------------------------------------------- /experiments/run_all.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from subprocess import run 3 | 4 | 5 | for param_file in Path('.').glob('*.json'): 6 | print(f'Run {param_file.stem}') 7 | run(['python', 'run.py', str(param_file)]) 8 | -------------------------------------------------------------------------------- /experiments/srcnn-9-1-5-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "srcnn-9-1-5-sc3", 3 | "model": { 4 | "name": "srcnn", 5 | "params": {"f": [9, 1, 5], "n": [64, 32]} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/srcnn-9-1-5-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "srcnn-9-1-5-sc4", 3 | "model": { 4 | "name": "srcnn", 5 | "params": {"f": [9, 1, 5], "n": [64, 32]} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/srcnn-9-5-5-sc3.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "srcnn-9-5-5-sc3", 3 | "model": { 4 | "name": "srcnn", 5 | "params": {"f": [9, 5, 5], "n": [64, 32]} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/srcnn-9-5-5-sc4.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "srcnn-9-5-5-sc4", 3 | "model": { 4 | "name": "srcnn", 5 | "params": {"f": [9, 5, 5], "n": [64, 32]} 6 | }, 7 | "scale": 4, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 11, 12 | "lr_sub_stride": 5, 13 | "epochs": 500, 14 | "optimizer": { 15 | "name": "adam", 16 | "params": { 17 | "lr": 1e-5, 18 | "decay": 1e-5 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/srcnn-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "save_dir": "srcnn-example", 3 | "model": { 4 | "name": "srcnn", 5 | "params": {"f": [9, 1, 5], "n": [64, 32]} 6 | }, 7 | "scale": 3, 8 | "train_set": "91-image", 9 | "val_set": "Set5", 10 | "test_sets": ["Set5", "Set14"], 11 | "lr_sub_size": 20, 12 | "lr_sub_stride": 100, 13 | "epochs": 2 14 | } 15 | -------------------------------------------------------------------------------- /install/create-env-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script creates a conda environment on a vanilla Ubuntu machine 3 | # from scratch. 4 | 5 | sudo apt-get -y install git 6 | cd ~ 7 | git clone -q https://github.com/qobilidop/srcnn.git 8 | cd srcnn 9 | . install/install-conda-on-linux.sh 10 | conda env create -f install/env-cpu.yml 11 | source activate srcnn 12 | pip install -e . 13 | -------------------------------------------------------------------------------- /install/create-env-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script creates a conda environment on a vanilla Ubuntu machine 3 | # from scratch. 4 | 5 | sudo apt-get -y install git 6 | cd ~ 7 | git clone -q https://github.com/qobilidop/srcnn.git 8 | cd srcnn 9 | . install/install-conda-on-linux.sh 10 | conda env create -f install/env-gpu.yml 11 | source activate srcnn 12 | pip install -e . 13 | -------------------------------------------------------------------------------- /install/env-cpu.yml: -------------------------------------------------------------------------------- 1 | name: srcnn 2 | dependencies: 3 | - h5py=2.6.0=np112py36_2 4 | - matplotlib=2.0.0=np112py36_0 5 | - numpy=1.12.0=py36_0 6 | - pandas=0.19.2=np112py36_1 7 | - pillow=4.0.0=py36_1 8 | - python=3.6.0=0 9 | - scipy=0.19.0=np112py36_0 10 | - pip: 11 | - keras==2.0.0 12 | - tensorflow==1.0.1 13 | -------------------------------------------------------------------------------- /install/env-gpu.yml: -------------------------------------------------------------------------------- 1 | name: srcnn 2 | dependencies: 3 | - h5py=2.6.0=np112py36_2 4 | - matplotlib=2.0.0=np112py36_0 5 | - numpy=1.12.0=py36_0 6 | - pandas=0.19.2=np112py36_1 7 | - pillow=4.0.0=py36_1 8 | - python=3.6.0=0 9 | - scipy=0.19.0=np112py36_0 10 | - pip: 11 | - keras==2.0.0 12 | - tensorflow-gpu==1.0.1 13 | -------------------------------------------------------------------------------- /install/install-conda-on-linux.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script installs conda silently on a Linux machine. 3 | # See http://conda.pydata.org/docs/help/silent.html#linux-and-os-x 4 | 5 | BASH_RC=$HOME/.bashrc 6 | PREFIX=$HOME/miniconda 7 | 8 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh 9 | bash ~/miniconda.sh -b -p $PREFIX 10 | rm ~/miniconda.sh 11 | echo " 12 | # added by Miniconda3 installer 13 | export PATH=\"$PREFIX/bin:\$PATH\"" >> $BASH_RC 14 | source $BASH_RC 15 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages 2 | from setuptools import setup 3 | 4 | 5 | setup( 6 | name='toolbox', 7 | packages=find_packages(), 8 | ) 9 | -------------------------------------------------------------------------------- /toolbox/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qobilidop/srcnn/110fcc574a22e0e87d88007670fa1dd1e553254b/toolbox/__init__.py -------------------------------------------------------------------------------- /toolbox/data.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | import numpy as np 4 | from keras.preprocessing.image import img_to_array 5 | from keras.preprocessing.image import load_img 6 | 7 | from toolbox.image import bicubic_rescale 8 | from toolbox.image import modcrop 9 | from toolbox.paths import data_dir 10 | 11 | 12 | def load_set(name, lr_sub_size=11, lr_sub_stride=5, scale=3): 13 | hr_sub_size = lr_sub_size * scale 14 | hr_sub_stride = lr_sub_stride * scale 15 | lr_gen_sub = partial(generate_sub_images, size=lr_sub_size, 16 | stride=lr_sub_stride) 17 | hr_gen_sub = partial(generate_sub_images, size=hr_sub_size, 18 | stride=hr_sub_stride) 19 | 20 | lr_sub_arrays = [] 21 | hr_sub_arrays = [] 22 | for path in (data_dir / name).glob('*'): 23 | lr_image, hr_image = load_image_pair(str(path), scale=scale) 24 | lr_sub_arrays += [img_to_array(img) for img in lr_gen_sub(lr_image)] 25 | hr_sub_arrays += [img_to_array(img) for img in hr_gen_sub(hr_image)] 26 | x = np.stack(lr_sub_arrays) 27 | y = np.stack(hr_sub_arrays) 28 | return x, y 29 | 30 | 31 | def load_image_pair(path, scale=3): 32 | image = load_img(path) 33 | image = image.convert('YCbCr') 34 | hr_image = modcrop(image, scale) 35 | lr_image = bicubic_rescale(hr_image, 1 / scale) 36 | return lr_image, hr_image 37 | 38 | 39 | def generate_sub_images(image, size, stride): 40 | for i in range(0, image.size[0] - size + 1, stride): 41 | for j in range(0, image.size[1] - size + 1, stride): 42 | yield image.crop([i, j, i + size, j + size]) 43 | -------------------------------------------------------------------------------- /toolbox/experiment.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | from pathlib import Path 3 | import time 4 | 5 | from keras import backend as K 6 | from keras.callbacks import CSVLogger 7 | from keras.callbacks import ModelCheckpoint 8 | from keras.optimizers import adam 9 | from keras.preprocessing.image import img_to_array 10 | import matplotlib 11 | matplotlib.use('Agg') 12 | import matplotlib.pyplot as plt 13 | import numpy as np 14 | import pandas as pd 15 | 16 | from toolbox.data import load_image_pair 17 | from toolbox.image import array_to_img 18 | from toolbox.metrics import psnr 19 | from toolbox.models import bicubic 20 | from toolbox.paths import data_dir 21 | 22 | 23 | class Experiment(object): 24 | def __init__(self, scale=3, load_set=None, build_model=None, 25 | optimizer='adam', save_dir='.'): 26 | self.scale = scale 27 | self.load_set = partial(load_set, scale=scale) 28 | self.build_model = partial(build_model, scale=scale) 29 | self.optimizer = optimizer 30 | self.save_dir = Path(save_dir) 31 | self.save_dir.mkdir(parents=True, exist_ok=True) 32 | 33 | self.config_file = self.save_dir / 'config.yaml' 34 | self.model_file = self.save_dir / 'model.hdf5' 35 | 36 | self.train_dir = self.save_dir / 'train' 37 | self.train_dir.mkdir(exist_ok=True) 38 | self.history_file = self.train_dir / 'history.csv' 39 | self.weights_dir = self.train_dir / 'weights' 40 | self.weights_dir.mkdir(exist_ok=True) 41 | 42 | self.test_dir = self.save_dir / 'test' 43 | self.test_dir.mkdir(exist_ok=True) 44 | 45 | def weights_file(self, epoch=None): 46 | if epoch is None: 47 | return self.weights_dir / 'ep{epoch:04d}.hdf5' 48 | else: 49 | return self.weights_dir / f'ep{epoch:04d}.hdf5' 50 | 51 | @property 52 | def latest_epoch(self): 53 | try: 54 | return pd.read_csv(str(self.history_file))['epoch'].iloc[-1] 55 | except (FileNotFoundError, pd.io.common.EmptyDataError): 56 | pass 57 | return -1 58 | 59 | def _ensure_dimension(self, array, dim): 60 | while len(array.shape) < dim: 61 | array = array[np.newaxis, ...] 62 | return array 63 | 64 | def _ensure_channel(self, array, c): 65 | return array[..., c:c+1] 66 | 67 | def pre_process(self, array): 68 | array = self._ensure_dimension(array, 4) 69 | array = self._ensure_channel(array, 0) 70 | return array 71 | 72 | def post_process(self, array, auxiliary_array): 73 | array = np.concatenate([array, auxiliary_array[..., 1:]], axis=-1) 74 | array = np.clip(array, 0, 255) 75 | return array 76 | 77 | def inverse_post_process(self, array): 78 | array = self._ensure_dimension(array, 4) 79 | array = self._ensure_channel(array, 0) 80 | return array 81 | 82 | def compile(self, model): 83 | """Compile model with default settings.""" 84 | model.compile(optimizer=self.optimizer, loss='mse', metrics=[psnr]) 85 | return model 86 | 87 | def train(self, train_set='91-image', val_set='Set5', epochs=1, 88 | resume=True): 89 | # Load and process data 90 | x_train, y_train = self.load_set(train_set) 91 | x_val, y_val = self.load_set(val_set) 92 | x_train, x_val = [self.pre_process(x) 93 | for x in [x_train, x_val]] 94 | y_train, y_val = [self.inverse_post_process(y) 95 | for y in [y_train, y_val]] 96 | 97 | # Compile model 98 | model = self.compile(self.build_model(x_train)) 99 | model.summary() 100 | 101 | # Save model architecture 102 | # Currently in Keras 2 it's not possible to load a model with custom 103 | # layers. So we just save it without checking consistency. 104 | self.config_file.write_text(model.to_yaml()) 105 | 106 | # Inherit weights 107 | if resume: 108 | latest_epoch = self.latest_epoch 109 | if latest_epoch > -1: 110 | weights_file = self.weights_file(epoch=latest_epoch) 111 | model.load_weights(str(weights_file)) 112 | initial_epoch = latest_epoch + 1 113 | else: 114 | initial_epoch = 0 115 | 116 | # Set up callbacks 117 | callbacks = [] 118 | callbacks += [ModelCheckpoint(str(self.model_file))] 119 | callbacks += [ModelCheckpoint(str(self.weights_file()), 120 | save_weights_only=True)] 121 | callbacks += [CSVLogger(str(self.history_file), append=resume)] 122 | 123 | # Train 124 | model.fit(x_train, y_train, epochs=epochs, callbacks=callbacks, 125 | validation_data=(x_val, y_val), initial_epoch=initial_epoch) 126 | 127 | # Plot metrics history 128 | prefix = str(self.history_file).rsplit('.', maxsplit=1)[0] 129 | df = pd.read_csv(str(self.history_file)) 130 | epoch = df['epoch'] 131 | for metric in ['Loss', 'PSNR']: 132 | train = df[metric.lower()] 133 | val = df['val_' + metric.lower()] 134 | plt.figure() 135 | plt.plot(epoch, train, label='train') 136 | plt.plot(epoch, val, label='val') 137 | plt.legend(loc='best') 138 | plt.xlabel('Epoch') 139 | plt.ylabel(metric) 140 | plt.savefig('.'.join([prefix, metric.lower(), 'png'])) 141 | plt.close() 142 | 143 | def test(self, test_set='Set5', metrics=[psnr]): 144 | print('Test on', test_set) 145 | image_dir = self.test_dir / test_set 146 | image_dir.mkdir(exist_ok=True) 147 | 148 | # Evaluate metrics on each image 149 | rows = [] 150 | for image_path in (data_dir / test_set).glob('*'): 151 | rows += [self.test_on_image(str(image_path), 152 | str(image_dir / image_path.stem), 153 | metrics=metrics)] 154 | df = pd.DataFrame(rows) 155 | 156 | # Compute average metrics 157 | row = pd.Series() 158 | row['name'] = 'average' 159 | for col in df: 160 | if col != 'name': 161 | row[col] = df[col].mean() 162 | df = df.append(row, ignore_index=True) 163 | 164 | df.to_csv(str(self.test_dir / f'{test_set}/metrics.csv')) 165 | 166 | def test_on_image(self, path, prefix, suffix='png', metrics=[psnr]): 167 | # Load images 168 | lr_image, hr_image = load_image_pair(path, scale=self.scale) 169 | 170 | # Generate bicubic image 171 | x = img_to_array(lr_image)[np.newaxis, ...] 172 | bicubic_model = bicubic(x, scale=self.scale) 173 | y = bicubic_model.predict_on_batch(x) 174 | bicubic_array = np.clip(y[0], 0, 255) 175 | 176 | # Generate output image and measure run time 177 | x = self.pre_process(x) 178 | model = self.compile(self.build_model(x)) 179 | if self.model_file.exists(): 180 | model.load_weights(str(self.model_file)) 181 | start = time.perf_counter() 182 | y_pred = model.predict_on_batch(x) 183 | end = time.perf_counter() 184 | output_array = self.post_process(y_pred[0], bicubic_array) 185 | output_image = array_to_img(output_array, mode='YCbCr') 186 | 187 | # Record metrics 188 | row = pd.Series() 189 | row['name'] = Path(path).stem 190 | row['time'] = end - start 191 | y_true = self.inverse_post_process(img_to_array(hr_image)) 192 | for metric in metrics: 193 | row[metric.__name__] = K.eval(metric(y_true, y_pred)) 194 | 195 | # Save images 196 | images_to_save = [] 197 | images_to_save += [(hr_image, 'original')] 198 | images_to_save += [(output_image, 'output')] 199 | images_to_save += [(lr_image, 'input')] 200 | for img, label in images_to_save: 201 | img.convert(mode='RGB').save('.'.join([prefix, label, suffix])) 202 | 203 | return row 204 | -------------------------------------------------------------------------------- /toolbox/image.py: -------------------------------------------------------------------------------- 1 | """Image processing tools.""" 2 | import numpy as np 3 | from PIL import Image 4 | 5 | 6 | def array_to_img(x, mode='YCbCr'): 7 | return Image.fromarray(x.astype('uint8'), mode=mode) 8 | 9 | 10 | def bicubic_rescale(image, scale): 11 | if isinstance(scale, (float, int)): 12 | size = (np.array(image.size) * scale).astype(int) 13 | return image.resize(size, resample=Image.BICUBIC) 14 | 15 | 16 | def modcrop(image, scale): 17 | size = np.array(image.size) 18 | size -= size % scale 19 | return image.crop([0, 0, *size]) 20 | -------------------------------------------------------------------------------- /toolbox/layers.py: -------------------------------------------------------------------------------- 1 | from keras.engine.topology import Layer 2 | import numpy as np 3 | import tensorflow as tf 4 | 5 | 6 | custom_layers = {} 7 | 8 | 9 | class ImageRescale(Layer): 10 | def __init__(self, scale, method=tf.image.ResizeMethod.BICUBIC, 11 | trainable=False, **kwargs): 12 | self.scale = scale 13 | self.method = method 14 | super().__init__(trainable=trainable, **kwargs) 15 | 16 | def compute_size(self, shape): 17 | size = np.array(shape)[[1, 2]] * self.scale 18 | return tuple(size.astype(int)) 19 | 20 | def call(self, x): 21 | size = self.compute_size(x.shape.as_list()) 22 | return tf.image.resize_images(x, size, method=self.method) 23 | 24 | def compute_output_shape(self, input_shape): 25 | size = self.compute_size(input_shape) 26 | return (input_shape[0], *size, input_shape[3]) 27 | 28 | def get_config(self): 29 | config = super().get_config() 30 | config['scale'] = self.scale 31 | config['method'] = self.method 32 | return config 33 | 34 | 35 | custom_layers['ImageRescale'] = ImageRescale 36 | 37 | 38 | class Conv2DSubPixel(Layer): 39 | """Sub-pixel convolution layer. 40 | 41 | See https://arxiv.org/abs/1609.05158 42 | """ 43 | def __init__(self, scale, trainable=False, **kwargs): 44 | self.scale = scale 45 | super().__init__(trainable=trainable, **kwargs) 46 | 47 | def call(self, t): 48 | r = self.scale 49 | shape = t.shape.as_list() 50 | new_shape = self.compute_output_shape(shape) 51 | H, W = shape[1:3] 52 | C = new_shape[-1] 53 | t = tf.reshape(t, [-1, H, W, r, r, C]) 54 | # Here we are different from Equation 4 from the paper. That equation 55 | # is equivalent to switching 3 and 4 in `perm`. But I feel my 56 | # implementation is more natural. 57 | t = tf.transpose(t, perm=[0, 1, 3, 2, 4, 5]) # S, H, r, H, r, C 58 | t = tf.reshape(t, [-1, H * r, W * r, C]) 59 | return t 60 | 61 | def compute_output_shape(self, input_shape): 62 | r = self.scale 63 | H, W, rrC = np.array(input_shape[1:]) 64 | assert rrC % (r ** 2) == 0 65 | return (input_shape[0], H * r, W * r, rrC // (r ** 2)) 66 | 67 | def get_config(self): 68 | config = super().get_config() 69 | config['scale'] = self.scale 70 | return config 71 | 72 | 73 | custom_layers['Conv2DSubPixel'] = Conv2DSubPixel 74 | -------------------------------------------------------------------------------- /toolbox/metrics.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | import numpy as np 3 | 4 | 5 | def psnr(y_true, y_pred): 6 | """Peak signal-to-noise ratio averaged over samples and channels.""" 7 | mse = K.mean(K.square(y_true - y_pred), axis=(-3, -2)) 8 | return K.mean(20 * K.log(255 / K.sqrt(mse)) / np.log(10)) 9 | 10 | 11 | def ssim(y_true, y_pred): 12 | """structural similarity measurement system.""" 13 | ## K1, K2 are two constants, much smaller than 1 14 | K1 = 0.04 15 | K2 = 0.06 16 | 17 | ## mean, std, correlation 18 | mu_x = K.mean(y_pred) 19 | mu_y = K.mean(y_true) 20 | 21 | sig_x = K.std(y_pred) 22 | sig_y = K.std(y_true) 23 | sig_xy = (sig_x * sig_y) ** 0.5 24 | 25 | ## L, number of pixels, C1, C2, two constants 26 | L = 33 27 | C1 = (K1 * L) ** 2 28 | C2 = (K2 * L) ** 2 29 | 30 | ssim = (2 * mu_x * mu_y + C1) * (2 * sig_xy * C2) * 1.0 / ((mu_x ** 2 + mu_y ** 2 + C1) * (sig_x ** 2 + sig_y ** 2 + C2)) 31 | return ssim 32 | -------------------------------------------------------------------------------- /toolbox/models.py: -------------------------------------------------------------------------------- 1 | from keras.layers import Conv2D 2 | from keras.layers import Conv2DTranspose 3 | from keras.layers import InputLayer 4 | from keras.models import Sequential 5 | import tensorflow as tf 6 | 7 | from toolbox.layers import ImageRescale 8 | from toolbox.layers import Conv2DSubPixel 9 | 10 | 11 | def bicubic(x, scale=3): 12 | model = Sequential() 13 | model.add(InputLayer(input_shape=x.shape[-3:])) 14 | model.add(ImageRescale(scale, method=tf.image.ResizeMethod.BICUBIC)) 15 | return model 16 | 17 | 18 | def srcnn(x, f=[9, 1, 5], n=[64, 32], scale=3): 19 | """Build an SRCNN model. 20 | 21 | See https://arxiv.org/abs/1501.00092 22 | """ 23 | assert len(f) == len(n) + 1 24 | model = bicubic(x, scale=scale) 25 | c = x.shape[-1] 26 | for ni, fi in zip(n, f): 27 | model.add(Conv2D(ni, fi, padding='same', 28 | kernel_initializer='he_normal', activation='relu')) 29 | model.add(Conv2D(c, f[-1], padding='same', 30 | kernel_initializer='he_normal')) 31 | return model 32 | 33 | 34 | def fsrcnn(x, d=56, s=12, m=4, scale=3): 35 | """Build an FSRCNN model. 36 | 37 | See https://arxiv.org/abs/1608.00367 38 | """ 39 | model = Sequential() 40 | model.add(InputLayer(input_shape=x.shape[-3:])) 41 | c = x.shape[-1] 42 | f = [5, 1] + [3] * m + [1] 43 | n = [d, s] + [s] * m + [d] 44 | for ni, fi in zip(n, f): 45 | model.add(Conv2D(ni, fi, padding='same', 46 | kernel_initializer='he_normal', activation='relu')) 47 | model.add(Conv2DTranspose(c, 9, strides=scale, padding='same', 48 | kernel_initializer='he_normal')) 49 | return model 50 | 51 | 52 | def nsfsrcnn(x, d=56, s=12, m=4, scale=3, pos=1): 53 | """Build an FSRCNN model, but change deconv position. 54 | 55 | See https://arxiv.org/abs/1608.00367 56 | """ 57 | model = Sequential() 58 | model.add(InputLayer(input_shape=x.shape[-3:])) 59 | c = x.shape[-1] 60 | f1 = [5, 1] + [3] * pos 61 | n1 = [d, s] + [s] * pos 62 | f2 = [3] * (m - pos - 1) + [1] 63 | n2 = [s] * (m - pos - 1) + [d] 64 | f3 = 9 65 | n3 = c 66 | for ni, fi in zip(n1, f1): 67 | model.add(Conv2D(ni, fi, padding='same', 68 | kernel_initializer='he_normal', activation='relu')) 69 | model.add(Conv2DTranspose(s, 3, strides=scale, padding='same', 70 | kernel_initializer='he_normal')) 71 | for ni, fi in zip(n2, f2): 72 | model.add(Conv2D(ni, fi, padding='same', 73 | kernel_initializer='he_normal', activation='relu')) 74 | model.add(Conv2D(n3, f3, padding='same', 75 | kernel_initializer='he_normal')) 76 | return model 77 | 78 | 79 | def espcn(x, f=[5, 3, 3], n=[64, 32], scale=3): 80 | """Build an ESPCN model. 81 | 82 | See https://arxiv.org/abs/1609.05158 83 | """ 84 | assert len(f) == len(n) + 1 85 | model = Sequential() 86 | model.add(InputLayer(input_shape=x.shape[1:])) 87 | c = x.shape[-1] 88 | for ni, fi in zip(n, f): 89 | model.add(Conv2D(ni, fi, padding='same', 90 | kernel_initializer='he_normal', activation='tanh')) 91 | model.add(Conv2D(c * scale ** 2, f[-1], padding='same', 92 | kernel_initializer='he_normal')) 93 | model.add(Conv2DSubPixel(scale)) 94 | return model 95 | 96 | 97 | def get_model(name): 98 | return globals()[name] 99 | -------------------------------------------------------------------------------- /toolbox/paths.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | 4 | repo_dir = Path(__file__).parents[1] 5 | data_dir = repo_dir / 'data' 6 | --------------------------------------------------------------------------------