Ask Your Question

Revision history [back]

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

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);
}
click to hide/show revision 2
retagged

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

berak gravatar image

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

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);
}