diff --git a/modules/stitching/include/opencv2/stitching.hpp b/modules/stitching/include/opencv2/stitching.hpp
index 3ccd2878a..2c48f2f2a 100644
--- a/modules/stitching/include/opencv2/stitching.hpp
+++ b/modules/stitching/include/opencv2/stitching.hpp
@@ -59,7 +59,13 @@ class CV_EXPORTS Stitcher
 {
 public:
     enum { ORIG_RESOL = -1 };
-    enum Status { OK, ERR_NEED_MORE_IMGS };
+    enum Status
+    {
+        OK = 0,
+        ERR_NEED_MORE_IMGS = 1,
+        ERR_HOMOGRAPHY_EST_FAIL = 2,
+        ERR_CAMERA_PARAMS_ADJUST_FAIL = 3
+    };
 
     // Creates stitcher with default parameters
     static Stitcher createDefault(bool try_use_gpu = false);
@@ -138,7 +144,7 @@ private:
     Stitcher() {}
 
     Status matchImages();
-    void estimateCameraParams();
+    Status estimateCameraParams();
 
     double registr_resol_;
     double seam_est_resol_;
diff --git a/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp b/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp
index 581a0292d..c0e446c60 100644
--- a/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp
+++ b/modules/stitching/include/opencv2/stitching/detail/motion_estimators.hpp
@@ -56,12 +56,14 @@ class CV_EXPORTS Estimator
 public:
     virtual ~Estimator() {}
 
-    void operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
+    bool operator ()(const std::vector<ImageFeatures> &features,
+                     const std::vector<MatchesInfo> &pairwise_matches,
                      std::vector<CameraParams> &cameras)
-        { estimate(features, pairwise_matches, cameras); }
+        { return estimate(features, pairwise_matches, cameras); }
 
 protected:
-    virtual void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
+    virtual bool estimate(const std::vector<ImageFeatures> &features,
+                          const std::vector<MatchesInfo> &pairwise_matches,
                           std::vector<CameraParams> &cameras) = 0;
 };
 
@@ -73,8 +75,9 @@ public:
         : is_focals_estimated_(is_focals_estimated) {}
 
 private:
-    void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
-                  std::vector<CameraParams> &cameras);
+    virtual bool estimate(const std::vector<ImageFeatures> &features,
+                          const std::vector<MatchesInfo> &pairwise_matches,
+                          std::vector<CameraParams> &cameras);
 
     bool is_focals_estimated_;
 };
@@ -107,7 +110,7 @@ protected:
     }
 
     // Runs bundle adjustment
-    virtual void estimate(const std::vector<ImageFeatures> &features,
+    virtual bool estimate(const std::vector<ImageFeatures> &features,
                           const std::vector<MatchesInfo> &pairwise_matches,
                           std::vector<CameraParams> &cameras);
 
@@ -193,11 +196,14 @@ void CV_EXPORTS waveCorrect(std::vector<Mat> &rmats, WaveCorrectKind kind);
 String CV_EXPORTS matchesGraphAsString(std::vector<String> &pathes, std::vector<MatchesInfo> &pairwise_matches,
                                             float conf_threshold);
 
-std::vector<int> CV_EXPORTS leaveBiggestComponent(std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
-                                                  float conf_threshold);
+std::vector<int> CV_EXPORTS leaveBiggestComponent(
+        std::vector<ImageFeatures> &features,
+        std::vector<MatchesInfo> &pairwise_matches,
+        float conf_threshold);
 
-void CV_EXPORTS findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches,
-                                    Graph &span_tree, std::vector<int> &centers);
+void CV_EXPORTS findMaxSpanningTree(
+        int num_images, const std::vector<MatchesInfo> &pairwise_matches,
+        Graph &span_tree, std::vector<int> &centers);
 
 } // namespace detail
 } // namespace cv
diff --git a/modules/stitching/src/motion_estimators.cpp b/modules/stitching/src/motion_estimators.cpp
index 1bb3df7bb..3640bd3cc 100644
--- a/modules/stitching/src/motion_estimators.cpp
+++ b/modules/stitching/src/motion_estimators.cpp
@@ -101,8 +101,10 @@ void calcDeriv(const Mat &err1, const Mat &err2, double h, Mat res)
 namespace cv {
 namespace detail {
 
-void HomographyBasedEstimator::estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
-                                        std::vector<CameraParams> &cameras)
+bool HomographyBasedEstimator::estimate(
+        const std::vector<ImageFeatures> &features,
+        const std::vector<MatchesInfo> &pairwise_matches,
+        std::vector<CameraParams> &cameras)
 {
     LOGLN("Estimating rotations...");
 #if ENABLE_LOG
@@ -164,12 +166,13 @@ void HomographyBasedEstimator::estimate(const std::vector<ImageFeatures> &featur
     }
 
     LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
+    return true;
 }
 
 
 //////////////////////////////////////////////////////////////////////////////
 
-void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
+bool BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
                                   const std::vector<MatchesInfo> &pairwise_matches,
                                   std::vector<CameraParams> &cameras)
 {
@@ -245,7 +248,21 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
     LOGLN_CHAT("Bundle adjustment, final RMS error: " << std::sqrt(err.dot(err) / total_num_matches_));
     LOGLN_CHAT("Bundle adjustment, iterations done: " << iter);
 
-    obtainRefinedCameraParams(cameras);
+    // Check if all camera parameters are valid
+    bool ok = true;
+    for (int i = 0; i < cam_params_.rows; ++i)
+    {
+        if (isnan(cam_params_.at<double>(i,0)) ||
+            isinf(cam_params_.at<double>(i,0)))
+        {
+            ok = false;
+            break;
+        }
+    }
+    if (!ok)
+        return false;
+
+    obtainRefinedCameraParams(cameras);        
 
     // Normalize motion to center image
     Graph span_tree;
@@ -256,6 +273,7 @@ void BundleAdjusterBase::estimate(const std::vector<ImageFeatures> &features,
         cameras[i].R = R_inv * cameras[i].R;
 
     LOGLN_CHAT("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
+    return true;
 }
 
 
diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp
index cef9fe4e9..75307209d 100644
--- a/modules/stitching/src/stitcher.cpp
+++ b/modules/stitching/src/stitcher.cpp
@@ -102,7 +102,8 @@ Stitcher::Status Stitcher::estimateTransform(InputArray images, const std::vecto
     if ((status = matchImages()) != OK)
         return status;
 
-    estimateCameraParams();
+    if ((status = estimateCameraParams()) != OK)
+        return status;
 
     return OK;
 }
@@ -442,10 +443,11 @@ Stitcher::Status Stitcher::matchImages()
 }
 
 
-void Stitcher::estimateCameraParams()
+Stitcher::Status Stitcher::estimateCameraParams()
 {
     detail::HomographyBasedEstimator estimator;
-    estimator(features_, pairwise_matches_, cameras_);
+    if (!estimator(features_, pairwise_matches_, cameras_))
+        return ERR_HOMOGRAPHY_EST_FAIL;
 
     for (size_t i = 0; i < cameras_.size(); ++i)
     {
@@ -456,7 +458,8 @@ void Stitcher::estimateCameraParams()
     }
 
     bundle_adjuster_->setConfThresh(conf_thresh_);
-    (*bundle_adjuster_)(features_, pairwise_matches_, cameras_);
+    if (!(*bundle_adjuster_)(features_, pairwise_matches_, cameras_))
+        return ERR_CAMERA_PARAMS_ADJUST_FAIL;
 
     // Find median focal length and use it as final image scale
     std::vector<double> focals;
@@ -481,6 +484,8 @@ void Stitcher::estimateCameraParams()
         for (size_t i = 0; i < cameras_.size(); ++i)
             cameras_[i].R = rmats[i];
     }
+
+    return OK;
 }
 
 } // namespace cv
diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp
index 5ee79184d..a50229a57 100644
--- a/samples/cpp/stitching_detailed.cpp
+++ b/samples/cpp/stitching_detailed.cpp
@@ -469,7 +469,11 @@ int main(int argc, char* argv[])
 
     HomographyBasedEstimator estimator;
     vector<CameraParams> cameras;
-    estimator(features, pairwise_matches, cameras);
+    if (!estimator(features, pairwise_matches, cameras))
+    {
+        cout << "Homography estimation failed.\n";
+        return -1;
+    }
 
     for (size_t i = 0; i < cameras.size(); ++i)
     {
@@ -495,7 +499,11 @@ int main(int argc, char* argv[])
     if (ba_refine_mask[3] == 'x') refine_mask(1,1) = 1;
     if (ba_refine_mask[4] == 'x') refine_mask(1,2) = 1;
     adjuster->setRefinementMask(refine_mask);
-    (*adjuster)(features, pairwise_matches, cameras);
+    if (!(*adjuster)(features, pairwise_matches, cameras))
+    {
+        cout << "Camera parameters adjusting failed.\n";
+        return -1;
+    }
 
     // Find median focal length