servlets.FillAreaByScribble.java Source code

Java tutorial

Introduction

Here is the source code for servlets.FillAreaByScribble.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package servlets;

import classes.ContourComparator;
import classes.FloodFillFacade;
import classes.ImageUtils;
import com.google.gson.Gson;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.highgui.Highgui;
import org.opencv.imgproc.Imgproc;
import responses.FindingResponse;

/**
 *
 * @author Gonzalo
 */
public class FillAreaByScribble extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {

            String imageForTextRecognition = request.getParameter("imageForTextRecognition") + ".png";
            String isSingleRegion = request.getParameter("isSingleRegion");
            boolean makeSingleRegion = isSingleRegion.toLowerCase().equals("true");

            Mat original = ImageUtils.loadImage(imageForTextRecognition, request);
            Mat image = original.clone();
            Mat mask = Mat.zeros(image.rows() + 2, image.cols() + 2, CvType.CV_8UC1);

            String samplingPoints = request.getParameter("samplingPoints");

            Gson gson = new Gson();
            Point[] tmpPoints = gson.fromJson(samplingPoints, Point[].class);

            ArrayList<Point> userPoints = new ArrayList<Point>(Arrays.asList(tmpPoints));

            Mat userPointsImage = image.clone();

            ArrayList<Mat> maskRegions = new ArrayList<>();

            Random random = new Random();
            int b = random.nextInt(256);
            int g = random.nextInt(256);
            int r = random.nextInt(256);
            Scalar newVal = new Scalar(b, g, r);
            FloodFillFacade floodFillFacade = new FloodFillFacade();

            int k = 0;

            for (int i = 0; i < userPoints.size(); i++) {
                Point point = userPoints.get(i);

                image = floodFillFacade.fill(image, mask, (int) point.x, (int) point.y, newVal);

                Mat seedImage = original.clone();
                Core.circle(seedImage, point, 9, new Scalar(0, 0, 255), -1);
                Core.putText(userPointsImage, "" + k, new Point(point.x + 5, point.y + 5), 3, 0.5,
                        new Scalar(0, 0, 0));
                //                ImageUtils.saveImage(seedImage, "mask_" + k + "_seed" + imageForTextRecognition + ".png", request);

                if (!makeSingleRegion) {
                    Mat element = new Mat(3, 3, CvType.CV_8U, new Scalar(1));
                    Imgproc.morphologyEx(mask, mask, Imgproc.MORPH_CLOSE, element, new Point(-1, -1), 3);
                    Imgproc.resize(mask, mask, original.size());
                }

                //                ImageUtils.saveImage(mask, "mask_" + k + "" + imageForTextRecognition + ".png", request);

                Mat dilatedMask = new Mat();

                int elementSide = 21;
                Mat element = new Mat(elementSide, elementSide, CvType.CV_8U, new Scalar(1));
                Imgproc.morphologyEx(mask, dilatedMask, Imgproc.MORPH_DILATE, element, new Point(-1, -1), 1);
                Imgproc.resize(dilatedMask, dilatedMask, original.size());

                //                ImageUtils.saveImage(dilatedMask, "mask_" + k + "_dilated" + imageForTextRecognition + ".png", request);

                maskRegions.add(mask);

                if (!makeSingleRegion) {
                    int totalRemovedPoints = filterPoints(userPoints, dilatedMask);
                    if (totalRemovedPoints > 0) {
                        i = -1; // so that the algorithm starts again at the first element of the userPoints array
                    }
                } else {
                    filterPoints(userPoints, mask);
                }

                //                System.out.println("Total points after filtering:");
                //                System.out.println(userPoints.size());

                if (!makeSingleRegion) {
                    mask = Mat.zeros(original.rows() + 2, original.cols() + 2, CvType.CV_8UC1);
                }

                k++;
            }

            ArrayList<FindingResponse> findingResponses = new ArrayList<>();

            if (makeSingleRegion) {

                Mat element = new Mat(3, 3, CvType.CV_8U, new Scalar(1));
                Imgproc.morphologyEx(mask, mask, Imgproc.MORPH_CLOSE, element, new Point(-1, -1), 3);

                Imgproc.resize(mask, mask, image.size());

                List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
                Imgproc.findContours(mask.clone(), contours, new Mat(), Imgproc.RETR_EXTERNAL,
                        Imgproc.CHAIN_APPROX_NONE);

                MatOfPoint biggestContour = contours.get(0); // getting the biggest contour
                double contourArea = Imgproc.contourArea(biggestContour);

                if (contours.size() > 1) {
                    biggestContour = Collections.max(contours, new ContourComparator()); // getting the biggest contour in case there are more than one
                }

                Point[] biggestContourPoints = biggestContour.toArray();
                String path = "M " + (int) biggestContourPoints[0].x + " " + (int) biggestContourPoints[0].y + " ";
                for (int i = 1; i < biggestContourPoints.length; ++i) {
                    Point v = biggestContourPoints[i];
                    path += "L " + (int) v.x + " " + (int) v.y + " ";
                }
                path += "Z";

                //                System.out.println("path:");
                //                System.out.println(path);

                Rect computedSearchWindow = Imgproc.boundingRect(biggestContour);
                Point massCenter = computedSearchWindow.tl();

                Scalar meanColor = Core.mean(original, mask);

                //                ImageUtils.saveImage(mask, "single_mask_" + imageForTextRecognition + ".png", request);

                FindingResponse findingResponse = new FindingResponse(path, meanColor, massCenter, -1, contourArea);
                findingResponses.add(findingResponse);

            } else {

                float imageArea = image.cols() * image.rows();

                for (int j = 0; j < maskRegions.size(); j++) {
                    Mat region = maskRegions.get(j);

                    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
                    Imgproc.findContours(region.clone(), contours, new Mat(), Imgproc.RETR_EXTERNAL,
                            Imgproc.CHAIN_APPROX_NONE);

                    MatOfPoint biggestContour = contours.get(0); // getting the biggest contour

                    if (contours.size() > 1) {
                        biggestContour = Collections.max(contours, new ContourComparator()); // getting the biggest contour in case there are more than one
                    }

                    double contourArea = Imgproc.contourArea(biggestContour);

                    if (contourArea / imageArea < 0.8) { // only areas less than 80% of that of the image are accepted

                        Point[] biggestContourPoints = biggestContour.toArray();
                        String path = "M " + (int) biggestContourPoints[0].x + " " + (int) biggestContourPoints[0].y
                                + " ";
                        for (int i = 1; i < biggestContourPoints.length; ++i) {
                            Point v = biggestContourPoints[i];
                            path += "L " + (int) v.x + " " + (int) v.y + " ";
                        }
                        path += "Z";

                        Rect computedSearchWindow = Imgproc.boundingRect(biggestContour);
                        Point massCenter = computedSearchWindow.tl();

                        //                        System.out.println("Contour area: " + contourArea);

                        Mat contoursImage = userPointsImage.clone();
                        Imgproc.drawContours(contoursImage, contours, 0, newVal, 1);

                        Scalar meanColor = Core.mean(original, region);

                        FindingResponse findingResponse = new FindingResponse(path, meanColor, massCenter, -1,
                                contourArea);
                        findingResponses.add(findingResponse);

                        //                        ImageUtils.saveImage(contoursImage, "mask_" + j + "_contourned" + imageForTextRecognition + ".png", request);

                    }

                }

            }

            String jsonResponse = gson.toJson(findingResponses, ArrayList.class);

            out.println(jsonResponse);

        }
    }

    public static int filterPoints(ArrayList<Point> points, Mat mask) {
        int removals = 0;
        for (int i = 0; i < points.size(); i++) {
            Point point = points.get(i);
            int col = (int) point.x;
            int row = (int) point.y;
            double[] value = mask.get(row, col);
            if (value[0] != 0) {
                //                System.out.println("Removing");
                points.remove(point);
                i--;
                removals++;
            }
        }
        return removals;
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}