Merge remote-tracking branch 'origin/upstream-master' into master am: bc0d32c531 am: 2d41fa5ba9
am: d62e011446

Change-Id: Iab0436dad8e2e9bee6af64f803f50622f6862d4c
diff --git a/modules/ocl/cl_fisheye_handler.cpp b/modules/ocl/cl_fisheye_handler.cpp
index 93b62a5..a7866c5 100644
--- a/modules/ocl/cl_fisheye_handler.cpp
+++ b/modules/ocl/cl_fisheye_handler.cpp
@@ -393,7 +393,7 @@
         size_t row_pitch;
         size_t slice_pitch;
         XCamReturn ret = _geo_table->enqueue_map ((void *&)map_ptr, origin, region, &row_pitch, &slice_pitch, CL_MAP_WRITE);
-        XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+        XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "CLFisheyeHandler mesh table failed in enqueue_map");
 
         for (uint32_t row = 0; row < table_height; row++) {
             for(uint32_t col = 0; col < table_width; col++) {
diff --git a/modules/ocl/cl_image_handler.cpp b/modules/ocl/cl_image_handler.cpp
index c359bcd..f9fc56c 100644
--- a/modules/ocl/cl_image_handler.cpp
+++ b/modules/ocl/cl_image_handler.cpp
@@ -230,6 +230,8 @@
 XCamReturn
 CLImageHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
 {
+    XCAM_UNUSED (input);
+    XCAM_UNUSED (output);
     XCAM_ASSERT (input.ptr () && output.ptr ());
     return XCAM_RETURN_NO_ERROR;
 }
diff --git a/modules/ocl/cl_kernel.cpp b/modules/ocl/cl_kernel.cpp
index 62dfcb7..fdda8ec 100644
--- a/modules/ocl/cl_kernel.cpp
+++ b/modules/ocl/cl_kernel.cpp
@@ -433,6 +433,7 @@
     KernelUserData *kernel_data = (KernelUserData *)data;
     XCAM_ASSERT (event == kernel_data->event->get_event_id ());
     XCAM_UNUSED (status);
+    XCAM_UNUSED (event);
 
     delete kernel_data;
 }
diff --git a/modules/ocl/cl_pyramid_blender.cpp b/modules/ocl/cl_pyramid_blender.cpp
index c0f4dce..d42fdcf 100644
--- a/modules/ocl/cl_pyramid_blender.cpp
+++ b/modules/ocl/cl_pyramid_blender.cpp
@@ -353,7 +353,7 @@
             cl_desc.width = XCAM_ALIGN_UP (this->blend_width, XCAM_CL_BLENDER_ALIGNMENT_X) / 8;
             cl_desc.height = XCAM_ALIGN_UP (this->blend_height, divider_vert[i_plane]) / divider_vert[i_plane];
             uint32_t row_pitch = CLImage::calculate_pixel_bytes (cl_desc.format) *
-                                     XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
+                                 XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
             uint32_t size = row_pitch * cl_desc.height;
             SmartPtr<CLBuffer> cl_buf = new CLBuffer (context, size);
             XCAM_ASSERT (cl_buf.ptr () && cl_buf->is_valid ());
@@ -379,7 +379,11 @@
     this->blend_mask[0] = new CLBuffer(context, mask_size);
     float *blend_ptr = NULL;
     XCamReturn ret = this->blend_mask[0]->enqueue_map((void*&)blend_ptr, 0, mask_size);
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    if (!xcam_ret_is_ok (ret)) {
+        XCAM_LOG_ERROR ("PyramidLayer init layer0 failed in blend_mask mem_map");
+        return;
+    }
+
     for (uint32_t i_ptr = 0; i_ptr < this->mask_width[0]; ++i_ptr) {
         if (i_ptr <= this->mask_width[0] / 2)
             blend_ptr[i_ptr] = 1.0f;
@@ -438,7 +442,7 @@
 
             //gauss y image created by cl buffer
             row_pitch = CLImage::calculate_pixel_bytes (cl_desc_set.format) *
-                            XCAM_ALIGN_UP (cl_desc_set.width, XCAM_CL_IMAGE_ALIGNMENT_X);
+                        XCAM_ALIGN_UP (cl_desc_set.width, XCAM_CL_IMAGE_ALIGNMENT_X);
             size = row_pitch * cl_desc_set.height;
             cl_buf = new CLBuffer (context, size);
             XCAM_ASSERT (cl_buf.ptr () && cl_buf->is_valid ());
@@ -451,7 +455,7 @@
         cl_desc_set.width = XCAM_ALIGN_UP (this->blend_width, XCAM_CL_BLENDER_ALIGNMENT_X) / 8;
         cl_desc_set.height = XCAM_ALIGN_UP (this->blend_height, divider_vert[plane]) / divider_vert[plane];
         row_pitch = CLImage::calculate_pixel_bytes (cl_desc_set.format) *
-                        XCAM_ALIGN_UP (cl_desc_set.width, XCAM_CL_IMAGE_ALIGNMENT_X);
+                    XCAM_ALIGN_UP (cl_desc_set.width, XCAM_CL_IMAGE_ALIGNMENT_X);
         size = row_pitch * cl_desc_set.height;
         cl_buf = new CLBuffer (context, size);
         XCAM_ASSERT (cl_buf.ptr () && cl_buf->is_valid ());
@@ -491,9 +495,9 @@
     float *from_ptr = NULL;
     float *to_ptr = NULL;
     ret = this->blend_mask[1]->enqueue_map ((void*&)to_ptr, 0, this->mask_width[1] * sizeof(float));
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), false, "PyramidLayer copy mask failed in blend_mask[1] mem_map");
     ret = this->blend_mask[0]->enqueue_map((void*&)from_ptr, 0, this->mask_width[0] * sizeof(float));
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), false, "PyramidLayer copy mask failed in blend_mask[0] mem_map");
 
     for (int i = 0; i < (int)this->mask_width[1]; ++i) {
         if (i * 2 + 1 >= (int)this->mask_width[0]) { // todo i* 2 + 1
@@ -532,7 +536,10 @@
 
     float *mask_ptr = NULL;
     XCamReturn ret = pyr_layer.blend_mask[plane]->enqueue_map ((void*&)mask_ptr, 0, pyr_layer.mask_width[plane] * sizeof(float));
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    if (!xcam_ret_is_ok (ret)) {
+        XCAM_LOG_ERROR ("CLPyramidBlender dump mask failed in blend_mask(layer:%d) mem_map", layer);
+        return;
+    }
 
     printf ("layer(%d)(-%s) mask, width:%d\n", layer, (is_uv ? "UV" : "Y"), pyr_layer.mask_width[plane]);
     for (uint32_t i = 0; i < pyr_layer.mask_width[plane]; ++i) {
@@ -560,10 +567,10 @@
     XCAM_ASSERT (to.blend_mask[0].ptr ());
     float *mask0_ptr = NULL;
     ret = to.blend_mask[0]->enqueue_map((void*&)mask0_ptr, 0, mask_size);
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), false, "gauss_fill_mask failed in destination image mem_map");
 
     ret = prev.blend_mask[0]->enqueue_map((void*&)pre_ptr, 0, prev_size);
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), false, "gauss_fill_mask failed in source image mem_map");
 
     for (i = 0; i < (int)to.blend_width; ++i) {
         if (i * 2 + 1 >= (int)prev.mask_width[0]) { // todo i* 2 + 1
@@ -659,7 +666,7 @@
     cl_desc.width = _seam_width / 8;
     cl_desc.height = _seam_height;
     cl_desc.row_pitch = CLImage::calculate_pixel_bytes (cl_desc.format) *
-                            XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
+                        XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
 
     uint32_t image_diff_size = cl_desc.row_pitch * _seam_height;
     SmartPtr<CLBuffer> cl_diff_buf = new CLBuffer (context, image_diff_size);
@@ -695,7 +702,7 @@
         cl_desc.width = mask_width / 8;
         cl_desc.height = mask_height;
         cl_desc.row_pitch = CLImage::calculate_pixel_bytes (cl_desc.format) *
-                                XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
+                            XCAM_ALIGN_UP (cl_desc.width, XCAM_CL_IMAGE_ALIGNMENT_X);
 
         uint32_t mask_size = cl_desc.row_pitch * mask_height;
         SmartPtr<CLBuffer> cl_buf0 = new CLBuffer (context, mask_size);
diff --git a/modules/ocl/cl_utils.cpp b/modules/ocl/cl_utils.cpp
index 55b59f5..b8ce3a9 100644
--- a/modules/ocl/cl_utils.cpp
+++ b/modules/ocl/cl_utils.cpp
@@ -60,7 +60,7 @@
     size_t slice_pitch;
 
     XCamReturn ret = image->enqueue_map (ptr, origin, region, &row_pitch, &slice_pitch, CL_MAP_READ);
-    XCAM_ASSERT (ret == XCAM_RETURN_NO_ERROR);
+    XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), false, "dump image failed in enqueue_map");
     XCAM_ASSERT (ptr);
     XCAM_ASSERT (row_pitch == desc.row_pitch);
     uint8_t *buf_start = (uint8_t *)ptr;
@@ -156,7 +156,9 @@
 
     VideoBufferPlanarInfo planar;
     const VideoBufferInfo info = buf->get_video_info ();
-    XCAM_ASSERT ((width == info.width) && (height == info.height));
+    XCAM_FAIL_RETURN (
+        DEBUG, (width == info.width) && (height == info.height), XCAM_RETURN_ERROR_PARAM,
+        "convert mem to video buffer failed since image sizes are not matched.");
 
     uint8_t *out_mem = buf->map ();
     XCAM_FAIL_RETURN (ERROR, out_mem, XCAM_RETURN_ERROR_MEM, "map buffer failed");
diff --git a/modules/ocl/cl_video_stabilizer.cpp b/modules/ocl/cl_video_stabilizer.cpp
index 66deadf..73b92fe 100644
--- a/modules/ocl/cl_video_stabilizer.cpp
+++ b/modules/ocl/cl_video_stabilizer.cpp
@@ -109,6 +109,7 @@
 {
     XCamReturn ret = XCAM_RETURN_NO_ERROR;
     XCAM_ASSERT (input.ptr () && output.ptr ());
+    XCAM_UNUSED (output);
 
     if (_input_buf_list.size () >= 2 * _filter_radius + 1) {
         _input_buf_list.pop_front ();
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 @@
 
 
 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_feature_match.cpp b/modules/ocl/cv_feature_match.cpp
index d670446..e4e2ea8 100644
--- a/modules/ocl/cv_feature_match.cpp
+++ b/modules/ocl/cv_feature_match.cpp
@@ -121,12 +121,13 @@
 {
     cv::_InputOutputArray debug_img;
     cv::Size img0_size = image0.size ();
-    cv::Size img1_size = image1.size ();
-    XCAM_ASSERT (img0_size.height == img1_size.height);
+    XCAM_ASSERT (img0_size.height == image1.rows ());
+    XCAM_UNUSED (image1);
 
 #if XCAM_CV_FM_DEBUG
     cv::Mat mat;
     cv::UMat umat;
+    cv::Size img1_size = image1.size ();
     cv::Size size (img0_size.width + img1_size.width, img0_size.height);
 
     if (image0.isUMat ()) {
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 @@
 
 
 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 @@
 }
 
 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);
     }
-    std::vector<cv::Mat> blurred_rgb(3);
-    cv::split(blurred, blurred_rgb);
-    std::vector<cv::Mat> deblurred_rgb(3);
+    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);
     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 @@
     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 @@
 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 @@
 
 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/modules/ocl/cv_image_process_helper.cpp b/modules/ocl/cv_image_process_helper.cpp
index 9698acc..0d08289 100644
--- a/modules/ocl/cv_image_process_helper.cpp
+++ b/modules/ocl/cv_image_process_helper.cpp
@@ -25,7 +25,7 @@
 
 
 CVImageProcessHelper::CVImageProcessHelper ()
-    : CVBaseClass()
+    : CVBaseClass ()
 {
 
 }
@@ -34,11 +34,11 @@
 CVImageProcessHelper::erosion (const cv::Mat &image, int erosion_size, int erosion_type)
 {
     cv::Mat element = cv::getStructuringElement (erosion_type,
-                      cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1 ),
-                      cv::Point(erosion_size, erosion_size));
+                      cv::Size (2 * erosion_size + 1, 2 * erosion_size + 1),
+                      cv::Point (erosion_size, erosion_size));
     cv::Mat eroded;
     cv::erode (image, eroded, element);
-    return eroded.clone();
+    return eroded.clone ();
 }
 
 float
@@ -55,17 +55,6 @@
     return res;
 }
 
-cv::Mat
-CVImageProcessHelper::get_auto_correlation (const cv::Mat &image)
-{
-    cv::Mat dst;
-    cv::Laplacian (image, dst, -1, 3, 1, 0, cv::BORDER_CONSTANT);
-    dst.convertTo (dst, CV_32FC1);
-    cv::Mat correlation;
-    cv::filter2D (dst, correlation, -1, dst, cv::Point(-1, -1), 0, cv::BORDER_CONSTANT);
-    return correlation.clone ();
-}
-
 void
 CVImageProcessHelper::compute_dft (const cv::Mat &image, cv::Mat &result)
 {
@@ -73,7 +62,7 @@
     int m = cv::getOptimalDFTSize (image.rows);
     int n = cv::getOptimalDFTSize (image.cols);
     cv::copyMakeBorder (image, padded, 0, m - image.rows, 0, n - image.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
-    cv::Mat planes[] = {cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32FC1)};
+    cv::Mat planes[] = {cv::Mat_<float> (padded), cv::Mat::zeros (padded.size (), CV_32FC1)};
     cv::merge (planes, 2, result);
     cv::dft (result, result);
 }
@@ -103,24 +92,11 @@
     }
 }
 
-// weights will be symmetric and sum(weights elements) == 1
 void
 CVImageProcessHelper::normalize_weights (cv::Mat &weights)
 {
     weights.convertTo (weights, CV_32FC1);
-    float sum = 0;
-    for (int i = 0; i < weights.rows; i++)
-    {
-        for (int j = 0; j <= i; j++)
-        {
-            weights.at<float>(i, j) = (weights.at<float>(i, j) + weights.at<float>(j, i)) / 2;
-            weights.at<float>(j, i) = weights.at<float>(i, j);
-            if (j == i)
-                sum += weights.at<float>(i, j);
-            else
-                sum += (2 * weights.at<float>(i, j));
-        }
-    }
+    float sum = cv::sum (weights)[0];
     weights /= sum;
 }
 
diff --git a/modules/ocl/cv_image_process_helper.h b/modules/ocl/cv_image_process_helper.h
index d1dbb72..137ff6b 100644
--- a/modules/ocl/cv_image_process_helper.h
+++ b/modules/ocl/cv_image_process_helper.h
@@ -37,12 +37,10 @@
 
     void compute_dft (const cv::Mat &image, cv::Mat &result);
     void compute_idft (cv::Mat *input, cv::Mat &result);
-    void apply_constraints (cv::Mat &image, float threshold_min_value, float threshold_max_value = 255.0f, float min_value = 0.0f, float max_value = 255.0f);
+    void apply_constraints (cv::Mat &image, float threshold_min_value = 0.0f, float threshold_max_value = 255.0f, float min_value = 0.0f, float max_value = 255.0f);
     float get_snr (const cv::Mat &noisy, const cv::Mat &noiseless);
     cv::Mat erosion (const cv::Mat &image, int erosion_size, int erosion_type);
-    // weights will be symmetric and sum(weights elements) == 1
     void normalize_weights (cv::Mat &weights);
-    cv::Mat get_auto_correlation (const cv::Mat &image);
 
     XCAM_DEAD_COPY (CVImageProcessHelper);
 };
diff --git a/modules/ocl/cv_image_sharp.cpp b/modules/ocl/cv_image_sharp.cpp
index 7ca087b..0a309af 100644
--- a/modules/ocl/cv_image_sharp.cpp
+++ b/modules/ocl/cv_image_sharp.cpp
@@ -25,7 +25,7 @@
 
 
 CVImageSharp::CVImageSharp ()
-    : CVBaseClass()
+    : CVBaseClass ()
 {
 
 }
@@ -36,34 +36,24 @@
     cv::Mat temp_image;
     image.convertTo (temp_image, CV_32FC1);
     cv::Mat bilateral_image;
-    cv::bilateralFilter (image, bilateral_image, 5, sigmar, 2);
+    cv::bilateralFilter (temp_image, bilateral_image, 5, sigmar, 2);
 
     cv::Mat sharp_filter = (cv::Mat_<float>(3, 3) << -1, -1, -1, -1, 8, -1, -1, -1, -1);
     cv::Mat filtered_image;
     cv::filter2D (bilateral_image, filtered_image, -1, sharp_filter);
-    filtered_image.convertTo (filtered_image, CV_32FC1);
     cv::normalize (filtered_image, filtered_image, 0, 255.0f, cv::NORM_MINMAX);
-
     cv::Mat sharpened = temp_image + filtered_image;
     cv::normalize (sharpened, sharpened, 0, 255.0f, cv::NORM_MINMAX);
     return sharpened.clone ();
 }
 
-
 float
 CVImageSharp::measure_sharp (const cv::Mat &image)
 {
     cv::Mat dst;
     cv::Laplacian (image, dst, -1, 3, 1, 0, cv::BORDER_CONSTANT);
     dst.convertTo (dst, CV_8UC1);
-    float sum = 0;
-    for (int i = 0; i < image.rows; i++)
-    {
-        for (int j = 0; j < image.cols; j++)
-        {
-            sum += dst.at<unsigned char>(i, j);
-        }
-    }
+    float sum = cv::sum (dst)[0];
     sum /= (image.rows * image.cols);
     return sum;
 }
diff --git a/modules/ocl/cv_wiener_filter.cpp b/modules/ocl/cv_wiener_filter.cpp
index fb3401e..ff96e5c 100644
--- a/modules/ocl/cv_wiener_filter.cpp
+++ b/modules/ocl/cv_wiener_filter.cpp
@@ -25,20 +25,20 @@
 
 
 CVWienerFilter::CVWienerFilter ()
-    : CVBaseClass()
+    : CVBaseClass ()
 {
-    _helpers = new CVImageProcessHelper();
+    _helpers = new CVImageProcessHelper ();
 }
 
 void
 CVWienerFilter::wiener_filter (const cv::Mat &blurred_image, const cv::Mat &known, cv::Mat &unknown, float noise_power)
 {
-    int image_w = blurred_image.size().width;
-    int image_h = blurred_image.size().height;
+    int image_w = blurred_image.size ().width;
+    int image_h = blurred_image.size ().height;
     cv::Mat y_ft;
     _helpers->compute_dft (blurred_image, y_ft);
 
-    cv::Mat padded = cv::Mat::zeros(image_h, image_w, CV_32FC1);
+    cv::Mat padded = cv::Mat::zeros (image_h, image_w, CV_32FC1);
     int padx = padded.cols - known.cols;
     int pady = padded.rows - known.rows;
     cv::copyMakeBorder (known, padded, 0, pady, 0, padx, cv::BORDER_CONSTANT, cv::Scalar::all(0));
@@ -47,22 +47,22 @@
 
     cv::Mat temp_unknown;
     cv::Mat unknown_ft[2];
-    unknown_ft[0] = cv::Mat::zeros(image_h, image_w, CV_32FC1);
-    unknown_ft[1] = cv::Mat::zeros(image_h, image_w, CV_32FC1);
+    unknown_ft[0] = cv::Mat::zeros (image_h, image_w, CV_32FC1);
+    unknown_ft[1] = cv::Mat::zeros (image_h, image_w, CV_32FC1);
 
     cv::Mat denominator;
-    cv::Mat denominator_splitted[] = {cv::Mat::zeros(blurred_image.size(), CV_32FC1), cv::Mat::zeros(blurred_image.size(), CV_32FC1)};
+    cv::Mat denominator_splitted[] = {cv::Mat::zeros (blurred_image.size (), CV_32FC1), cv::Mat::zeros (blurred_image.size (), CV_32FC1)};
     cv::mulSpectrums (padded_ft, padded_ft, denominator, 0, true);
     cv::split (denominator, denominator_splitted);
-    denominator_splitted[0] = denominator_splitted[0](cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
+    denominator_splitted[0] = denominator_splitted[0] (cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
     denominator_splitted[0] += cv::Scalar (noise_power);
 
     cv::Mat numerator;
-    cv::Mat numerator_splitted[] = {cv::Mat::zeros(blurred_image.size(), CV_32FC1), cv::Mat::zeros(blurred_image.size(), CV_32FC1)};
+    cv::Mat numerator_splitted[] = {cv::Mat::zeros (blurred_image.size (), CV_32FC1), cv::Mat::zeros (blurred_image.size (), CV_32FC1)};
     cv::mulSpectrums (y_ft, padded_ft, numerator, 0, true);
     cv::split (numerator, numerator_splitted);
-    numerator_splitted[0] = numerator_splitted[0](cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
-    numerator_splitted[1] = numerator_splitted[1](cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
+    numerator_splitted[0] = numerator_splitted[0] (cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
+    numerator_splitted[1] = numerator_splitted[1] (cv::Rect (0, 0, blurred_image.cols, blurred_image.rows));
     cv::divide (numerator_splitted[0], denominator_splitted[0], unknown_ft[0]);
     cv::divide (numerator_splitted[1], denominator_splitted[0], unknown_ft[1]);
     _helpers->compute_idft (unknown_ft, temp_unknown);
diff --git a/modules/soft/cv_capi_feature_match.cpp b/modules/soft/cv_capi_feature_match.cpp
index c4a38ac..0e0081c 100644
--- a/modules/soft/cv_capi_feature_match.cpp
+++ b/modules/soft/cv_capi_feature_match.cpp
@@ -134,8 +134,8 @@
 {
     CvMat debug_image;
     CvSize img0_size = cvSize(((CvMat*)image0)->width, ((CvMat*)image0)->height);
-    CvSize img1_size = cvSize(((CvMat*)image1)->width, ((CvMat*)image1)->height);
-    XCAM_ASSERT (img0_size.height == img1_size.height);
+    XCAM_ASSERT (img0_size.height == ((CvMat*)image1)->height);
+    XCAM_UNUSED (image1);
 
     std::vector<float> offsets;
     float offset_sum = 0.0f;
@@ -144,6 +144,7 @@
     offsets.reserve (corner0.size ());
 
 #if XCAM_CV_CAPI_FM_DEBUG
+    CvSize img1_size = cvSize(((CvMat*)image1)->width, ((CvMat*)image1)->height);
     cv::Mat mat;
     mat.create (img0_size.height, img0_size.width + img1_size.width, ((CvMat*)image0)->type);
     debug_image = cvMat (img0_size.height, img0_size.width + img1_size.width, ((CvMat*)image0)->type, mat.ptr());
diff --git a/modules/soft/soft_geo_mapper.cpp b/modules/soft/soft_geo_mapper.cpp
index 88ee870..478b025 100644
--- a/modules/soft/soft_geo_mapper.cpp
+++ b/modules/soft/soft_geo_mapper.cpp
@@ -178,6 +178,7 @@
 SoftGeoMapper::remap_task_done (
     const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
 {
+    XCAM_UNUSED (worker);
     XCAM_ASSERT (worker.ptr () == _map_task.ptr ());
     SmartPtr<XCamSoftTasks::GeoMapTask::Args> args = base.dynamic_cast_ptr<XCamSoftTasks::GeoMapTask::Args> ();
     XCAM_ASSERT (args.ptr ());
diff --git a/modules/soft/soft_stitcher.cpp b/modules/soft/soft_stitcher.cpp
index 895597a..c345dcd 100644
--- a/modules/soft/soft_stitcher.cpp
+++ b/modules/soft/soft_stitcher.cpp
@@ -843,6 +843,7 @@
     const SmartPtr<Worker::Arguments> &base,
     const XCamReturn error)
 {
+    XCAM_UNUSED (worker);
     XCAM_ASSERT (worker.ptr ());
     SmartPtr<SoftSitcherPriv::StitcherCopyArgs> args = base.dynamic_cast_ptr<SoftSitcherPriv::StitcherCopyArgs> ();
     XCAM_ASSERT (args.ptr ());
diff --git a/tests/test-image-deblurring.cpp b/tests/test-image-deblurring.cpp
index d71a448..bc681b2 100644
--- a/tests/test-image-deblurring.cpp
+++ b/tests/test-image-deblurring.cpp
@@ -21,46 +21,85 @@
 
 #include "test_common.h"
 #include "test_inline.h"
+
 #include <unistd.h>
 #include <getopt.h>
 #include <image_file_handle.h>
-#include <ocl/cl_device.h>
-#include <ocl/cl_context.h>
-#include <ocl/cl_blender.h>
+#include <ocl/cv_image_sharp.h>
+#include <ocl/cv_wiener_filter.h>
 #include <ocl/cv_image_deblurring.h>
+
 #include <opencv2/opencv.hpp>
 #include <opencv2/core/ocl.hpp>
 
 using namespace XCam;
 
 static void
-usage(const char* arg0)
+usage (const char* arg0)
 {
     printf ("Usage: %s --input file --output file\n"
             "\t--input,    input image(RGB)\n"
             "\t--output,   output image(RGB) PREFIX\n"
+            "\t--blind,    optional, blind or non-blind deblurring, default true; select from [true/false]\n"
             "\t--save,     optional, save file or not, default true; select from [true/false]\n"
             "\t--help,     usage\n",
             arg0);
 }
 
+static void
+blind_deblurring (cv::Mat &input_image, cv::Mat &output_image)
+{
+    SmartPtr<CVImageDeblurring> image_deblurring = new CVImageDeblurring ();
+    cv::Mat kernel;
+    image_deblurring->blind_deblurring (input_image, output_image, kernel, -1, -1, false);
+}
+
+static void
+non_blind_deblurring (cv::Mat &input_image, cv::Mat &output_image)
+{
+    SmartPtr<CVWienerFilter> wiener_filter = new CVWienerFilter ();
+    cv::cvtColor (input_image, input_image, CV_BGR2GRAY);
+    // use simple motion blur kernel
+    int kernel_size = 13;
+    cv::Mat kernel = cv::Mat::zeros (kernel_size, kernel_size, CV_32FC1);
+    for (int i = 0; i < kernel_size; i++)
+    {
+        kernel.at<float> ((kernel_size - 1) / 2, i) = 1.0;
+    }
+    kernel /= kernel_size;
+    //flip kernel to perform convolution
+    cv::Mat conv_kernel;
+    cv::flip (kernel, conv_kernel, -1);
+    cv::Mat blurred;
+    cv::filter2D (input_image, blurred, CV_32FC1, conv_kernel, cv::Point(-1, -1), 0, cv::BORDER_CONSTANT);
+    // restore the image
+    cv::Mat median_blurred;
+    medianBlur (blurred, median_blurred, 3);
+    SmartPtr<CVImageProcessHelper> helpers = new CVImageProcessHelper ();
+    float noise_power = 1.0f / helpers->get_snr (blurred, median_blurred);
+    wiener_filter->wiener_filter (blurred, kernel, output_image, noise_power);
+}
+
 int main (int argc, char *argv[])
 {
     const char *file_in_name = NULL;
     const char *file_out_name = NULL;
 
     bool need_save_output = true;
+    bool blind = true;
 
     const struct option long_opts[] = {
         {"input", required_argument, NULL, 'i'},
         {"output", required_argument, NULL, 'o'},
+        {"blind", required_argument, NULL, 'b'},
         {"save", required_argument, NULL, 's'},
         {"help", no_argument, NULL, 'H'},
         {0, 0, 0, 0},
     };
 
     int opt = -1;
-    while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+    while ((opt = getopt_long (argc, argv, "", long_opts, NULL)) != -1)
+    {
         switch (opt) {
         case 'i':
             file_in_name = optarg;
@@ -68,6 +107,9 @@
         case 'o':
             file_out_name = optarg;
             break;
+        case 'b':
+            blind = (strcasecmp (optarg, "false") == 0 ? false : true);
+            break;
         case 's':
             need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true);
             break;
@@ -81,13 +123,15 @@
         }
     }
 
-    if (optind < argc || argc < 2) {
-        printf("unknown option %s\n", argv[optind]);
+    if (optind < argc || argc < 2)
+    {
+        printf ("unknown option %s\n", argv[optind]);
         usage (argv[0]);
         return -1;
     }
 
-    if (!file_in_name || !file_out_name) {
+    if (!file_in_name || !file_out_name)
+    {
         XCAM_LOG_ERROR ("input/output path is NULL");
         return -1;
     }
@@ -95,24 +139,32 @@
     printf ("Description-----------\n");
     printf ("input image file:%s\n", file_in_name);
     printf ("output file :%s\n", file_out_name);
+    printf ("blind deblurring:%s\n", blind ? "true" : "false");
     printf ("need save file:%s\n", need_save_output ? "true" : "false");
     printf ("----------------------\n");
 
-    SmartPtr<CVImageDeblurring> imageDeblurring = new CVImageDeblurring();
-    SmartPtr<CVImageSharp> sharp = new CVImageSharp();
-    cv::Mat blurred = cv::imread(file_in_name, CV_LOAD_IMAGE_COLOR);
-    if (blurred.empty()) {
+    SmartPtr<CVImageSharp> sharp = new CVImageSharp ();
+    cv::Mat input_image = cv::imread (file_in_name, CV_LOAD_IMAGE_COLOR);
+    cv::Mat output_image;
+    if (input_image.empty ())
+    {
         XCAM_LOG_ERROR ("input file read error");
         return 0;
     }
-    cv::Mat deblurred;
-    cv::Mat kernel;
-    imageDeblurring->blind_deblurring (blurred, deblurred, kernel);
-    float input_sharp = sharp->measure_sharp (blurred);
-    float output_sharp = sharp->measure_sharp (deblurred);
-    if (need_save_output) {
-        cv::imwrite(file_out_name, deblurred);
+    if (blind)
+    {
+        blind_deblurring (input_image, output_image);
     }
-    assert(output_sharp > input_sharp);
+    else
+    {
+        non_blind_deblurring (input_image, output_image);
+    }
+    float input_sharp = sharp->measure_sharp (input_image);
+    float output_sharp = sharp->measure_sharp (output_image);
+    if (need_save_output)
+    {
+        cv::imwrite (file_out_name, output_image);
+    }
+    XCAM_ASSERT (output_sharp > input_sharp);
 }
 
diff --git a/tests/test-image-stitching.cpp b/tests/test-image-stitching.cpp
index 6d1fa86..ddd765f 100644
--- a/tests/test-image-stitching.cpp
+++ b/tests/test-image-stitching.cpp
@@ -453,7 +453,6 @@
     }
     rectified_view_buf = rectified_view_pool->get_buffer (rectified_view_pool);
 
-
     for (int i = 0; i < input_count; i++) {
         ret = file_in[i].open (file_in_name[i], "rb");
         CHECK (ret, "open %s failed", file_in_name[i]);
@@ -528,27 +527,27 @@
             ret = image_360->execute (input_buf, output_buf);
             CHECK (ret, "image_360 stitch execute failed");
 
-            BowlDataConfig config = image_360->get_fisheye_bowl_config ();
-            sample_generate_top_view (output_buf, top_view_buf, config, top_view_map_table);
-            sample_generate_rectified_view (output_buf, rectified_view_buf, config, rectified_start_angle,
-                                            rectified_end_angle, rectified_view_map_table);
-
 #if HAVE_OPENCV
             if (need_save_output) {
                 cv::Mat out_mat;
                 convert_to_mat (output_buf, out_mat);
                 writer.write (out_mat);
 
+                BowlDataConfig config = image_360->get_fisheye_bowl_config ();
                 cv::Mat top_view_mat;
+                sample_generate_top_view (output_buf, top_view_buf, config, top_view_map_table);
                 convert_to_mat (top_view_buf, top_view_mat);
                 top_view_writer.write (top_view_mat);
 
                 cv::Mat rectified_view_mat;
+                sample_generate_rectified_view (output_buf, rectified_view_buf, config, rectified_start_angle,
+                                                rectified_end_angle, rectified_view_map_table);
                 convert_to_mat (rectified_view_buf, rectified_view_mat);
                 rectified_view_writer.write (rectified_view_mat);
 
 #if XCAM_TEST_STITCH_DEBUG
-                dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf, all_in_one, fisheye_num, input_count);
+                dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf,
+                                 all_in_one, fisheye_num, input_count);
 #endif
             } else
 #endif
diff --git a/tests/test-soft-image.cpp b/tests/test-soft-image.cpp
index 64c2d66..578de8e 100644
--- a/tests/test-soft-image.cpp
+++ b/tests/test-soft-image.cpp
@@ -254,7 +254,7 @@
 #endif
 
 static int
-parse_camera_info (const char *path, uint32_t idx, CameraInfo &info)
+parse_camera_info (const char *path, uint32_t idx, CameraInfo &info, uint32_t camera_count)
 {
     static const char *instrinsic_names[] = {
         "intrinsic_camera_front.txt", "intrinsic_camera_right.txt",
@@ -282,7 +282,7 @@
     info.calibration.extrinsic.trans_x += TEST_CAMERA_POSITION_OFFSET_X;
 
     info.angle_range = viewpoints_range[idx];
-    info.round_angle_start = (idx * 360.0f / 4.0f) - info.angle_range / 2.0f;
+    info.round_angle_start = (idx * 360.0f / camera_count) - info.angle_range / 2.0f;
     return 0;
 }
 
@@ -428,17 +428,36 @@
     return XCAM_RETURN_NO_ERROR;
 }
 
+static bool
+check_element (const SoftElements &elements, const uint32_t &idx)
+{
+    if (idx >= elements.size ())
+        return false;
+
+    if (!elements[idx].ptr()) {
+        XCAM_LOG_ERROR ("SoftElement(idx:%d) ptr is NULL", idx);
+        return false;
+    }
+
+    XCAM_FAIL_RETURN (
+        ERROR,
+        elements[idx]->get_width () && elements[idx]->get_height (),
+        false,
+        "SoftElement(idx:%d): invalid parameters width:%d height:%d",
+        idx, elements[idx]->get_width (), elements[idx]->get_height ());
+
+    return true;
+}
+
 static XCamReturn
 check_elements (const SoftElements &elements)
 {
     for (uint32_t i = 0; i < elements.size (); ++i) {
-        XCAM_ASSERT (elements[i].ptr ());
         XCAM_FAIL_RETURN (
             ERROR,
-            elements[i]->get_width () && elements[i]->get_height (),
+            check_element (elements, i),
             XCAM_RETURN_ERROR_PARAM,
-            "SoftElement: invalid parameters index:%d width:%d height:%d",
-            i, elements[i]->get_width (), elements[i]->get_height ());
+            "invalid SoftElement index:%d\n", i);
     }
 
     return XCAM_RETURN_NO_ERROR;
@@ -482,13 +501,17 @@
             if (ret == XCAM_RETURN_BYPASS)
                 break;
 
-            stitcher->stitch_buffers (in_buffers, outs[0]->get_buf ());
-            if (outs[1].ptr ()) {
-                CHECK (run_topview (stitcher, outs), "run topview failed");
-            }
+            CHECK (
+                stitcher->stitch_buffers (in_buffers, outs[0]->get_buf ()),
+                "stitch buffer failed.");
 
-            if (save_output)
+            if (save_output) {
+                if (check_element (outs, 1)) {
+                    CHECK (run_topview (stitcher, outs), "run topview failed");
+                }
+
                 write_image (ins, outs, nv12_output);
+            }
 
             FPS_CALCULATION (soft - stitcher, XCAM_OBJ_DUR_FRAME_NUM);
         } while (true);
@@ -637,16 +660,16 @@
         return -1;
     }
 
-    if (!strlen (ins[0]->get_file_name ()) || !strlen (outs[0]->get_file_name ())) {
+    if (ins.empty () || outs.empty () ||
+            !strlen (ins[0]->get_file_name ()) || !strlen (outs[0]->get_file_name ())) {
         XCAM_LOG_ERROR ("input or output file name was not set");
         usage (argv[0]);
         return -1;
     }
 
-    printf ("input0 file:\t\t%s\n", ins[0]->get_file_name ());
-    printf ("input1 file:\t\t%s\n", ins[1]->get_file_name ());
-    printf ("input2 file:\t\t%s\n", ins[2]->get_file_name ());
-    printf ("input3 file:\t\t%s\n", ins[3]->get_file_name ());
+    for (uint32_t i = 0; i < ins.size (); ++i) {
+        printf ("input%d file:\t\t%s\n", i, ins[i]->get_file_name ());
+    }
     printf ("output file:\t\t%s\n", outs[0]->get_file_name ());
     printf ("input width:\t\t%d\n", input_width);
     printf ("input height:\t\t%d\n", input_height);
@@ -677,6 +700,7 @@
 
     switch (type) {
     case SoftTypeBlender: {
+        CHECK_EXP (ins.size () >= 2, "blender need 2 input files.");
         SmartPtr<Blender> blender = Blender::create_soft_blender ();
         XCAM_ASSERT (blender.ptr ());
         blender->set_output_size (output_width, output_height);
@@ -708,6 +732,9 @@
         break;
     }
     case SoftTypeStitch: {
+        CHECK_EXP (ins.size () >= 2 && ins.size () <= 4, "stitcher need at 2~4 input files.");
+
+        uint32_t camera_count = ins.size ();
         SmartPtr<Stitcher> stitcher = Stitcher::create_soft_stitcher ();
         XCAM_ASSERT (stitcher.ptr ());
 
@@ -716,21 +743,23 @@
         if (!fisheye_config_path)
             fisheye_config_path = FISHEYE_CONFIG_PATH;
 
-        for (uint32_t i = 0; i < 4; ++i) {
-            if (parse_camera_info (fisheye_config_path, i, cam_info[i]) != 0) {
+        for (uint32_t i = 0; i < camera_count; ++i) {
+            if (parse_camera_info (fisheye_config_path, i, cam_info[i], camera_count) != 0) {
                 XCAM_LOG_ERROR ("parse fisheye dewarp info(idx:%d) failed.", i);
                 return -1;
             }
         }
 
         PointFloat3 bowl_coord_offset;
-        centralize_bowl_coord_from_cameras (
-            cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic,
-            cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic,
-            bowl_coord_offset);
+        if (camera_count == 4) {
+            centralize_bowl_coord_from_cameras (
+                cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic,
+                cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic,
+                bowl_coord_offset);
+        }
 
-        stitcher->set_camera_num (4);
-        for (uint32_t i = 0; i < 4; ++i) {
+        stitcher->set_camera_num (camera_count);
+        for (uint32_t i = 0; i < camera_count; ++i) {
             stitcher->set_camera_info (i, cam_info[i]);
         }
 
@@ -745,10 +774,13 @@
         stitcher->set_bowl_config (bowl);
         stitcher->set_output_size (output_width, output_height);
 
-        add_element (outs, "topview", topview_width, topview_height);
-        if (save_output)
+        if (save_output) {
+            add_element (outs, "topview", topview_width, topview_height);
             elements_open_file (outs, "wb", nv12_output);
-        run_stitcher (stitcher, ins, outs, nv12_output, save_output, loop);
+        }
+        CHECK_EXP (
+            run_stitcher (stitcher, ins, outs, nv12_output, save_output, loop) == 0,
+            "run stitcher failed.");
         break;
     }
 
diff --git a/xcore/image_processor.cpp b/xcore/image_processor.cpp
index f9914d2..928cbcc 100644
--- a/xcore/image_processor.cpp
+++ b/xcore/image_processor.cpp
@@ -25,6 +25,7 @@
 
 void
 ImageProcessCallback::process_buffer_done (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf) {
+    XCAM_UNUSED (processor);
     XCAM_ASSERT (buf.ptr() && processor);
 
     int64_t ts = buf->get_timestamp();
@@ -51,6 +52,7 @@
 void
 ImageProcessCallback::process_image_result_done (ImageProcessor *processor, const SmartPtr<X3aResult> &result)
 {
+    XCAM_UNUSED (processor);
     XCAM_ASSERT (result.ptr() && processor);
 
     int64_t ts = result->get_timestamp();