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