diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp
index 862f3f950c94090554f0c803ec530f0e51327c44..013d9187febd4d0994c3c3562c9caa8eb7e7b000 100644
--- a/modules/ml/include/opencv2/ml.hpp
+++ b/modules/ml/include/opencv2/ml.hpp
@@ -719,6 +719,10 @@ public:
     Use StatModel::train to train the model. Since %SVM has several parameters, you may want to
     find the best parameters for your problem, it can be done with SVM::trainAuto. */
     CV_WRAP static Ptr<SVM> create();
+
+    CV_WRAP virtual void read( const FileNode& fn ) = 0;
+
+    CV_WRAP static Ptr<SVM> load(const String& fs);
 };
 
 /****************************************************************************************\
diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp
index 757bb7a17113f016a7f2c154b289a29f038069d5..639f6e2168fa19d3197611085c3cadec461eb484 100644
--- a/modules/ml/src/svm.cpp
+++ b/modules/ml/src/svm.cpp
@@ -2261,6 +2261,17 @@ Ptr<SVM> SVM::create()
     return makePtr<SVMImpl>();
 }
 
+Ptr<SVM> SVM::load(const String& filename)
+{
+    FileStorage fs;
+    fs.open(filename, FileStorage::READ);
+
+    Ptr<SVM> svm = makePtr<SVMImpl>();
+
+    svm->read(fs.getFirstTopLevelNode());
+    return svm;
+}
+
 Mat SVM::getUncompressedSupportVectors() const
 {
     const SVMImpl* this_ = dynamic_cast<const SVMImpl*>(this);