• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * cv_edgetaper.cpp - used in deblurring to remove ringing artifacts
3  *
4  *  Copyright (c) 2016-2017 Intel Corporation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Andrey Parfenov <a1994ndrey@gmail.com>
19  * Author: Wind Yuan <feng.yuan@intel.com>
20  */
21 
22 #include "cv_edgetaper.h"
23 
24 namespace XCam {
25 
26 
CVEdgetaper()27 CVEdgetaper::CVEdgetaper ()
28     : CVBaseClass ()
29 {
30 
31 }
32 
33 void
create_weights(const cv::Mat & image,const cv::Mat & psf,cv::Mat & coefficients)34 CVEdgetaper::create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat &coefficients)
35 {
36     cv::Mat rows_proj, cols_proj;
37     cv::Mat rows_proj_border, cols_proj_border;
38     cv::Mat rows_cor, cols_cor;
39     // get psf rows and cols projections
40     cv::reduce (psf, rows_proj, 1, CV_REDUCE_SUM, -1);
41     cv::reduce (psf, cols_proj, 0, CV_REDUCE_SUM, -1);
42     // calculate correlation for psf projections
43     cv::copyMakeBorder (rows_proj, rows_proj_border, (psf.rows - 1) / 2, (psf.rows - 1) / 2, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all (0));
44     cv::copyMakeBorder (cols_proj, cols_proj_border, 0, 0,  (psf.cols - 1) / 2, (psf.cols - 1) / 2, cv::BORDER_CONSTANT, cv::Scalar::all (0));
45     cv::matchTemplate (rows_proj_border, rows_proj, rows_cor, CV_TM_CCORR);
46     cv::matchTemplate (cols_proj_border, cols_proj, cols_cor, CV_TM_CCORR);
47     // make it symmetric on both sides
48     cv::Mat rows_add = cv::Mat_<float>(1, 1) << rows_proj.at<float> (0, 0);
49     cv::Mat cols_add = cv::Mat_<float>(1, 1) << cols_proj.at<float> (0, 0);
50     cv::vconcat (rows_cor, rows_add, rows_cor);
51     cv::hconcat (cols_cor, cols_add, cols_cor);
52     double min, max;
53     cv::minMaxLoc (rows_cor, &min, &max);
54     rows_cor /= max;
55     cv::minMaxLoc (cols_cor, &min, &max);
56     cols_cor /= max;
57     // get matrix from projections
58     cv::Mat alpha = (cv::Scalar (1) - rows_proj) * (cv::Scalar (1) - cols_proj);
59     // expand it to the image size
60     int nc = image.cols / psf.cols + 1;
61     int nr = image.rows / psf.rows + 1;
62     cv::Mat expanded;
63     cv::repeat (alpha, nr, nc, expanded);
64     cv::Mat weights = expanded (cv::Rect (expanded.cols / 2 - image.cols / 2, expanded.rows / 2 - image.rows / 2, image.cols, image.rows));
65     coefficients = weights.clone ();
66 }
67 
68 void
edgetaper(const cv::Mat & img,const cv::Mat & psf,cv::Mat & output)69 CVEdgetaper::edgetaper (const cv::Mat &img, const cv::Mat &psf, cv::Mat &output)
70 {
71     cv::Mat blurred = cv::Mat::zeros (img.rows, img.cols, CV_32FC1);
72     // flip PSF to perform convolution
73     cv::Mat psf_flipped;
74     cv::flip (psf, psf_flipped, -1);
75     cv::filter2D (img, blurred, CV_32FC1, psf_flipped, cv::Point (-1, -1), 0, cv::BORDER_CONSTANT);
76     cv::Mat coefficients;
77     create_weights (img, psf, coefficients);
78     cv::Mat result;
79     img.convertTo (result, CV_32FC1);
80     result = result.mul (coefficients) + blurred.mul (cv::Scalar (1.0f) - coefficients);
81     output = result.clone ();
82 }
83 
84 }
85