Crop screenshot to window view port (or clearly bordered part inside view port)

asked 2014-11-18 05:59:10 -0600

cjtown gravatar image

updated 2014-11-18 08:00:26 -0600

berak gravatar image

I'm new to OpenCV and am trying to write a method using the v2.4.9 Java bindings to crop an ALT+PRINTSCREEN screenshot to the viewport of the window or to a clearly bordered part inside the viewport. The contents of the window viewport are inherently unknown. However, when cropping to a sub-selection is required, this would be clearly indicated by "greying out" all of the window view port contents except that which needs to be cropped to.

So far, I have been following a thread on stackoverflow as guidance. However, whilst this works for some cases, it is not quite what I need even though finding contours seems to be the right way to go. My method as it currently stands is included below.

Any hints or tips on how to approach this problem using OpenCV and/or modify my existing code would be very much appreciated! Thanks.

public void crop(File in, File out) throws Exception {
    Mat img = Highgui.imread(in.getAbsolutePath(), Highgui.CV_LOAD_IMAGE_GRAYSCALE);
    Mat orig = img.clone();
    Imgproc.threshold(img, img, 100, 128, Imgproc.THRESH_BINARY_INV);
    Point centre = new Point(new double[] { (double) img.width() / 2, (double) img.height() / 2 });
    List<MatOfPoint> contours = new ArrayList<>();
    Mat hierarchy = new Mat();
    Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    double min = Double.MAX_VALUE;
    Rect rect = new Rect();
    for (MatOfPoint contour : contours) {
        Rect bounds = Imgproc.boundingRect(contour);
        if (bounds.height > img.height() / 2 & bounds.width > img.width() / 2) {
            continue;
        }
        Point p = new Point(bounds.x, bounds.y);
        double d = Math.sqrt(Math.pow(p.x - centre.x, 2) + Math.pow(p.y - centre.y, 2));
        if (d < min) {
            min = d;
            rect = bounds;
        }
    }
    int pad = 5;
    rect.x = rect.x - pad;
    rect.y = rect.y - pad;
    rect.width = rect.width + 2 * pad;
    rect.height = rect.height + 2 * pad;
    Mat result = orig.submat(rect);
    Highgui.imwrite(out.getAbsolutePath(), result);
}
edit retag flag offensive close merge delete