aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Parfenov <a1994ndrey@gmail.com>2017-12-23 03:44:38 +0300
committerwindyuan <feng.yuan@intel.com>2017-12-25 09:59:29 +0800
commitf60f0a65705112bfa3ff3dc35d63d6896014ab8c (patch)
treee5dc31e920908dfa17b6b7269e6c96d464a5af7d
parentbe3ac1e217dd371c77983c812dfb149c258a3f42 (diff)
downloadlibxcam-f60f0a65705112bfa3ff3dc35d63d6896014ab8c.tar.gz
fix edgetaper
Signed-off-by: Andrey Parfenov <a1994ndrey@gmail.com>
-rw-r--r--modules/ocl/cv_edgetaper.cpp112
-rw-r--r--modules/ocl/cv_edgetaper.h7
-rw-r--r--modules/ocl/cv_image_deblurring.cpp53
-rw-r--r--modules/ocl/cv_image_deblurring.h6
-rw-r--r--tests/test-image-deblurring.cpp2
5 files changed, 83 insertions, 97 deletions
diff --git a/modules/ocl/cv_edgetaper.cpp b/modules/ocl/cv_edgetaper.cpp
index a07eeac..ab79238 100644
--- a/modules/ocl/cv_edgetaper.cpp
+++ b/modules/ocl/cv_edgetaper.cpp
@@ -25,86 +25,60 @@ namespace XCam {
CVEdgetaper::CVEdgetaper ()
- : CVBaseClass()
+ : CVBaseClass ()
{
}
void
-CVEdgetaper::normalized_autocorrelation (const cv::Mat &psf, cv::Mat &auto_correlation_psf)
+CVEdgetaper::create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat &coefficients)
{
- cv::Mat correlation;
- cv::copyMakeBorder (psf, auto_correlation_psf, psf.cols - 1, 0, psf.rows - 1, 0, cv::BORDER_CONSTANT, cv::Scalar::all(0));
- cv::filter2D (auto_correlation_psf, correlation, -1, psf, cv::Point(0, 0), 0, cv::BORDER_CONSTANT);
- cv::normalize (correlation, correlation, 0, 1.0f, cv::NORM_MINMAX);
- auto_correlation_psf = correlation.clone ();
+ 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::create_weights (cv::Mat &coefficients, const cv::Mat &psf)
-{
- int psfr_last = psf.rows - 1;
- int psfc_last = psf.cols - 1;
-
- cv::Mat auto_correlation_psf;
- normalized_autocorrelation(psf, auto_correlation_psf);
-
- for (int i = 0; i < coefficients.rows; i++)
- {
- for (int j = 0; j < coefficients.cols; j++) {
- if (i < psfr_last)
- {
- if (j < psfc_last)
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i, j);
- else if (psfc_last <= j && j < (coefficients.cols - psfc_last))
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i, psfc_last);
- else
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i, j - (coefficients.cols - 2 * psfc_last) + 1);
- }
- else if (psfr_last <= i && i < (coefficients.rows - psfr_last))
- {
- if (j < psfc_last)
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(psfr_last, j);
- else if (psfc_last <= j && j < (coefficients.cols - psfc_last))
- coefficients.at<float>(i, j) = 1.0f;
- else
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(psfr_last, j - (coefficients.cols - 2 * psfc_last) + 1);
- }
- else
- {
- if (j < psfc_last)
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i - (coefficients.rows - 2 * psfr_last) + 1, j);
- else if (psfc_last <= j && j < (coefficients.cols - psfc_last))
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i - (coefficients.rows - 2 * psfr_last) + 1, psfc_last);
- else
- coefficients.at<float>(i, j) = auto_correlation_psf.at<float>(i - (coefficients.rows - 2 * psfr_last) + 1, j - (coefficients.cols - 2 * psfc_last) + 1);
- }
- }
- }
-}
-
-cv::Mat
-CVEdgetaper::edgetaper (const cv::Mat &img, const cv::Mat &psf)
+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);
- cv::filter2D (img, blurred, CV_32F, psf, cv::Point(-1, -1), 0, cv::BORDER_CONSTANT);
-
- cv::Mat coefficients = cv::Mat::zeros (img.rows, img.cols, CV_32FC1);
- create_weights (coefficients, psf);
- cv::Mat result = img.clone ();
- result.convertTo (result, CV_32FC1);
- for (int i = 0; i < img.rows; i++)
- {
- for (int j = 0; j < img.cols; j++)
- {
- if (coefficients.at<float>(i, j) != 1.0f)
- {
- result.at<float>(i, j) = img.at<unsigned char>(i, j) * coefficients.at<float>(i, j) +
- blurred.at<float>(i, j) * (1.0f - coefficients.at<float>(i, j));
- }
- }
- }
- return result;
+ // 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 ();
}
}
diff --git a/modules/ocl/cv_edgetaper.h b/modules/ocl/cv_edgetaper.h
index 9c00fc7..1ead29f 100644
--- a/modules/ocl/cv_edgetaper.h
+++ b/modules/ocl/cv_edgetaper.h
@@ -30,17 +30,16 @@
namespace XCam {
+
class CVEdgetaper : public CVBaseClass
{
public:
explicit CVEdgetaper ();
-
- cv::Mat edgetaper (const cv::Mat &image, const cv::Mat &psf);
+ void edgetaper (const cv::Mat &image, const cv::Mat &psf, cv::Mat &output);
private:
- void create_weights (cv::Mat &coefficients, const cv::Mat &psf);
- void normalized_autocorrelation (const cv::Mat &psf, cv::Mat &auto_correlation_psf);
+ void create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat &coefficients);
XCAM_DEAD_COPY (CVEdgetaper);
};
diff --git a/modules/ocl/cv_image_deblurring.cpp b/modules/ocl/cv_image_deblurring.cpp
index c036b42..730eb42 100644
--- a/modules/ocl/cv_image_deblurring.cpp
+++ b/modules/ocl/cv_image_deblurring.cpp
@@ -25,12 +25,12 @@ namespace XCam {
CVImageDeblurring::CVImageDeblurring ()
- : CVBaseClass()
+ : CVBaseClass ()
{
- _helper = new CVImageProcessHelper();
- _sharp = new CVImageSharp();
- _edgetaper = new CVEdgetaper();
- _wiener = new CVWienerFilter();
+ _helper = new CVImageProcessHelper ();
+ _sharp = new CVImageSharp ();
+ _edgetaper = new CVEdgetaper ();
+ _wiener = new CVWienerFilter ();
}
void
@@ -152,35 +152,52 @@ CVImageDeblurring::estimate_kernel_size (const cv::Mat &image)
}
void
-CVImageDeblurring::blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, cv::Mat &kernel, int kernel_size, float noise_power)
+CVImageDeblurring::blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, cv::Mat &kernel, int kernel_size, float noise_power, bool use_edgetaper)
{
cv::Mat gray_blurred;
cv::cvtColor (blurred, gray_blurred, CV_BGR2GRAY);
- if (noise_power < 0) {
+ if (noise_power < 0)
+ {
cv::Mat median_blurred;
medianBlur (gray_blurred, median_blurred, 3);
noise_power = 1.0f / _helper->get_snr (gray_blurred, median_blurred);
- XCAM_LOG_DEBUG("estimated inv snr %f", noise_power);
+ XCAM_LOG_DEBUG ("estimated inv snr %f", noise_power);
}
- if (kernel_size < 0) {
+ if (kernel_size < 0)
+ {
kernel_size = estimate_kernel_size (gray_blurred);
- XCAM_LOG_DEBUG("estimated kernel size %d", kernel_size);
+ XCAM_LOG_DEBUG ("estimated kernel size %d", kernel_size);
+ }
+ if (use_edgetaper) {
+ XCAM_LOG_DEBUG ("edgetaper will be used");
+ }
+ else {
+ XCAM_LOG_DEBUG ("edgetaper will not be used");
}
- std::vector<cv::Mat> blurred_rgb(3);
- cv::split(blurred, blurred_rgb);
- std::vector<cv::Mat> deblurred_rgb(3);
+ std::vector<cv::Mat> blurred_rgb (3);
+ cv::split (blurred, blurred_rgb);
+ std::vector<cv::Mat> deblurred_rgb (3);
cv::Mat result_deblurred;
cv::Mat result_kernel;
blind_deblurring_one_channel (gray_blurred, result_kernel, kernel_size, noise_power);
for (int i = 0; i < 3; i++)
{
- _wiener->wiener_filter (_edgetaper->edgetaper(blurred_rgb[i], result_kernel), result_kernel, deblurred_rgb[i], noise_power);
+ cv::Mat input;
+ if (use_edgetaper)
+ {
+ _edgetaper->edgetaper (blurred_rgb[i], result_kernel, input);
+ }
+ else
+ {
+ input = blurred_rgb[i].clone ();
+ }
+ _wiener->wiener_filter (input, result_kernel, deblurred_rgb[i], noise_power);
_helper->apply_constraints (deblurred_rgb[i], 0);
}
cv::merge (deblurred_rgb, result_deblurred);
result_deblurred.convertTo (result_deblurred, CV_8UC3);
fastNlMeansDenoisingColored (result_deblurred, deblurred, 3, 3, 7, 21);
- kernel = result_kernel.clone();
+ kernel = result_kernel.clone ();
}
void
@@ -189,19 +206,17 @@ CVImageDeblurring::blind_deblurring_one_channel (const cv::Mat &blurred, cv::Mat
cv::Mat kernel_current = cv::Mat::zeros (kernel_size, kernel_size, CV_32FC1);
cv::Mat deblurred_current = _helper->erosion (blurred, 2, 0);
float sigmar = 20;
- cv::Mat enhanced_blurred = blurred.clone ();
for (int i = 0; i < _config.iterations; i++)
{
cv::Mat sharpened = _sharp->sharp_image_gray (deblurred_current, sigmar);
_wiener->wiener_filter (blurred, sharpened.clone (), kernel_current, noise_power);
- kernel_current = kernel_current (cv::Rect(0, 0, kernel_size, kernel_size));
+ kernel_current = kernel_current (cv::Rect (0, 0, kernel_size, kernel_size));
double min_val;
double max_val;
cv::minMaxLoc (kernel_current, &min_val, &max_val);
_helper->apply_constraints (kernel_current, (float)max_val / 20);
_helper->normalize_weights (kernel_current);
- enhanced_blurred = _edgetaper->edgetaper (blurred, kernel_current);
- _wiener->wiener_filter (enhanced_blurred, kernel_current.clone(), deblurred_current, noise_power);
+ _wiener->wiener_filter (blurred, kernel_current.clone(), deblurred_current, noise_power);
_helper->apply_constraints (deblurred_current, 0);
sigmar *= 0.9;
}
diff --git a/modules/ocl/cv_image_deblurring.h b/modules/ocl/cv_image_deblurring.h
index f46de35..afac22c 100644
--- a/modules/ocl/cv_image_deblurring.h
+++ b/modules/ocl/cv_image_deblurring.h
@@ -35,7 +35,7 @@ namespace XCam {
struct CVIDConfig {
int iterations; // number of iterations for IBD algorithm
- CVIDConfig (unsigned int _iterations = 200)
+ CVIDConfig (unsigned int _iterations = 50)
{
iterations = _iterations;
}
@@ -46,11 +46,9 @@ class CVImageDeblurring : public CVBaseClass
public:
explicit CVImageDeblurring ();
-
void set_config (CVIDConfig config);
CVIDConfig get_config ();
-
- void blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, cv::Mat &kernel, int kernel_size = -1, float noise_power = -1.0f);
+ void blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, cv::Mat &kernel, int kernel_size = -1, float noise_power = -1.0f, bool use_edgetaper = true);
private:
void blind_deblurring_one_channel (const cv::Mat &blurred, cv::Mat &kernel, int kernel_size, float noise_power);
diff --git a/tests/test-image-deblurring.cpp b/tests/test-image-deblurring.cpp
index 91f019f..a5b24ab 100644
--- a/tests/test-image-deblurring.cpp
+++ b/tests/test-image-deblurring.cpp
@@ -111,7 +111,7 @@ int main (int argc, char *argv[])
}
cv::Mat deblurred;
cv::Mat kernel;
- imageDeblurring->blind_deblurring (blurred, deblurred, kernel, -1, -1, true);
+ imageDeblurring->blind_deblurring (blurred, deblurred, kernel, -1, -1, false);
float input_sharp = sharp->measure_sharp (blurred);
float output_sharp = sharp->measure_sharp (deblurred);
if (need_save_output)