sarxos / webcam-capture

The goal of this project is to allow integrated or USB-connected webcams to be accessed directly from Java. Using provided libraries users are able to read camera images and detect motion. Main project consist of several sub projects - the root one, which contains required classes, build-in webcam driver compatible with Windows, Linux and Mac OS, which can stream images as fast as your camera can serve them (up to 50 FPS). Main project can be used standalone, but user is able to replace build-in driver with different one - such as OpenIMAJ, GStreamer, V4L4j, JMF, LTI-CIVIL, FMJ, etc.
http://webcam-capture.sarxos.pl
MIT License
2.27k stars 1.11k forks source link

Question: Rotate/flip webcam stream by 90°/180° #581

Closed githubtrey closed 6 years ago

githubtrey commented 6 years ago

Hello,

Does somebody know an easy way to rotate/flip the webcam stream within a panel? Maybe a "non-easy" solution? I couldn't find a solution so far.

Thank you

sarxos commented 6 years ago

Hi @githubtrey,

This is unfortunately impossible in case of normal USB webcams.

But in case of IP cameras this is possible with a "non-easy" solution. In most cases IP cameras are controlled by a HTTP requests, so you can use developer console from any modern browser (e.g. Firefox or Chrome) to trace down which requests are being made to the camera endpoint, and then implement your own IpCamDevice which will send these requests with internal HTTP client.

Implementing own IP camera device by extending IpCamDevice is rather simple - there are already several dedicated device implementations in the code:

https://github.com/sarxos/webcam-capture/tree/master/webcam-capture-drivers/driver-ipcam/src/main/java/com/github/sarxos/webcam/ds/ipcam/device

You would just have to add new methods to control pan/tilt and send corresponding HTTP requests. And this, together with tracing down HTTP requests it uses, is a "non-easy" solution. But it's doable IMO.

sarxos commented 6 years ago

@githubtrey,

I'm very sorry, after reading your post for the second time I think I missed the point... You asked about flip/rotate image in webcam panel and I answered by providing detail on how to do pan/tilt in IP camera. Silly me :)

Flipping

To flip image in webcam panel you can simply use:

panel.setMirrored(boolean);

Example:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;

@SuppressWarnings("serial")
public class WebcamPanelExample {

    public static void main(String[] args) throws InterruptedException {

        final Webcam webcam = Webcam.getDefault();
        webcam.setViewSize(WebcamResolution.QVGA.getSize());

        final WebcamPanel panel = new WebcamPanel(webcam);
        panel.setFPSDisplayed(true);
        panel.setImageSizeDisplayed(true);
        panel.setMirrored(true);

        final JCheckBox flip = new JCheckBox();
        flip.setSelected(true);
        flip.setAction(new AbstractAction("Flip") {

            @Override
            public void actionPerformed(ActionEvent e) {
                panel.setMirrored(flip.isSelected());
            }
        });

        JFrame window = new JFrame("Test webcam panel");
        window.setLayout(new FlowLayout());
        window.add(panel);
        window.add(flip);
        window.setResizable(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.pack();
        window.setVisible(true);
    }
}

The effect is:

1 2

Rotating

Rotation is not so simple and requires more "advanced" solution, but hey, it's still possible ;) You have two options to do that, either:

  1. Use Painter interface of Webcampanel to rotate image viewed in panel (but original image from webcam.getImage() will remain unmodified), or
  2. Use WebcamImageTransformer interface to transform original image captured from webcam by webcam.getImage() (since this rotates original image, the view in webcam panel will also be rotated).

Example for case 1:

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.util.jh.JHFlipFilter;

public class WebcamPanelRotationExample {

    public static void main(String[] args) throws InterruptedException {

        final Webcam webcam = Webcam.getDefault();
        webcam.setViewSize(WebcamResolution.QVGA.getSize());

        final WebcamPanel panel = new WebcamPanel(webcam);
        panel.setFPSDisplayed(true);
        panel.setImageSizeDisplayed(true);

        final JHFlipFilter rotate = new JHFlipFilter(JHFlipFilter.FLIP_90CW);

        final WebcamPanel.Painter painter = panel.new DefaultPainter() {

            @Override
            public void paintImage(WebcamPanel owner, BufferedImage image, Graphics2D g2) {
                image = rotate.filter(image, null);
                super.paintImage(owner, image, g2);
            }

        };

        panel.setPainter(painter);

        JFrame window = new JFrame("Test webcam panel");
        window.add(panel);
        window.setResizable(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.pack();
        window.setVisible(true);
    }
}

The effect is:

1

Example for case 2:

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;

import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamImageTransformer;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamPanel.DrawMode;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.util.jh.JHFlipFilter;

/**
 * This example demonstrates how to use {@link WebcamImageTransformer} to rotate the image from
 * camera by using {@link JHFlipFilter} from Jerry Huxtable filters package.
 *
 * @author Bartosz Firyn (sarxos)
 */
public class ImageTransformerRotationExample implements WebcamImageTransformer {

    /**
     * This is filter from JH Labs which flips buffered image 90 degrees clockwise. For more details
     * please follow to the <a href="http://www.jhlabs.com/ip/filters/index.html">JH Labs Filters<a>
     * home page (filters source code can be found
     * <a href="https://github.com/axet/jhlabs">here</a>).
     */
    private final BufferedImageOp filter = new JHFlipFilter(JHFlipFilter.FLIP_90CW);

    public ImageTransformerRotationExample() {

        // use VGA resolution

        Dimension size = WebcamResolution.VGA.getSize();

        // get default webcam and set image transformer to this (transformer will modify image after
        // it's received from webcam, in this case it will rotate it)

        Webcam webcam = Webcam.getDefault();
        webcam.setViewSize(size);
        webcam.setImageTransformer(this);
        webcam.open();

        // create window

        JFrame window = new JFrame("Test Rotation");

        // and webcam panel

        WebcamPanel panel = new WebcamPanel(webcam);
        panel.setFPSDisplayed(true);
        panel.setDrawMode(DrawMode.FIT);

        // add panel to window

        window.add(panel);
        window.pack();
        window.setVisible(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public BufferedImage transform(BufferedImage image) {

        // this will do rotation on image

        return filter.filter(image, null);
    }

    public static void main(String[] args) {
        new ImageTransformerRotationExample();
    }
}

The effect is:

1

githubtrey commented 6 years ago

Just one thing:

AWESOME !!!

You saved my day!

Remark: I was looking at the WebcamImageTransformer, however I thought this would just draw on top of a stream (like in the some funny frames example). Sorry about this.

sarxos commented 6 years ago

@githubtrey,

Yes, the WebcamImageTransformer is actually drawing on the original images from a stream and therefore when you try to get single frame from a stream you will get it transformed.

The WebcamPanel.Painter, from the other hand, modifies only view displayed in webcam panel and left original stream frames unmodified.

sarxos commented 6 years ago

Thanks Rey! Good luck with your project!

stolario commented 5 years ago

Is it possible to use JHFlipFilter to mirror image?