Home | History | Annotate | Download | only in ocl
      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 (at) gmail.com>
     19  * Author: Wind Yuan <feng.yuan (at) intel.com>
     20  */
     21 
     22 #include "cv_edgetaper.h"
     23 
     24 namespace XCam {
     25 
     26 
     27 CVEdgetaper::CVEdgetaper ()
     28     : CVBaseClass ()
     29 {
     30 
     31 }
     32 
     33 void
     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
     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