Note Book : OpenCV v4.5.0-openvino Mask CNN by With Spring Boot

### Mask RCNN

####Final Result
![8829708882_48f263491e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/53a56d71-53cc-a617-7f4e-00a200edcbcc.jpeg)

####Mask
![8829708882_48f263491e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/00093541-f249-ffaf-afe7-f1c6d4baab7d.jpeg)

####Rectangle Mask
![8829708882_48f263491e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/917dbe76-524f-e009-5481-d743c036f48e.jpeg)
####log
2020-11-28 12:30:59.341  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Running 24 / 29
2020-11-28 12:30:59.341  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Iinput file /usr/local/src/Mask_RCNN/images/8829708882_48f263491e_z.jpg
2020-11-28 12:30:59.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : file rows 427 file cols 640 threshold 0.5
2020-11-28 12:30:59.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : bus:1.0
2020-11-28 12:30:59.539  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Output file ./output/mask_rcnn_inception_v2_coco_2018_01_28/8829708882_48f263491e_z.jpg
2020-11-28 12:30:59.539  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Running 25 / 29
2020-11-28 12:30:59.539  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Iinput file /usr/local/src/Mask_RCNN/images/8734543718_37f6b8bd45_z.jpg
2020-11-28 12:30:59.740  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : file rows 394 file cols 640 threshold 0.5
2020-11-28 12:30:59.740  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : donut:0.83
2020-11-28 12:30:59.741  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : donut:0.77
2020-11-28 12:30:59.741  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : donut:0.58
2020-11-28 12:30:59.741  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : donut:0.53
2020-11-28 12:30:59.744  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Output file ./output/mask_rcnn_inception_v2_coco_2018_01_28/8734543718_37f6b8bd45_z.jpg


####Final Result
![7933423348_c30bd9bd4e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/f3b6fd18-1f2c-250f-ce57-1e519768426b.jpeg)

####Mask
![7933423348_c30bd9bd4e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/aaa20218-8982-9749-b736-f8f4d9e16ab2.jpeg)

####Rectangle Mask
![7933423348_c30bd9bd4e_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/233d2c0d-921b-8360-76db-a1372298db7b.jpeg)

####log
2020-11-28 12:30:58.340  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Running 19 / 29
2020-11-28 12:30:58.340  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Iinput file /usr/local/src/Mask_RCNN/images/7933423348_c30bd9bd4e_z.jpg
2020-11-28 12:30:58.535  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : file rows 480 file cols 640 threshold 0.5
2020-11-28 12:30:58.535  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : motorcycle:0.99
2020-11-28 12:30:58.535  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : bench:0.98
2020-11-28 12:30:58.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.96
2020-11-28 12:30:58.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : car:0.96
2020-11-28 12:30:58.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.95
2020-11-28 12:30:58.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.9
2020-11-28 12:30:58.536  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.66
2020-11-28 12:30:58.537  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : motorcycle:0.65
2020-11-28 12:30:58.537  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : car:0.52
2020-11-28 12:30:58.541  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Output file ./output/mask_rcnn_inception_v2_coco_2018_01_28/7933423348_c30bd9bd4e_z.jpg


####Final Result
![4410436637_7b0ca36ee7_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/dea4a634-89ce-d499-797e-5ffb635b3966.jpeg)

####Mask
![4410436637_7b0ca36ee7_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/2ed123a0-976a-8af7-3118-859260a58c5e.jpeg)

####Rectangle Mask
![4410436637_7b0ca36ee7_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732297/abf7f7e4-fce4-a089-09c8-7a9f76e8f2e9.jpeg)

####log
2020-11-28 12:30:59.942  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Running 27 / 29
2020-11-28 12:30:59.942  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Iinput file /usr/local/src/Mask_RCNN/images/4410436637_7b0ca36ee7_z.jpg
2020-11-28 12:31:00.137  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : file rows 426 file cols 640 threshold 0.5
2020-11-28 12:31:00.138  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:1.0
2020-11-28 12:31:00.138  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : snowboard:0.93
2020-11-28 12:31:00.139  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.88
2020-11-28 12:31:00.139  INFO 6778 --- [           main] deepl.dnn.impl.SimpleRCnn                : person:0.85
2020-11-28 12:31:00.141  INFO 6778 --- [           main] deepl.dnn.impl.MaskRCnn                  : Output file ./output/mask_rcnn_inception_v2_coco_2018_01_28/4410436637_7b0ca36ee7_z.jpg


```java:RCnn.java
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package deepl.dnn;

import org.opencv.core.Mat;

/**
 * @author jashika.t.e
 * @since 0.1
 */
public interface RCnn<T> {
    Mat run(T targetObject);
}
```

####Source Code

```java:SimpleRCnn.java

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package deepl.dnn.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import deepl.dnn.RCnn;

/**
 * @author jashika.t.e
 * @since 0.1
 */
public class SimpleRCnn implements RCnn<Mat> {

    /**
     * logger.
     */
    protected static final Logger log = LoggerFactory.getLogger(SimpleRCnn.class);

    /**
     * properties.
     */
    protected RCnnProperties properties;

    /**
     * network.
     */
    protected Net net;

    /**
     * constractor.
     * 
     * @param properties
     */
    public SimpleRCnn(RCnnProperties properties, Net net) {
        this.properties = properties;
        this.net = net;
    }

    public Mat run(Mat orgImage) {

        Mat dstImage = orgImage.clone();
        List<Mat> outputBlobs = getOutputBlobs(dstImage);

        Mat detectionOutFinal = outputBlobs.get(0);
        Mat detectionMasks = outputBlobs.get(1);

        // Output size of masks is NxCxHxW where
        // N - number of detected boxes
        // C - number of classes (excluding background)
        // HxW - segmentation shape
        Mat detection = detectionOutFinal.reshape(1, (int) detectionOutFinal.total() / detectionOutFinal.size(3));
        Mat reshapeMask = detectionMasks.reshape(1, (int) detectionMasks.total() / (detectionMasks.size(2) * detectionMasks.size(3)));

        log.debug("detectionOutFinal.reshape(1, " + (int) (detectionOutFinal.total() / detectionOutFinal.size(3)) + ")");
        log.debug("detectionOutFinal.size(2) == " + detectionOutFinal.size(2));
        log.debug("detectionMasks.reshape(1, " + (int) detectionMasks.total() / (detectionMasks.size(2) * detectionMasks.size(3)) + ")");

        int cols = dstImage.cols();
        int rows = dstImage.rows();
        List<Mat> masks = new ArrayList<Mat>();
        List<Mat> ractangleMasks = new ArrayList<Mat>();
        List<double[]> colors = properties.getColors();
        List<String> names = properties.getNames();
        double threshold = properties.getThreshold();

        log.info("file rows " + rows + " file cols " + cols + " threshold " + threshold);
        IntStream.range(0, detectionOutFinal.size(2)).filter(i -> detection.get(i, 2)[0] > threshold).forEach(i -> {
            int classId = (int) detection.get(i, 1)[0];
            // color from txt
            Scalar color = new Scalar(colors.get(classId % colors.size()));
            color.val[3] = 255d;
            // axis
            Rect box = createRect(detection, i, cols, rows);
            // for rectangle txt
            String label = createLabel(detection, i, cols, rows, names);
            // create and collect ractangle mask
            ractangleMasks.add(createRectangleMask(dstImage.size(), label, color, box));
            // 1 x 255
            Mat objectMask = reshapeMask.row(i * detectionMasks.size(0) + classId);
            // 15 x 15
            objectMask = objectMask.reshape(1, detectionMasks.size(2));
            // create and collect mask
            masks.add(createMask(objectMask, dstImage.size(), color, box));
            log.info("result " + label);
        });
        return createFinalDst(dstImage, masks, ractangleMasks);
    }

    protected Mat createFinalDst(Mat targetMat, List<Mat> masks, List<Mat> ractangleMasks) {
        Mat mask = new Mat();
        masks.stream().forEach(m -> m.copyTo(mask, m));
        Imgcodecs.imwrite("/tmp/mask.png", mask);

        Mat ractangleMask = new Mat();
        ractangleMasks.stream().forEach(m -> m.copyTo(ractangleMask, m));
        Imgcodecs.imwrite("/tmp/mask.png", ractangleMask);

        ractangleMask.copyTo(targetMat, ractangleMask);

//        mask.copyTo(targetMat, mask);

        Core.addWeighted(targetMat, properties.getMask().getAlpha(), mask, properties.getMask().getBeta(), properties.getMask().getGannma(),
                targetMat);

      Imgcodecs.imwrite("/tmp/mask.png", targetMat);
        return targetMat;
    }

    protected List<Mat> getOutputBlobs(Mat orgImage) {
        net.setInput(Dnn.blobFromImage(orgImage));

        List<Mat> outputBlobs = new ArrayList<>();
        // outputNames = detection_out_final, detection_masks
        List<String> outputNames = Arrays.asList(properties.getDetection().getNames());
        net.forward(outputBlobs, outputNames);

        log.debug("output blob size " + outputBlobs.size());
        return outputBlobs;
    }

    protected Mat createRectangleMask(Size maskSize, String label, Scalar color, Rect box) {
        int thickness = properties.getRectangle().getThickness();
        double fontScale = properties.getRectangle().getFontScale();
        Mat dstMask = Mat.zeros(maskSize, CvType.CV_8UC3);

        // non alpha
        Imgproc.rectangle(dstMask, new Point(box.x, box.y), new Point(box.x + box.width, box.y + box.height), color, thickness);

        // text box size
        Size size = Imgproc.getTextSize(label, Imgproc.FONT_HERSHEY_SIMPLEX, fontScale, thickness, null);
        Imgproc.putText(dstMask, label, new Point(box.x, box.y + size.height - 1), Imgproc.FONT_HERSHEY_SIMPLEX, fontScale - 0.1,
                new Scalar(255, 255, 255, 255), thickness);

        return dstMask;
    }

    protected Mat createMask(Mat objectMask, Size maskSize, Scalar color, Rect box) {
        Imgproc.resize(objectMask, objectMask, new Size(box.width + 1, box.height + 1));

        Mat mask = new Mat();
        objectMask.convertTo(mask, CvType.CV_8U);

        Mat dstMask = Mat.zeros(maskSize, CvType.CV_8UC3);
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchy = new Mat();

        Imgproc.findContours(mask, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);
        Imgproc.drawContours(dstMask, contours, -1, color, Imgproc.FILLED, Imgproc.LINE_8, hierarchy, 500, new Point(box.x, box.y));

        return dstMask;
    }

    protected String createLabel(Mat detection, int detectionNumber, int cols, int rows, List<String> names) {
        return names.get((int) detection.get(detectionNumber, 1)[0]) + ":"
                + (double) Math.round(detection.get(detectionNumber, 2)[0] * 100) / 100;
    }

    protected Rect createRect(Mat detection, int detectionNumber, int cols, int rows) {
        double left = detection.get(detectionNumber, 3)[0] * cols;
        double top = detection.get(detectionNumber, 4)[0] * rows;
        double right = detection.get(detectionNumber, 5)[0] * cols;
        double bottom = detection.get(detectionNumber, 6)[0] * rows;
        left = Math.max(0, Math.min(left, cols - 1));
        top = Math.max(0, Math.min(top, rows - 1));
        right = Math.max(0, Math.min(right, cols - 1));
        bottom = Math.max(0, Math.min(bottom, rows - 1));
        log.debug("rect data left " + left + " top " + top + " right " + right + " bottom " + bottom);
        return new Rect(new double[] { left, top, right - left + 1, bottom - top + 1 });
    }
}

```


```java:MaskRCnnRunner
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package deepl.controller.dnn;

import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;

import deepl.dnn.impl.MaskRCnn;
import deepl.dnn.impl.RCnnProperties;
import deepl.support.io.MediaFormat;

/**
 * @author jashika.t.e
 * @since 0.1
 */
public class MaskRCnnRunner implements CommandLineRunner {

    /**
     * logger.
     */
    private Logger log = LoggerFactory.getLogger(MaskRCnn.class);

    /**
     * @see MaskRCnn
     */
    private MaskRCnn maskRCnn;

    /**
     * settings.
     */
    private RCnnProperties properties;

    /**
     * constructor.
     * 
     * @param maskRCnn
     * @param properties
     */
    public MaskRCnnRunner(MaskRCnn maskRCnn, RCnnProperties properties) {
        this.maskRCnn = maskRCnn;
        this.properties = properties;
    }

    @Override
    public void run(String... args) throws Exception {
        List<Path> files = properties.getInputFileExtension() == MediaFormat.NONE
                ? Files.walk(Files.createDirectories(Paths.get(properties.getInputDir())))
                        .filter(p -> p.toFile().isFile()).collect(Collectors.toList())
                : Files.walk(Files.createDirectories(Paths.get(properties.getInputDir())))
                        .filter(FileSystems.getDefault()
                                .getPathMatcher("regex:.+" + properties.getInputFileExtension())::matches)
                        .collect(Collectors.toList());

        int size = files.size();
        Paths.get(properties.getOutputDir()).toFile().mkdirs();
        IntStream.range(0, files.size()).forEach(i -> {
            log.info("Running " + (i + 1) + " / " + size);

            Path targetFile = files.get(i);
            String inputFile = targetFile.toString();
            String outputFile = properties.getOutputDir() + "/" + targetFile.getFileName().toString();
            log.info("Iinput file " + targetFile);

            Mat input = Imgcodecs.imread(inputFile);
            Imgproc.resize(input, input, new Size(input.width() * 1.5, input.height() * 1.5));
            Mat dstImage = maskRCnn.run(input);
            Imgcodecs.imwrite(outputFile, dstImage);

            log.info("Output file " + outputFile);
        });
    }
}
```

```java:DnnConfiguration
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package deepl.configre.dnn;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
 * @author jashika.t.e
 * @since 0.1
 */
import org.springframework.context.annotation.Configuration;

import deepl.controller.dnn.MaskRCnnRunner;
import deepl.dnn.impl.MaskRCnn;
import deepl.dnn.impl.RCnnProperties;

@Configuration
public class DnnConfiguration {

    @Bean
    public MaskRCnnRunner dnnRunner(MaskRCnn maskRCnn, RCnnProperties maskRCnnProperties) {
        return new MaskRCnnRunner(maskRCnn, maskRCnnProperties);
    }

    @Bean
    @ConfigurationProperties(prefix = "mask.rcnn")
    public RCnnProperties maskRCnnProperties() {
        RCnnProperties properties = new RCnnProperties();
        return properties;
    }
    
    @Bean
    public MaskRCnn maskRCnn(RCnnProperties maskRCnnProperties) throws IOException {

        maskRCnnProperties.setNames(Files.readAllLines(Paths.get(maskRCnnProperties.getLabelNamesTextPath())));
        for (String line : Files.readAllLines(Paths.get(maskRCnnProperties.getColorsTextPath()))) {
            maskRCnnProperties.getColors()
                    .add(Arrays.stream(line.split(" ")).mapToDouble(Double::parseDouble).toArray());
        }

        Net net = Dnn.readNetFromTensorflow(maskRCnnProperties.getModelPath(), maskRCnnProperties.getConfigPath());
        net.setPreferableBackend(Dnn.DNN_BACKEND_CUDA);
        net.setPreferableTarget(Dnn.DNN_TARGET_CUDA);

        return new MaskRCnn(maskRCnnProperties, net);
    }
}

```

```java:RCnnProperties.java
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package deepl.dnn.impl;

import java.util.ArrayList;
import java.util.List;

import deepl.support.io.MediaFormat;

/**
 * @author jashika.t.e
 * @since 0.1
 */
public class RCnnProperties {

    /**
     * default input directory.
     */
    private String DEFAULT_INPUT_DIR = "./data/input";

    /**
     * default output directory.
     */
    private String DEFAULT_OUTPUT_DIR = "./data/output";

    /**
     * TensorFlowModel:frozen_inference_graph.pb file path string.
     */
    private String modelPath = DEFAULT_INPUT_DIR + "/metadata/frozen_inference_graph.pb";

    /**
     * TensorFlowModel:pbtxt file path string.
     */
    private String configPath = DEFAULT_INPUT_DIR + "/metadata/mask_rcnn_inception_v2_coco_2018_01_28.pbtxt";

    /**
     * Coco:mscoco_labels.names text file path strein.
     */
    private String labelNamesTextPath = DEFAULT_INPUT_DIR + "/metadata/mscoco_labels.names";

    /**
     * Coco:mscoco_labels.color text file path strein.
     */
    private String colorsTextPath = DEFAULT_INPUT_DIR + "/metadata/colors.txt";

    /**
     * input data dir.
     */
    private String inputDir = DEFAULT_INPUT_DIR + "/images";

    /**
     * output data dir.
     */
    private String outputDir = DEFAULT_OUTPUT_DIR + "/images";

    /**
     * input file extension.
     */
    private MediaFormat inputFileExtension = MediaFormat.NONE;

    /**
     * output file extension.
     */
    private MediaFormat outputFileExtension = MediaFormat.NONE;

    /**
     * labelNames.
     */
    private List<String> names;

    /**
     * colors.
     */
    private List<double[]> colors = new ArrayList<>();

    private Rectangle rectangle = new Rectangle();

    private Mask mask = new Mask();

    private Detection detection = new Detection();
    
    /**
     * threshold
     */
    private double threshold = 0.5;

    /**
     * @return the modelPath
     */
    public String getModelPath() {
        return modelPath;
    }

    /**
     * @param modelPath the modelPath to set
     */
    public void setModelPath(String modelPath) {
        this.modelPath = modelPath;
    }

    /**
     * @return the configPath
     */
    public String getConfigPath() {
        return configPath;
    }

    /**
     * @param configPath the configPath to set
     */
    public void setConfigPath(String configPath) {
        this.configPath = configPath;
    }

    /**
     * @return the labelNamesTextPath
     */
    public String getLabelNamesTextPath() {
        return labelNamesTextPath;
    }

    /**
     * @param labelNamesTextPath the labelNamesTextPath to set
     */
    public void setLabelNamesTextPath(String labelNamesTextPath) {
        this.labelNamesTextPath = labelNamesTextPath;
    }

    /**
     * @return the colorsTextPath
     */
    public String getColorsTextPath() {
        return colorsTextPath;
    }

    /**
     * @param colorsTextPath the colorsTextPath to set
     */
    public void setColorsTextPath(String colorsTextPath) {
        this.colorsTextPath = colorsTextPath;
    }

    /**
     * @return the names
     */
    public List<String> getNames() {
        return names;
    }

    /**
     * @param names the names to set
     */
    public void setNames(List<String> names) {
        this.names = names;
    }

    /**
     * @return the colors
     */
    public List<double[]> getColors() {
        return colors;
    }

    /**
     * @param colors the colors to set
     */
    public void setColors(List<double[]> colors) {
        this.colors = colors;
    }

    /**
     * @return the threshold
     */
    public double getThreshold() {
        return threshold;
    }

    /**
     * @param threshold the threshold to set
     */
    public void setThreshold(double threshold) {
        this.threshold = threshold;
    }

    /**
     * @return the inputDir
     */
    public String getInputDir() {
        return inputDir;
    }

    /**
     * @param inputDir the inputDir to set
     */
    public void setInputDir(String inputDir) {
        this.inputDir = inputDir;
    }

    /**
     * @return the outputDir
     */
    public String getOutputDir() {
        return outputDir;
    }

    /**
     * @param outputDir the outputDir to set
     */
    public void setOutputDir(String outputDir) {
        this.outputDir = outputDir;
    }

    /**
     * @return the inputFileExtension
     */
    public MediaFormat getInputFileExtension() {
        return inputFileExtension;
    }

    /**
     * @return the outputFileExtension
     */
    public MediaFormat getOutputFileExtension() {
        return outputFileExtension;
    }

    /**
     * @param outputFileExtension the outputFileExtension to set
     */
    public void setOutputFileExtension(MediaFormat outputFileExtension) {
        this.outputFileExtension = outputFileExtension;
    }

    /**
     * @param inputFileExtension the inputFileExtension to set
     */
    public void setInputFileExtension(MediaFormat inputFileExtension) {
        this.inputFileExtension = inputFileExtension;
    }

    /**
     * @return the rectangle
     */
    public Rectangle getRectangle() {
        return rectangle;
    }

    /**
     * @param rectangle the rectangle to set
     */
    public void setRectangle(Rectangle rectangle) {
        this.rectangle = rectangle;
    }

    public Mask getMask() {
        return mask;
    }

    public void setMask(Mask mask) {
        this.mask = mask;
    }

    static class Detection {
        private String[] names = { "detection_out_final", "detection_masks" };

        /**
         * @return the names
         */
        public String[] getNames() {
            return names;
        }

        /**
         * @param names the names to set
         */
        public void setNames(String[] names) {
            this.names = names;
        }
    }

    static class Rectangle {
        /**
         * thickness.
         */
        private int thickness = 1;

        /**
         * fontScale.
         */
        private double fontScale = 0.4d;

        /**
         * @return the fontScale
         */
        public double getFontScale() {
            return fontScale;
        }

        /**
         * @param fontScale the fontScale to set
         */
        public void setFontScale(double fontScale) {
            this.fontScale = fontScale;
        }

        /**
         * @return the thickness
         */
        public int getThickness() {
            return thickness;
        }

        /**
         * @param thickness the thickness to set
         */
        public void setThickness(int thickness) {
            this.thickness = thickness;
        }
    }

    static class Mask {
        private double alpha = 1.0;
        private double beta = 0.5;
        private double gannma = 0;

        /**
         * @return the alpha
         */
        public double getAlpha() {
            return alpha;
        }

        /**
         * @param alpha the alpha to set
         */
        public void setAlpha(double alpha) {
            this.alpha = alpha;
        }

        /**
         * @return the beta
         */
        public double getBeta() {
            return beta;
        }

        /**
         * @param beta the beta to set
         */
        public void setBeta(double beta) {
            this.beta = beta;
        }

        /**
         * @return the gannma
         */
        public double getGannma() {
            return gannma;
        }

        /**
         * @param gannma the gannma to set
         */
        public void setGannma(double gannma) {
            this.gannma = gannma;
        }
    }

    /**
     * @return the detection
     */
    public Detection getDetection() {
        return detection;
    }

    /**
     * @param detection the detection to set
     */
    public void setDetection(Detection detection) {
        this.detection = detection;
    }
}
```

```yaml:application.yml
spring:
  main:
    banner-mode: off
    
management:
  endpoint:
    shutdown:
      enabled: true

logging:
  level:
    org.springframework.aop.interceptor.PerformanceMonitorInterceptor: trace

model: 
  rcnn: 
    name: mask_rcnn_inception_v2_coco_2018_01_28

mask:
  rcnn:
    model-path: ./data/${model.rcnn.name}/frozen_inference_graph.pb
    config-path: ./data/${model.rcnn.name}/mask_rcnn_inception_v2_coco_2018_01_28.pbtxt
    colors-text-path: ./data/${model.rcnn.name}/colors.txt
    label-names-text-path: ./data/${model.rcnn.name}/mscoco_labels.names
    input-dir: /usr/local/src/Mask_RCNN/images
    output-dir: ./output/${model.rcnn.name}
```

If there is demand, put it in git.