content: import java.util.Random;
  
  import org.opencv.core.Core;
  import org.opencv.core.CvType;
  import org.opencv.core.Mat;
  import org.opencv.core.Point;
  import org.opencv.core.Scalar;
  import org.opencv.core.TermCriteria;
  import org.opencv.highgui.HighGui;
  import org.opencv.imgcodecs.Imgcodecs;
  import org.opencv.imgproc.Imgproc;
  import org.opencv.ml.Ml;
  import org.opencv.ml.SVM;
  
  public class NonLinearSVMsDemo {
      public static final int NTRAINING_SAMPLES = 100;
      public static final float FRAC_LINEAR_SEP = 0.9f;
  
      public static void main(String[] args) {
          // Load the native OpenCV library
          System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  
          System.out.println("\n--------------------------------------------------------------------------");
          System.out.println("This program shows Support Vector Machines for Non-Linearly Separable Data. ");
          System.out.println("--------------------------------------------------------------------------\n");
  
          // Data for visual representation
          int width = 512, height = 512;
          Mat I = Mat.zeros(height, width, CvType.CV_8UC3);
  
          // --------------------- 1. Set up training data randomly---------------------------------------
          Mat trainData = new Mat(2 * NTRAINING_SAMPLES, 2, CvType.CV_32F);
          Mat labels = new Mat(2 * NTRAINING_SAMPLES, 1, CvType.CV_32S);
  
          Random rng = new Random(100); // Random value generation class
  
          // Set up the linearly separable part of the training data
          int nLinearSamples = (int) (FRAC_LINEAR_SEP * NTRAINING_SAMPLES);
  
          //! [setup1]
          // Generate random points for the class 1
          Mat trainClass = trainData.rowRange(0, nLinearSamples);
          // The x coordinate of the points is in [0, 0.4)
          Mat c = trainClass.colRange(0, 1);
          float[] cData = new float[(int) (c.total() * c.channels())];
          double[] cDataDbl = rng.doubles(cData.length, 0, 0.4f * width).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
          // The y coordinate of the points is in [0, 1)
          c = trainClass.colRange(1, 2);
          cData = new float[(int) (c.total() * c.channels())];
          cDataDbl = rng.doubles(cData.length, 0, height).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
  
          // Generate random points for the class 2
          trainClass = trainData.rowRange(2 * NTRAINING_SAMPLES - nLinearSamples, 2 * NTRAINING_SAMPLES);
          // The x coordinate of the points is in [0.6, 1]
          c = trainClass.colRange(0, 1);
          cData = new float[(int) (c.total() * c.channels())];
          cDataDbl = rng.doubles(cData.length, 0.6 * width, width).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
          // The y coordinate of the points is in [0, 1)
          c = trainClass.colRange(1, 2);
          cData = new float[(int) (c.total() * c.channels())];
          cDataDbl = rng.doubles(cData.length, 0, height).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
          //! [setup1]
  
          // ------------------ Set up the non-linearly separable part of the training data ---------------
          //! [setup2]
          // Generate random points for the classes 1 and 2
          trainClass = trainData.rowRange(nLinearSamples, 2 * NTRAINING_SAMPLES - nLinearSamples);
          // The x coordinate of the points is in [0.4, 0.6)
          c = trainClass.colRange(0, 1);
          cData = new float[(int) (c.total() * c.channels())];
          cDataDbl = rng.doubles(cData.length, 0.4 * width, 0.6 * width).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
          // The y coordinate of the points is in [0, 1)
          c = trainClass.colRange(1, 2);
          cData = new float[(int) (c.total() * c.channels())];
          cDataDbl = rng.doubles(cData.length, 0, height).toArray();
          for (int i = 0; i < cData.length; i++) {
              cData[i] = (float) cDataDbl[i];
          }
          c.put(0, 0, cData);
          //! [setup2]
  
          // ------------------------- Set up the labels for the classes---------------------------------
          labels.rowRange(0, NTRAINING_SAMPLES).setTo(new Scalar(1)); // Class 1
          labels.rowRange(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES).setTo(new Scalar(2)); // Class 2
  
          // ------------------------ 2. Set up the support vector machines parameters--------------------
          System.out.println("Starting training process");
          //! [init]
          SVM svm = SVM.create();
          svm.setType(SVM.C_SVC);
          svm.setC(0.1);
          svm.setKernel(SVM.LINEAR);
          svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, (int) 1e7, 1e-6));
          //! [init]
  
          // ------------------------ 3. Train the svm----------------------------------------------------
          //! [train]
          svm.train(trainData, Ml.ROW_SAMPLE, labels);
          //! [train]
          System.out.println("Finished training process");
  
          // ------------------------ 4. Show the decision regions----------------------------------------
          //! [show]
          byte[] IData = new byte[(int) (I.total() * I.channels())];
          Mat sampleMat = new Mat(1, 2, CvType.CV_32F);
          float[] sampleMatData = new float[(int) (sampleMat.total() * sampleMat.channels())];
          for (int i = 0; i < I.rows(); i++) {
              for (int j = 0; j < I.cols(); j++) {
                  sampleMatData[0] = j;
                  sampleMatData[1] = i;
                  sampleMat.put(0, 0, sampleMatData);
                  float response = svm.predict(sampleMat);
  
                  if (response == 1) {
                      IData[(i * I.cols() + j) * I.channels()] = 0;
                      IData[(i * I.cols() + j) * I.channels() + 1] = 100;
                      IData[(i * I.cols() + j) * I.channels() + 2] = 0;
                  } else if (response == 2) {
                      IData[(i * I.cols() + j) * I.channels()] = 100;
                      IData[(i * I.cols() + j) * I.channels() + 1] = 0;
                      IData[(i * I.cols() + j) * I.channels() + 2] = 0;
                  }
              }
          }
          I.put(0, 0, IData);
          //! [show]
  
          // ----------------------- 5. Show the training data--------------------------------------------
          //! [show_data]
          int thick = -1;
          int lineType = Imgproc.LINE_8;
          float px, py;
          // Class 1
          float[] trainDataData = new float[(int) (trainData.total() * trainData.channels())];
          trainData.get(0, 0, trainDataData);
          for (int i = 0; i < NTRAINING_SAMPLES; i++) {
              px = trainDataData[i * trainData.cols()];
              py = trainDataData[i * trainData.cols() + 1];
              Imgproc.circle(I, new Point(px, py), 3, new Scalar(0, 255, 0), thick, lineType, 0);
          }
          // Class 2
          for (int i = NTRAINING_SAMPLES; i < 2 * NTRAINING_SAMPLES; ++i) {
              px = trainDataData[i * trainData.cols()];
              py = trainDataData[i * trainData.cols() + 1];
              Imgproc.circle(I, new Point(px, py), 3, new Scalar(255, 0, 0), thick, lineType, 0);
          }
          //! [show_data]
  
          // ------------------------- 6. Show support vectors--------------------------------------------
          //! [show_vectors]
          thick = 2;
          Mat sv = svm.getUncompressedSupportVectors();
          float[] svData = new float[(int) (sv.total() * sv.channels())];
          sv.get(0, 0, svData);
          for (int i = 0; i < sv.rows(); i++) {
              Imgproc.circle(I, new Point(svData[i * sv.cols()], svData[i * sv.cols() + 1]), 6, new Scalar(128, 128, 128),
                      thick, lineType, 0);
          }
          //! [show_vectors]
  
          Imgcodecs.imwrite("result.png", I); // save the Image
          HighGui.imshow("SVM for Non-Linear Training Data", I); // show it to the user
          HighGui.waitKey();
          System.exit(0);
      }
  }
  