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

Customizable WebcamMotionDetector, WebcamUpdater, FsWebcamDevice #307

Open krok32 opened 9 years ago

krok32 commented 9 years ago

I'd like to implement further changes. All of them should be backward compatible and allow customization.

1] WebcamMotionDetector Currently, I can only override whole class WebcamMotionDetector, but fields are private, so it would be pain. Also WebcamMotionDetector implemens Runner and Inverter which i don't want to re-implement.

I suggest: Algorithm for motion detection would be customizable, so part of the detect() method would be moved to the DefaultDetectorAlgorithm implementing IDetectorAlgorithm

I'm considering following methods: BufferedImage IDetectorAlgorithm.prepareImage(BufferedImage original) // blur, gray, resize, etc... boolean IDetectorAlgorithm.detect(BufferedImage previousModified, BufferedImage currentModified); Poing IDetectorAlgorithm.getCog(); double IDetectorAlgorithm.getArea();

2] WebcamUpdater Currently, I can't modify delay, and since I'm running it on RasPI, it's pretty slow and delay is always 0.

I suggest: Part of the method WebcamUpdater.tick() would be moved to new class DefaultDelayCalculator implementing IDelayCalculator, so another implementation may be specified as parameter of Webcam.open() method.

Following method should be enough... long IDelayCalculator.calculateDelay(snapshotDuration, deviceFps)

3] FsWebcamDevice

fswebcam needs some specific parameters to work reliably on RasPI with some cheap webcams. If also some other drivers needed parameters, some common method setParameters(Map<String,Object>) would be helpful. I'm not sure about this. Anyway, I would commit configurable FsWebcamDevice if I knew how to parametrize it properly.

Please let me know what you thing about it, so I can implement it.

sarxos commented 9 years ago

Hi @krok32,

These are indeed very useful changes :+1: Please go ahead and do what you want to do.

When you will be doing your changes please push them in separate pull requests (for motion detector, webcam updater and fswebcam driver).

Just my few cents, so we keep the code style consistent:

  1. If this is possible, please avoid the "I" interface naming convention so we have DetectorAlgorithm instead of IDetectorAlgorithm and DelayCalculator instead of IDelayCalculator.
  2. Please make DefaultDetectorAlgorithm and DetectorAlgorithm public inner class/interface of the WebcamMotionDetector, or rather, if you want to have them separated in package (which is also good), please add the Webcam prefix at the beginning of class name.
  3. In regards to device specific parameters my first though is to make possibility to set them thru WebcamDriver impl. In such a case the parameters map would be common for all devices created by given driver. I'm not sure if this is what you desire or not. Something like:
class FsWebcamDevice {
   final Map<String, ?> parameters;
   FsWebcamDevice(File vfile, Map<String, ?> parameters) {
      this.parameters = parameters;
   }
   ... 
}
class FsWebcamDriver {
   Map<String, ?> parameters = ...
   public FsWebcamDriver(Map<String, ?> parameters) {
      this.parameters = parameters;
   }
   @Override
   public List<WebcamDevice> getDevices() {
      for (File vfile : VFFILTER.getVideoFiles()) {
         devices.add(new FsWebcamDevice(vfile, parameters));
      }
   }
   ...
}

The source code indents are made by tabs. If you want you can reuse formatter.xml (from project root) which can be imported to the Eclipse or IntelliJ to perform automated code formatting on save action.

krok32 commented 9 years ago

Regarding the device parameters, i suggest these changes

sarxos commented 9 years ago

Hi @krok32,

Adding new interface ConfigurableDevice or simply Configurable is imho a better option than modifying WebcamDevice interface. This new interface could be public static inner interface of WebcamDevice, same as BufferAccess and FPSSource are.

Except the Webcam.open(boolean async, DelayCalculator delayCalculator, Map<String, ?> params) please consider adding Webcam.setParameters(Map<String, ?> params), so one could set parameters before the open(..) is invoked.

public void setParameters(Map<String, ?> parameters) {
  WebcamDevice device = getDevice();
  if (device instanceof Configurable) {
    ((Configurable) device).setParameters(parameters);
  } else {
    LOG.debug("Webcam device {} is not configurable", device);
  }
}

And, of course, your new open(..) signature would be still added where setParameters(..) is invoked:

public boolean open(boolean async, DelayCalculator delayCalculator,Map<String, ?> parameters) {
  if (open.compareAndSet(false, true)) {
    setParameters(parameters);
    ...
  }
  ...
}

Please let me know if this fit into your idea and needs.

I hope you don't mind if I add @author Martin Krok (krok32) annotation on the classes/interfaces you created?

krok32 commented 9 years ago

Ok, I'll add