Commit 4c1fb008 authored by Xavier Weber's avatar Xavier Weber Committed by Alexander Alekhin

Merge pull request #2231 from Saafke:dnn_superres_final_phase

* Add learning-based super-resolution module

Adds the module plus loading classes for SR data

Complete with docs, tutorials and tests.

* Fix typo

* Small commit to restart buildbot

* Change refs from arXiv to official

* Remove video string

* dnn_superres: update perf test code

* dnn_superres: test fixup
parent dda33bf3
...@@ -22,7 +22,7 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -D BUILD_opencv_<r ...@@ -22,7 +22,7 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -D BUILD_opencv_<r
- **datasets**: Datasets Reader -- Code for reading existing computer vision databases and samples of using the readers to train, test and run using that dataset's data. - **datasets**: Datasets Reader -- Code for reading existing computer vision databases and samples of using the readers to train, test and run using that dataset's data.
- **dnn_objdetect**: Object Detection using CNNs -- Implements compact CNN Model for object detection. Trained using Caffe but uses opencv_dnn modeule. - **dnn_objdetect**: Object Detection using CNNs -- Implements compact CNN Model for object detection. Trained using Caffe but uses opencv_dnn module.
- **dnn_superres**: Superresolution using CNNs -- Contains four trained convolutional neural networks to upscale images. - **dnn_superres**: Superresolution using CNNs -- Contains four trained convolutional neural networks to upscale images.
......
...@@ -435,6 +435,53 @@ Usage: ...@@ -435,6 +435,53 @@ Usage:
./opencv/build/bin/example_datasets_slam_tumindoor -p=/home/user/path_to_unpacked_folders/ ./opencv/build/bin/example_datasets_slam_tumindoor -p=/home/user/path_to_unpacked_folders/
~~~ ~~~
@defgroup datasets_sr Super Resolution
### The Berkeley Segmentation Dataset and Benchmark
Implements loading dataset:
"The Berkeley Segmentation Dataset and Benchmark": <https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/segbench/>
Usage:
-# From link above download `BSDS300-images.tgz`.
-# Unpack.
-# To load data run:
~~~
./opencv/build/bin/example_datasets_sr_bsds -p=/home/user/path_to_unpacked_folder/
~~~
### DIV2K dataset: DIVerse 2K
Implements loading dataset:
"DIV2K dataset: DIVerse 2K": <https://data.vision.ee.ethz.ch/cvl/DIV2K/>
Usage:
-# From link above download 'Train data (HR images)' or any other of the dataset files.
-# Unpack.
-# To load data run:
~~~
./opencv/build/bin/example_datasets_sr_div2k -p=/home/user/path_to_unpacked_folder/folder_containing_the_images/
~~~
### The General-100 Dataset
Implements loading dataset:
"General-100 dataset contains 100 bmp-format images (with no compression).
We used this dataset in our FSRCNN ECCV 2016 paper. The size of these 100 images ranges from 710 x 704 (large) to 131 x 112 (small).
They are all of good quality with clear edges but fewer smooth regions (e.g., sky and ocean), thus are very suitable for the super-resolution training.":
<http://mmlab.ie.cuhk.edu.hk/projects/FSRCNN.html>
Usage:
-# From link above download `General-100.zip`.
-# Unpack.
-# To load data run:
~~~
./opencv/build/bin/example_datasets_sr_general100 -p=/home/user/path_to_unpacked_folder/
~~~
@defgroup datasets_tr Text Recognition @defgroup datasets_tr Text Recognition
### The Chars74K Dataset ### The Chars74K Dataset
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_DATASETS_SR_BSDS_HPP
#define OPENCV_DATASETS_SR_BSDS_HPP
#include <string>
#include <vector>
#include "opencv2/datasets/dataset.hpp"
#include <opencv2/core.hpp>
namespace cv
{
namespace datasets
{
//! @addtogroup datasets_sr
//! @{
struct SR_bsdsObj : public Object
{
std::string imageName;
};
class CV_EXPORTS SR_bsds : public Dataset
{
public:
virtual void load(const std::string &path) CV_OVERRIDE = 0;
static Ptr<SR_bsds> create();
};
//! @}
}
}
#endif
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_DATASETS_SR_DIV2K_HPP
#define OPENCV_DATASETS_SR_DIV2K_HPP
#include <string>
#include <vector>
#include "opencv2/datasets/dataset.hpp"
#include <opencv2/core.hpp>
namespace cv
{
namespace datasets
{
//! @addtogroup datasets_sr
//! @{
struct SR_div2kObj : public Object
{
std::string imageName;
};
class CV_EXPORTS SR_div2k : public Dataset
{
public:
virtual void load(const std::string &path) CV_OVERRIDE = 0;
static Ptr<SR_div2k> create();
};
//! @}
}
}
#endif
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_DATASETS_SR_GENERAL100_HPP
#define OPENCV_DATASETS_SR_GENERAL100_HPP
#include <string>
#include <vector>
#include "opencv2/datasets/dataset.hpp"
#include <opencv2/core.hpp>
namespace cv
{
namespace datasets
{
//! @addtogroup datasets_sr
//! @{
struct SR_general100Obj : public Object
{
std::string imageName;
};
class CV_EXPORTS SR_general100 : public Dataset
{
public:
virtual void load(const std::string &path) CV_OVERRIDE = 0;
static Ptr<SR_general100> create();
};
//! @}
}
}
#endif
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_bsds.hpp"
#include <opencv2/core.hpp>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
using namespace cv::datasets;
int main(int argc, char *argv[])
{
const char *keys =
"{ help h usage ? | | show this message }"
"{ path p |true| path to dataset (images, iids_train.txt, iids_test.txt) }";
CommandLineParser parser(argc, argv, keys);
string path(parser.get<string>("path"));
if (parser.has("help") || path=="true")
{
parser.printMessage();
return -1;
}
Ptr<SR_bsds> dataset = SR_bsds::create();
dataset->load(path);
// ***************
// Dataset train & test contain names of appropriate images.
// For example, let's output full path & name for first train and test images.
// And dataset sizes.
printf("train size: %u\n", (unsigned int)dataset->getTrain().size());
printf("test size: %u\n", (unsigned int)dataset->getTest().size());
SR_bsdsObj *example1 = static_cast<SR_bsdsObj *>(dataset->getTrain()[0].get());
string fullPath(path + "images/train/" + example1->imageName + ".jpg");
printf("first train image: %s\n", fullPath.c_str());
SR_bsdsObj *example2 = static_cast<SR_bsdsObj *>(dataset->getTest()[0].get());
fullPath = path + "images/test/" + example2->imageName + ".jpg";
printf("first test image: %s\n", fullPath.c_str());
return 0;
}
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_div2k.hpp"
#include <opencv2/core.hpp>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
using namespace cv::datasets;
int main(int argc, char *argv[])
{
const char *keys =
"{ help h usage ? | | show this message }"
"{ path p |true| path to dataset (Div2k dataset folder containing the images) }";
CommandLineParser parser(argc, argv, keys);
string path(parser.get<string>("path"));
if (parser.has("help") || path=="true")
{
parser.printMessage();
return -1;
}
Ptr<SR_div2k> dataset = SR_div2k::create();
dataset->load(path);
// ***************
// Dataset contains all images.
// For example, let's output dataset size; first image name; and second image full path.
printf("dataset size: %u\n", (unsigned int)dataset->getTrain().size());
SR_div2kObj *example = static_cast<SR_div2kObj *>(dataset->getTrain()[0].get());
printf("first image name: %s\n", example->imageName.c_str());
SR_div2kObj *example2 = static_cast<SR_div2kObj *>(dataset->getTrain()[1].get());
string fullPath = path + "/" + example2->imageName.c_str();
printf("second image full path: %s\n", fullPath.c_str());
return 0;
}
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_general100.hpp"
#include <opencv2/core.hpp>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
using namespace cv::datasets;
int main(int argc, char *argv[])
{
const char *keys =
"{ help h usage ? | | show this message }"
"{ path p |true| path to dataset (General-100 dataset folder) }";
CommandLineParser parser(argc, argv, keys);
string path(parser.get<string>("path"));
if (parser.has("help") || path=="true")
{
parser.printMessage();
return -1;
}
Ptr<SR_general100> dataset = SR_general100::create();
dataset->load(path);
// ***************
// Dataset contains all images.
// For example, let's output dataset size; first image name; and second image full path.
printf("dataset size: %u\n", (unsigned int)dataset->getTrain().size());
SR_general100Obj *example = static_cast<SR_general100Obj *>(dataset->getTrain()[0].get());
printf("first image name: %s\n", example->imageName.c_str());
SR_general100Obj *example2 = static_cast<SR_general100Obj *>(dataset->getTrain()[1].get());
string fullPath = path + "/" + example2->imageName.c_str();
printf("second image full path: %s\n", fullPath.c_str());
return 0;
}
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_bsds.hpp"
#include "opencv2/datasets/util.hpp"
namespace cv
{
namespace datasets
{
using namespace std;
class SR_bsdsImp CV_FINAL : public SR_bsds
{
public:
SR_bsdsImp() {}
//SR_bsdsImp(const string &path);
virtual ~SR_bsdsImp() {}
virtual void load(const string &path) CV_OVERRIDE;
private:
void loadDataset(const string &path);
void loadDatasetPart(const string &fileName, vector< Ptr<Object> > &dataset_);
};
void SR_bsdsImp::loadDatasetPart(const string &fileName, vector< Ptr<Object> > &dataset_)
{
ifstream infile(fileName.c_str());
string imageName;
while (infile >> imageName)
{
Ptr<SR_bsdsObj> curr(new SR_bsdsObj);
curr->imageName = imageName;
dataset_.push_back(curr);
}
}
/*SR_bsdsImp::SR_bsdsImp(const string &path)
{
loadDataset(path);
}*/
void SR_bsdsImp::load(const string &path)
{
loadDataset(path);
}
void SR_bsdsImp::loadDataset(const string &path)
{
train.push_back(vector< Ptr<Object> >());
test.push_back(vector< Ptr<Object> >());
validation.push_back(vector< Ptr<Object> >());
string trainName(path + "iids_train.txt");
string testName(path + "iids_test.txt");
// loading train
loadDatasetPart(trainName, train.back());
// loading test
loadDatasetPart(testName, test.back());
}
Ptr<SR_bsds> SR_bsds::create()
{
return Ptr<SR_bsdsImp>(new SR_bsdsImp);
}
}
}
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_div2k.hpp"
#include "opencv2/datasets/util.hpp"
namespace cv
{
namespace datasets
{
using namespace std;
class SR_div2kImp CV_FINAL : public SR_div2k
{
public:
SR_div2kImp() {}
//SR_div2kImp(const string &path);
virtual ~SR_div2kImp() {}
virtual void load(const string &path) CV_OVERRIDE;
private:
void loadDataset(const string &path);
};
/*SR_div2kImp::SR_div2kImp(const string &path)
{
loadDataset(path);
}*/
void SR_div2kImp::load(const string &path)
{
loadDataset(path);
}
void SR_div2kImp::loadDataset(const string &path)
{
train.push_back(vector< Ptr<Object> >());
test.push_back(vector< Ptr<Object> >());
validation.push_back(vector< Ptr<Object> >());
vector<string> fileNames;
getDirList(path, fileNames);
for (vector<string>::iterator it=fileNames.begin(); it!=fileNames.end(); ++it)
{
string &imageName = *it;
Ptr<SR_div2kObj> curr(new SR_div2kObj);
curr->imageName = imageName;
train.back().push_back(curr);
}
}
Ptr<SR_div2k> SR_div2k::create()
{
return Ptr<SR_div2kImp>(new SR_div2kImp);
}
}
}
\ No newline at end of file
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "opencv2/datasets/sr_general100.hpp"
#include "opencv2/datasets/util.hpp"
namespace cv
{
namespace datasets
{
using namespace std;
class SR_general100Imp CV_FINAL : public SR_general100
{
public:
SR_general100Imp() {}
//SR_general100Imp(const string &path);
virtual ~SR_general100Imp() {}
virtual void load(const string &path) CV_OVERRIDE;
private:
void loadDataset(const string &path);
};
/*SR_general100Imp::SR_general100Imp(const string &path)
{
loadDataset(path);
}*/
void SR_general100Imp::load(const string &path)
{
loadDataset(path);
}
void SR_general100Imp::loadDataset(const string &path)
{
train.push_back(vector< Ptr<Object> >());
test.push_back(vector< Ptr<Object> >());
validation.push_back(vector< Ptr<Object> >());
vector<string> fileNames;
getDirList(path, fileNames);
for (vector<string>::iterator it=fileNames.begin(); it!=fileNames.end(); ++it)
{
string &imageName = *it;
Ptr<SR_general100Obj> curr(new SR_general100Obj);
curr->imageName = imageName;
train.back().push_back(curr);
}
}
Ptr<SR_general100> SR_general100::create()
{
return Ptr<SR_general100Imp>(new SR_general100Imp);
}
}
}
\ No newline at end of file
...@@ -40,7 +40,7 @@ Trained models can be downloaded from [here](https://github.com/fannymonori/TF-E ...@@ -40,7 +40,7 @@ Trained models can be downloaded from [here](https://github.com/fannymonori/TF-E
- Advantage: It is tiny and fast, and still performs well. - Advantage: It is tiny and fast, and still performs well.
- Disadvantage: Perform worse visually than newer, more robust models. - Disadvantage: Perform worse visually than newer, more robust models.
- Speed: < 0.01 sec for every scaling factor on 256x256 images on an Intel i7-9700K CPU. - Speed: < 0.01 sec for every scaling factor on 256x256 images on an Intel i7-9700K CPU.
- Original paper: [Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network](<https://arxiv.org/abs/1609.05158>) [2] - Original paper: [Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network](https://arxiv.org/pdf/1707.02921.pdf) [2]
#### FSRCNN #### FSRCNN
...@@ -66,11 +66,11 @@ Trained models can be downloaded from [here](https://github.com/fannymonori/TF-L ...@@ -66,11 +66,11 @@ Trained models can be downloaded from [here](https://github.com/fannymonori/TF-L
- Advantage: The model can do multi-scale super-resolution with one forward pass. It can now support 2x, 4x, 8x, and [2x, 4x] and [2x, 4x, 8x] super-resolution. - Advantage: The model can do multi-scale super-resolution with one forward pass. It can now support 2x, 4x, 8x, and [2x, 4x] and [2x, 4x, 8x] super-resolution.
- Disadvantage: It is slower than ESPCN and FSRCNN, and the accuracy is worse than EDSR. - Disadvantage: It is slower than ESPCN and FSRCNN, and the accuracy is worse than EDSR.
- Speed: < 0.1 sec for every scaling factor on 256x256 images on an Intel i7-9700K CPU. - Speed: < 0.1 sec for every scaling factor on 256x256 images on an Intel i7-9700K CPU.
- Original paper: [Deep laplacian pyramid networks for fast and accurate super-resolution](<https://arxiv.org/abs/1710.01992>) [4] - Original paper: [Deep laplacian pyramid networks for fast and accurate super-resolution](https://arxiv.org/pdf/1707.02921.pdf) [4]
### Benchmarks ### Benchmarks
Comparing different algorithms. Scale x4 on monarch.png. Comparing different algorithms. Scale x4 on monarch.png (768x512 image).
| | Inference time in seconds (CPU)| PSNR | SSIM | | | Inference time in seconds (CPU)| PSNR | SSIM |
| ------------- |:-------------------:| ---------:|--------:| | ------------- |:-------------------:| ---------:|--------:|
...@@ -82,6 +82,8 @@ Comparing different algorithms. Scale x4 on monarch.png. ...@@ -82,6 +82,8 @@ Comparing different algorithms. Scale x4 on monarch.png.
| Nearest neighbor |**0.00014** |23.5628 |0.81741 | | Nearest neighbor |**0.00014** |23.5628 |0.81741 |
| Lanczos |0.00101 |25.9115 |0.87057 | | Lanczos |0.00101 |25.9115 |0.87057 |
Refer to the benchmarks located in the tutorials for more detailed benchmarking.
### References ### References
[1] Bee Lim, Sanghyun Son, Heewon Kim, Seungjun Nah, and Kyoung Mu Lee, **"Enhanced Deep Residual Networks for Single Image Super-Resolution"**, <i> 2nd NTIRE: New Trends in Image Restoration and Enhancement workshop and challenge on image super-resolution in conjunction with **CVPR 2017**. </i> [[PDF](http://openaccess.thecvf.com/content_cvpr_2017_workshops/w12/papers/Lim_Enhanced_Deep_Residual_CVPR_2017_paper.pdf)] [[arXiv](https://arxiv.org/abs/1707.02921)] [[Slide](https://cv.snu.ac.kr/research/EDSR/Presentation_v3(release).pptx)] [1] Bee Lim, Sanghyun Son, Heewon Kim, Seungjun Nah, and Kyoung Mu Lee, **"Enhanced Deep Residual Networks for Single Image Super-Resolution"**, <i> 2nd NTIRE: New Trends in Image Restoration and Enhancement workshop and challenge on image super-resolution in conjunction with **CVPR 2017**. </i> [[PDF](http://openaccess.thecvf.com/content_cvpr_2017_workshops/w12/papers/Lim_Enhanced_Deep_Residual_CVPR_2017_paper.pdf)] [[arXiv](https://arxiv.org/abs/1707.02921)] [[Slide](https://cv.snu.ac.kr/research/EDSR/Presentation_v3(release).pptx)]
...@@ -90,4 +92,4 @@ Comparing different algorithms. Scale x4 on monarch.png. ...@@ -90,4 +92,4 @@ Comparing different algorithms. Scale x4 on monarch.png.
[3] Chao Dong, Chen Change Loy, Xiaoou Tang. **"Accelerating the Super-Resolution Convolutional Neural Network"**, <i> in Proceedings of European Conference on Computer Vision </i>**ECCV 2016**. [[PDF](http://personal.ie.cuhk.edu.hk/~ccloy/files/eccv_2016_accelerating.pdf)] [3] Chao Dong, Chen Change Loy, Xiaoou Tang. **"Accelerating the Super-Resolution Convolutional Neural Network"**, <i> in Proceedings of European Conference on Computer Vision </i>**ECCV 2016**. [[PDF](http://personal.ie.cuhk.edu.hk/~ccloy/files/eccv_2016_accelerating.pdf)]
[[arXiv](https://arxiv.org/abs/1608.00367)] [[Project Page](http://mmlab.ie.cuhk.edu.hk/projects/FSRCNN.html)] [[arXiv](https://arxiv.org/abs/1608.00367)] [[Project Page](http://mmlab.ie.cuhk.edu.hk/projects/FSRCNN.html)]
[4] Lai, W. S., Huang, J. B., Ahuja, N., and Yang, M. H., **"Deep laplacian pyramid networks for fast and accurate super-resolution"**, <i> In Proceedings of the IEEE conference on computer vision and pattern recognition </i>**CVPR 2017**. [[PDF](http://openaccess.thecvf.com/content_cvpr_2017/papers/Lai_Deep_Laplacian_Pyramid_CVPR_2017_paper.pdf)] [[arXiv](https://arxiv.org/abs/1710.01992)] [[Project Page](http://vllab.ucmerced.edu/wlai24/LapSRN/)] [4] Lai, W. S., Huang, J. B., Ahuja, N., and Yang, M. H., **"Deep laplacian pyramid networks for fast and accurate super-resolution"**, <i> In Proceedings of the IEEE conference on computer vision and pattern recognition </i>**CVPR 2017**. [[PDF](http://openaccess.thecvf.com/content_cvpr_2017/papers/Lai_Deep_Laplacian_Pyramid_CVPR_2017_paper.pdf)] [[arXiv](https://arxiv.org/abs/1710.01992)] [[Project Page](http://vllab.ucmerced.edu/wlai24/LapSRN/)]
\ No newline at end of file
...@@ -27,20 +27,21 @@ PERF_TEST_P(dnn_superres, upsample, testing::Combine(MODEL, IMAGES)) ...@@ -27,20 +27,21 @@ PERF_TEST_P(dnn_superres, upsample, testing::Combine(MODEL, IMAGES))
string model_filename = get<1>(model); string model_filename = get<1>(model);
int scale = get<2>(model); int scale = get<2>(model);
string model_path = getDataPath( TEST_DIR + "/" + model_filename ); string model_path = cvtest::findDataFile(TEST_DIR + "/" + model_filename);
string image_path = getDataPath( image_name ); string image_path = cvtest::findDataFile(image_name);
DnnSuperResImpl sr; DnnSuperResImpl sr;
sr.readModel(model_path); sr.readModel(model_path);
sr.setModel(model_name, scale); sr.setModel(model_name, scale);
Mat img = imread(image_path); Mat img = imread(image_path);
ASSERT_FALSE(img.empty()) << image_path;
Mat img_new(img.rows * scale, img.cols * scale, CV_8UC3); Mat result;
declare.in(img, WARMUP_RNG).out(img_new).iterations(10); TEST_CYCLE() { sr.upsample(img, result); }
TEST_CYCLE() { sr.upsample(img, img_new); } ASSERT_FALSE(result.empty());
SANITY_CHECK_NOTHING(); SANITY_CHECK_NOTHING();
} }
......
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include <iostream>
#include <opencv2/dnn_superres.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
using namespace dnn_superres;
int main(int argc, char *argv[])
{
// Check for valid command line arguments, print usage
// if insufficient arguments were given.
if ( argc < 4 ) {
cout << "usage: Arg 1: image | Path to image" << endl;
cout << "\t Arg 2: algorithm | bilinear, bicubic, edsr, espcn, fsrcnn or lapsrn" << endl;
cout << "\t Arg 3: scale | 2, 3 or 4 \n";
cout << "\t Arg 4: path to model file \n";
return -1;
}
string img_path = string(argv[1]);
string algorithm = string(argv[2]);
int scale = atoi(argv[3]);
string path = "";
if( argc > 4)
path = string(argv[4]);
// Load the image
Mat img = cv::imread(img_path);
Mat original_img(img);
if ( img.empty() )
{
std::cerr << "Couldn't load image: " << img << "\n";
return -2;
}
//Make dnn super resolution instance
DnnSuperResImpl sr;
Mat img_new;
if( algorithm == "bilinear" ){
resize(img, img_new, Size(), scale, scale, 2);
}
else if( algorithm == "bicubic" )
{
resize(img, img_new, Size(), scale, scale, 3);
}
else if( algorithm == "edsr" || algorithm == "espcn" || algorithm == "fsrcnn" || algorithm == "lapsrn" )
{
sr.readModel(path);
sr.setModel(algorithm, scale);
sr.upsample(img, img_new);
}
else{
std::cerr << "Algorithm not recognized. \n";
}
if ( img_new.empty() )
{
std::cerr << "Upsampling failed. \n";
return -3;
}
cout << "Upsampling succeeded. \n";
// Display image
cv::namedWindow("Initial Image", WINDOW_AUTOSIZE);
cv::imshow("Initial Image", img_new);
//cv::imwrite("./saved.jpg", img_new);
cv::waitKey(0);
return 0;
}
\ No newline at end of file
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <memory>
#include <string> #include <string>
#include <sstream> #include <map>
#include <numeric>
#include <algorithm>
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include <opencv2/core/utils/logger.hpp> #include <opencv2/core/utils/logger.hpp>
......
...@@ -44,12 +44,22 @@ void runSingleModel(std::string algorithm, int scale, std::string model_filename ...@@ -44,12 +44,22 @@ void runSingleModel(std::string algorithm, int scale, std::string model_filename
ASSERT_EQ(new_rows, result.rows); ASSERT_EQ(new_rows, result.rows);
} }
TEST(CV_DnnSuperResSingleOutputTest, accuracy) TEST(CV_DnnSuperResSingleOutputTest, accuracy_espcn_2)
{ {
//x2
runSingleModel("espcn", 2, "ESPCN_x2.pb"); runSingleModel("espcn", 2, "ESPCN_x2.pb");
} }
TEST(CV_DnnSuperResSingleOutputTest, accuracy_fsrcnn_2)
{
runSingleModel("fsrcnn", 2, "FSRCNN_x2.pb");
}
TEST(CV_DnnSuperResSingleOutputTest, accuracy_fsrcnn_3)
{
runSingleModel("fsrcnn", 3, "FSRCNN_x3.pb");
}
/****************************************************************************************\ /****************************************************************************************\
* Test multi output models * * Test multi output models *
\****************************************************************************************/ \****************************************************************************************/
...@@ -101,4 +111,4 @@ TEST(CV_DnnSuperResMultiOutputTest, accuracy) ...@@ -101,4 +111,4 @@ TEST(CV_DnnSuperResMultiOutputTest, accuracy)
runMultiModel("lapsrn", 4, "LapSRN_x4.pb", scales_4x, names_4x); runMultiModel("lapsrn", 4, "LapSRN_x4.pb", scales_4x, names_4x);
} }
}} }}
\ No newline at end of file
Super Resolution using CNNs {#tutorial_table_of_content_dnn_superres} Super Resolution using CNNs {#tutorial_table_of_content_dnn_superres}
============================ ===========================
- @subpage tutorial_dnn_superres_upscale_image_single
*Author:* Xavier Weber
How to upscale images using the 'dnn_superres' interface: single-output
- @subpage tutorial_dnn_superres_upscale_image_multi - @subpage tutorial_dnn_superres_upscale_image_multi
......
Upscaling images: single-output {#tutorial_dnn_superres_upscale_image_single}
===========================
In this tutorial you will learn how to use the 'dnn_superres' interface to upscale an image via pre-trained neural networks.
Building
----
When building OpenCV, run the following command to build the 'dnn_superres' module:
```make
cmake -DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -Dopencv_dnn_superres=ON <opencv_source_dir>
```
Or make sure you check the dnn_superres module in the GUI version of CMake: cmake-gui.
Source Code of the sample
-----------
@includelineno dnn_superres/samples/dnn_superres.cpp
Explanation
-----------
-# **Set header and namespaces**
@code{.cpp}
#include <opencv2/dnn_superres.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
using namespace dnn_superres;
@endcode
If you want you can set the namespace like the code above.
-# **Create the Dnn Superres object**
@code{.cpp}
DnnSuperResImpl sr;
@endcode
This is just to create the object, register the custom dnn layers and get access to the class functions.
-# **Read the model**
@code{.cpp}
path = "models/FSRCNN_x2.pb"
sr.readModel(path);
@endcode
This reads the TensorFlow model from the .pb file. Here 'path' is one of the pre-trained Tensorflow models' path file. You can download the models from OpenCV's GitHub, in the 'dnn_superres' module.
-# **Set the model**
@code{.cpp}
sr.setModel("fsrcnn", 2);
@endcode
Depending on the model you want to run, you have to set the algorithm and upscale factor. This is to know the desired algorithm and scale, even if you change the .pb file's name. For example: if you chose FSRCNN_x2.pb, your algorithm and scale will be 'fsrcnn' and 2, respectively. (Other algorithm options include "edsr", "espcn" and "lapsrn".)
-# **Upscale an image**
@code{.cpp}
Mat img = cv::imread(img_path);
Mat img_new;
sr.upsample(img, img_new);
@endcode
Now we can upscale any image. Load an image via the standard 'imread' function and create a new Mat for the destination image. Then simple
upscale. Your upscaled image is located in 'img_new'.
Original: ![](images/input.jpg)
Upscaled Image via FSRCNN: ![](images/fsrcnnOutput.jpg)
Upscaled Image via Bicubic Interpolation: ![](images/bicubicOutput.jpg)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment