Удаление фона OpenCV Java, дать правильные пороговые значения - PullRequest
0 голосов
/ 29 октября 2019

Я новичок в обработке изображений с opencv. Я знаю Java, и я пытаюсь удалить фон из изображения. Я собрал некоторый код из интернета и попытался собрать его вместе, и результаты довольно хорошие, но я что-то упустил.

public class RemoveBackground {


    public static void main(String[] args) {
        // Loading the OpenCV core library
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // Reading the Image from the file and storing it in to a Matrix object
        String file = "C:\\Users\\KobitPC\\Desktop\\Test Pictures/orange.jpg";
        Mat man = Imgcodecs.imread(file);
        man = doCanny(man);

        Imgcodecs.imwrite("C:\\Users\\KobitPC\\Desktop\\Test Pictures/cany.jpg", man);

        System.out.println("Image doCanny");

        man = doBackgroundRemoval(man);

        Imgcodecs.imwrite("C:\\Users\\KobitPC\\Desktop\\Test Pictures/bgremoved.png", man);

        System.out.println("Image backgroundRemoval");
    }

    private static Mat doCanny(Mat frame) {
        double threshold = 0;
        // init
        Mat grayImage = new Mat();
        Mat detectedEdges = new Mat();

        // convert to grayscale
        Imgproc.cvtColor(frame, grayImage, Imgproc.COLOR_BGR2GRAY);

        // reduce noise with a 3x3 kernel
        Imgproc.blur(grayImage, detectedEdges, new Size(3, 3));

        // canny detector, with ratio of lower:upper threshold of 3:1
       Imgproc.Canny(detectedEdges, detectedEdges, threshold, threshold * 3, 3, false);

        // using Canny's output as a mask, display the result
        Mat dest = new Mat();
        Core.add(dest, Scalar.all(0), dest);
        frame.copyTo(dest, detectedEdges);

        return dest;
    }

    /**
     * Perform the operations needed for removing a uniform background
     *
     * @param frame the current frame
     * @return an image with only foreground objects
     */
    private static Mat doBackgroundRemoval(Mat frame) {

         // init
        Mat hsvImg = new Mat();
        List<Mat> hsvPlanes = new ArrayList<>();
        Mat thresholdImg = new Mat();

        // threshold the image with the histogram average value
        hsvImg.create(frame.size(), CvType.CV_8U);
        Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV);
        Core.split(hsvImg, hsvPlanes);

        double threshValue = getHistAverage(hsvImg, hsvPlanes.get(0));


        Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY_INV);

       // Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);

        Imgproc.blur(thresholdImg, thresholdImg, new Size(5, 5));

        // dilate to fill gaps, erode to smooth edges
        Imgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, 1), 6);
        Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, 1), 6);

        Imgproc.threshold(thresholdImg, thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);

        // create the new image
        Mat foreground = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
        frame.copyTo(foreground, thresholdImg);

        return foreground;
    }
    /**
     * Get the average value of the histogram representing the image Hue
     * component
     *
     * @param hsvImg
     *            the current frame in HSV
     * @param hueValues
     *            the Hue component of the current frame
     * @return the average value
     */
    private static double getHistAverage(Mat hsvImg, Mat hueValues) {
            // init
            double average = 0.0;
            Mat hist_hue = new Mat();
            MatOfInt histSize = new MatOfInt(180);
            List<Mat> hue = new ArrayList<>();
            hue.add(hueValues);

            // compute the histogram
            Imgproc.calcHist(hue, new MatOfInt(0), new Mat(), hist_hue, histSize, new MatOfFloat(0, 179));

            // get the average for each bin
            for (int h = 0; h < 180; h++)
            {
                    average += (hist_hue.get(h, 0)[0] * h);
            }

            return average = average / hsvImg.size().height / hsvImg.size().width;
    }
} 

Входное изображение

Input image

Выходное изображение

Output image after background removal

Форма футболки очень хорошо обрезана, но я не понимаю, почему футболка содержит эти линии. Я знаю, что есть способ удалить их и получить чистое изображение без фона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...