aboutsummaryrefslogtreecommitdiff
path: root/modules/ocv/cv_edgetaper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ocv/cv_edgetaper.cpp')
-rw-r--r--modules/ocv/cv_edgetaper.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/modules/ocv/cv_edgetaper.cpp b/modules/ocv/cv_edgetaper.cpp
new file mode 100644
index 0000000..524caa7
--- /dev/null
+++ b/modules/ocv/cv_edgetaper.cpp
@@ -0,0 +1,77 @@
+/*
+ * cv_edgetaper.cpp - used in deblurring to remove ringing artifacts
+ *
+ * Copyright (c) 2016-2017 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Andrey Parfenov <a1994ndrey@gmail.com>
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "cv_edgetaper.h"
+
+namespace XCam {
+
+void
+CVEdgetaper::create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat &coefficients)
+{
+ cv::Mat rows_proj, cols_proj;
+ cv::Mat rows_proj_border, cols_proj_border;
+ cv::Mat rows_cor, cols_cor;
+ // get psf rows and cols projections
+ cv::reduce (psf, rows_proj, 1, cv::REDUCE_SUM, -1);
+ cv::reduce (psf, cols_proj, 0, cv::REDUCE_SUM, -1);
+ // calculate correlation for psf projections
+ cv::copyMakeBorder (rows_proj, rows_proj_border, (psf.rows - 1) / 2, (psf.rows - 1) / 2, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all (0));
+ cv::copyMakeBorder (cols_proj, cols_proj_border, 0, 0, (psf.cols - 1) / 2, (psf.cols - 1) / 2, cv::BORDER_CONSTANT, cv::Scalar::all (0));
+ cv::matchTemplate (rows_proj_border, rows_proj, rows_cor, cv::TM_CCORR);
+ cv::matchTemplate (cols_proj_border, cols_proj, cols_cor, cv::TM_CCORR);
+ // make it symmetric on both sides
+ cv::Mat rows_add = cv::Mat_<float>(1, 1) << rows_proj.at<float> (0, 0);
+ cv::Mat cols_add = cv::Mat_<float>(1, 1) << cols_proj.at<float> (0, 0);
+ cv::vconcat (rows_cor, rows_add, rows_cor);
+ cv::hconcat (cols_cor, cols_add, cols_cor);
+ double min, max;
+ cv::minMaxLoc (rows_cor, &min, &max);
+ rows_cor /= max;
+ cv::minMaxLoc (cols_cor, &min, &max);
+ cols_cor /= max;
+ // get matrix from projections
+ cv::Mat alpha = (cv::Scalar (1) - rows_proj) * (cv::Scalar (1) - cols_proj);
+ // expand it to the image size
+ int nc = image.cols / psf.cols + 1;
+ int nr = image.rows / psf.rows + 1;
+ cv::Mat expanded;
+ cv::repeat (alpha, nr, nc, expanded);
+ cv::Mat weights = expanded (cv::Rect (expanded.cols / 2 - image.cols / 2, expanded.rows / 2 - image.rows / 2, image.cols, image.rows));
+ coefficients = weights.clone ();
+}
+
+void
+CVEdgetaper::edgetaper (const cv::Mat &img, const cv::Mat &psf, cv::Mat &output)
+{
+ cv::Mat blurred = cv::Mat::zeros (img.rows, img.cols, CV_32FC1);
+ // flip PSF to perform convolution
+ cv::Mat psf_flipped;
+ cv::flip (psf, psf_flipped, -1);
+ cv::filter2D (img, blurred, CV_32FC1, psf_flipped, cv::Point (-1, -1), 0, cv::BORDER_CONSTANT);
+ cv::Mat coefficients;
+ create_weights (img, psf, coefficients);
+ cv::Mat result;
+ img.convertTo (result, CV_32FC1);
+ result = result.mul (coefficients) + blurred.mul (cv::Scalar (1.0f) - coefficients);
+ output = result.clone ();
+}
+
+}