lvsn / CameraNetwork

ROS camera network system
2 stars 0 forks source link

Add auto-exposure bracketing feature #12

Open jflalonde opened 9 years ago

jflalonde commented 9 years ago

Using auto-exposure bracketing on the Mark iii allows the capture of multiple exposures extremely fast. For example, using the following script, the 7 exposures needed for the sky camera can be captured in 6 seconds, instead of 40+ seconds with the current setup.

gphoto2 --set-config /main/capturesettings/aeb="+/- 3" --set-config /main/capturesettings/aperture="16" --set-config /main/capturesettings/shutterspeed="1/1000" --set-config /main/actions/eosremoterelease=2 --wait-event=1s

gphoto2 --set-config /main/capturesettings/aperture="4" --set-config /main/capturesettings/shutterspeed="1/30" --set-config /main/actions/eosremoterelease=2 --wait-event=1s

gphoto2 --set-config /main/capturesettings/aeb=0 --set-config /main/capturesettings/shutterspeed="1" --capture-image

Let's talk about this soon!

soravux commented 9 years ago

I've previously handled this issue with gphoto in this bash script I gave to @jacenfox some time ago. In CameraNetwork, the delay could be handled in Python instead of specifying "--wait-event=1s", for instance.

But to make it robust, the _run_gphoto function should do a loop over its Popen to try multiples times (like 5, with a delay of 100ms between calls for example). This would be to prevent a call that would fail because the previous call still isn't done, which can happend quite often.

jacenfox commented 9 years ago

Using auto-exposure bracketing will greatly improve the capturing speed. It is different from the normal capturing we are using now. In this model camera could capture mutiple exposure images just in one setting! Thanks to professor JF find this method, this allow us to capture 7 images in 6sec. This is faster than adjusting the "--wait-event" in normal capture model.

soravux commented 9 years ago

Sorry, after reading my post I realise I wasn't really clear on my intentions: I was proposing a method to get the 7 photos in even less than 6 seconds if we merge the two ideas together.

The bracketing trick is an awesome find for sure!

jflalonde commented 9 years ago

Thing is, I think the wait-event is necessary... More experiments necessary :)

Sent from my iPhone

On Nov 1, 2014, at 12:56, Yannick Hold notifications@github.com wrote:

Sorry, after reading my post I realise I wasn't really clear on my intentions: I was proposing a method to get the 7 photos in even less than 6 seconds if we merge the two ideas together.

The bracketing trick is an awesome find for sure!

— Reply to this email directly or view it on GitHub.

soravux commented 9 years ago

I bet you a beer I can get the 7 exposures in less than 5 seconds!

Joking aside, the experiments I did a while ago worked when I discarded the wait-event (taking into account that there were no transfer in the request). The problem was subsequent requests to gphoto2: they crashed or weren't executed if the previous command was not completed. The cool thing about wait-event is that it'll wait for the delay after the command was issued, while issuing a sleep command asynchronously would begin before the command was even issued to the camera (because of gphoto2 handshake and delays). Hence, it's not because there is a sleep(0.5) in the code that a capture of 1/2s is done...

I just thought that if there was a way to either poll quickly the camera to ask it if it's busy, or call the gphoto2 anyway and check its return value (and re-issue the command if it crashed), we could improve even more the time footprint.

But I may be wrong, these details are dim in my memory... And I'm talking about ~30% gain, which is nowhere near the 85% gain of auto-exposure bracketing...

jflalonde commented 9 years ago

You're on for the beer :)

Sent from my iPhone

On Nov 1, 2014, at 19:22, Yannick Hold notifications@github.com wrote:

I bet you a beer I can get the 7 exposures in less than 5 seconds!

Joking aside, the experiments I did a while ago worked when I discarded the wait-event (taking into account that there were no transfer in the request). The problem was subsequent requests to gphoto2: they crashed or weren't executed if the previous command was not completed. The cool thing about wait-event is that it'll wait for the delay after the command was issued, while issuing a sleep command asynchronously would begin before the command was even issued to the camera (because of gphoto2 handshake and delays). Hence, it's not because there is a sleep(0.5) in the code that a capture of 1/2s is done...

I just thought that if there was a way to either poll quickly the camera to ask it if it's busy, or call the gphoto2 anyway and check its return value (and re-issue the command if it crashed), we could improve even more the time footprint.

But I may be wrong, these details are dim in my memory... And I'm talking about ~30% gain, which is nowhere near the 85% gain of auto-exposure bracketing...

— Reply to this email directly or view it on GitHub.

jacenfox commented 9 years ago

You owe a beer to our Professor :) haha Yes, both of you are exactl right! We need to keep the wait-event. Maybe this is the reason why we lost one CR2 file at 15:11-20141022.

jflalonde commented 9 years ago

Tell you what: I owe you both beers if you can integrate the exposure bracketing feature in the cam network :)

Sent from my iPhone

On Nov 1, 2014, at 22:13, jacenfox notifications@github.com wrote:

You owe a beer to our Professor :) haha Yes, both of you are exactl right! We need to keep the wait-event. Maybe this is the reason why we lost one CR2 file at 15:11-20141022.

— Reply to this email directly or view it on GitHub.

soravux commented 9 years ago

I'm on in this week, probably Tuesday or Wednesday!

MathGaron commented 9 years ago

Any idea how to implement it without breaking compatibility with other device that dont support this feature? Unless we feel that hdr may be done only with auto-bracketing... If there is a way to check if gphoto can set the mode it would be a good start. And do we have to physically turn on a switch?

For the timing, I remember stumbling on a feature about wait-event, and waiting on events instead of time, I tried some things but did not understand what gphoto was capturing as "event", it was not acting like i wanted so I made it wait on time instead. But if we understand it and if it is stable, maybe it will be the most efficient way, if we know exactly the quantity of event after a shot?

But in fact like soravux said, it is little optimisation vs the bracketting feature, and these can be implemented easily as 2 different features.

soravux commented 9 years ago

@jacenfox : There seems to be problems with the auto exposure bracketing in recent versions that were published around 2013 (see here and here). Maybe it's the same problem you experienced when trying the feature? If so, updating to the latest nightly build or newer stable release (if there is) should fix the problem.

@MathGaron : It's possible to probe the camera abilities (--abilities) before performing the --set-config. I'm not sure whether aeb is in the probed abilities, though. There's no switch to turn on physically on the camera.

I share your wariness about the event catching of gphoto. I saw multiple problems of people trying to use that to trigger something on various forums. I tried to use the shell version of gphoto2 to display all the triggers and I wasn't really sure that everything that should be happening was really happening. We could give it another shot, but I doubt it will lead to something stable... Actually, I think the goal is to wait for a specific event to trigger and not a quantity of events after a shot.

soravux commented 9 years ago

I just realized that using the shell version of gphoto more than halves the execution time of every command issued. This is because loading the gphoto executable image in memory (and all its libraries) takes a long time on my system (and very probably even more on the pi).

Something along the lines of :

time gphoto2 --shell <<< '
set-config f-number=13
set-config shutterspeed=0,0002
capture-image wait-event=0s
'

is actually more than twice as fast as issuing the commands separately. (Sorry for the Nikon config, I don't have a Canon at home :p ). Another bonus feature: it doesn't probe for the camera for each command.

jflalonde commented 9 years ago

Keep working hard, that beer is coming! :)

On Nov 5, 2014, at 12:18 , Yannick Hold notifications@github.com wrote:

I just realized that using the shell version of gphoto more than halves the execution time of every command issued. This is because loading the gphoto executable image in memory (and all its libraries) takes a long time on my system (and very probably even more on the pi).

Something along the lines of :

time gphoto2 --shell <<< ' set-config f-number=13 set-config shutterspeed=0,0002 capture-image wait-event=0s ' is actually more than twice as fast as issuing the commands separately. (Sorry for the Nikon config, I don't have a Canon at home :p ). Another bonus feature: it doesn't probe for the camera for each command.

— Reply to this email directly or view it on GitHub https://github.com/lvsn/CameraNetwork/issues/12#issuecomment-61845643.

MathGaron commented 9 years ago

is it possible for you to push your work? at least on another branch if it disturb the system? I would like to know whats going on to make sure we are not working on the same thing. If you are working on the bracket feature I will take a look to make download back

soravux commented 9 years ago

@MathGaron : The only thing that I have working and stable on the 5D mark III that speeds up the capture is this gist. I try to keep it updated as soon as I find new stuff. As of now, I am not fully happy with the time it takes (~30 seconds on a Canon, ~18 seconds on a Nikon), so I'm still working on it.

The auto exposure bracketing made the camera firmware crash after a while, so I'm trying to understand what's happening.

One thing is pretty sure though, it would be useful if we could batch the HDR as I did in the gist (one single gphoto2 instance to take every picture). If you have some time, could you work on a way to achieve that?

MathGaron commented 9 years ago

Sure I will work on it tomorow, thanks for the feedback! (I was just curious about the way you wanted to implement it ;) )

MathGaron commented 9 years ago

After some thought, I believe the best way to implement it will be to make camera_driver offer a new service that will add parameter sets to a queue, and capture_camera will capture using the queue by default. so set_camera is not deprecated : it is to set the camera's actual value.

This way, no change have to be made to the GUI, and some minor changes to the controler, it will give the possibility to implement specialized chain action to the drivers (picam and gphoto) and wont break any other function using set_camera, capture_camera etc.

soravux commented 9 years ago

@MathGaron : I agree. If the "hdr" checkbox is disabled, capture_camera won't set the parameters and only take the picture using the current settings. Is that what you plan?

MathGaron commented 9 years ago

yes, it will call the same function as it is currently doing. From the GUI point of view, only the HDR check box will use the " --shell " function

From the controller point of view when the hdr flag is up, instead of calling set_camera, capture_camera, set_camera, capture_camera... it will simply call : set_parameter,set_parameter, set_parameter, ... , capture_camera.

And in the driver you can handle the special case when the parameterQueue have data in it (rigth now I construct the shell command, eventually , it will be the bracketing command)

It should be ready tomorrow (no more battery in my camera! )

MathGaron commented 9 years ago

The setup is ready, but the gain will not be that important using --shell, we need to add the wait-event after each capture to make sure that gphoto2 dont try to set-config while the camera is taking picture, I will push this afternoon after some tests, everything will be ready to accept the bracketing check and command! (I cant test bracketing rigth now, my camera does not support it :( )

soravux commented 9 years ago

@MathGaron : When doing my tests using --shell , I did not need to set a wait-event; the shell waited for the event to complete before it allowed to enter a new command. Which version of gphoto2 do you have? Here, I have 2.5.5 with libgphoto2 at 2.5.5.1 .

MathGaron commented 9 years ago

@soravux : I did update to 2.5.5 but there is case when the shutterspeed time is to high, it miss the next capture. I dont know if it depend only on the camera, I only tested with the Nikon D3100 for now. I will check if I can have something at least stable for now ( I will try to add wait-events) before pushing.

--Shell seems to add wait-event 3s, but it does not wait 3 seconds.

EDIT: with wait-event 1s, we are ok for most shot, without it, on my Nikon, shot with an aperture time of more than 0.4s make the next capture crash

soravux commented 9 years ago

Could you reproduce the problem on the Canon 5D mark III? I couldn't... (Subsequent calls to capture-image all work for up to 1 second shutter time.) In fact, there seems to be a 6 seconds delay at each capture-image that I did not have with my Nikon D90.

You're right, the --shell interface says "wait-event 3s" which is not true on my Nikon tests. That "may" explan the Canon delays, though.

MathGaron commented 9 years ago

So you mean that the waiting time is worst with Canon markIII? if the solution work only on one model maybe its not a good idea at long term? and i was wondering if there was a difference between --shell ... and calling functions on the same commande : ex : --set-config... --capture-image --set-config...

of course finding a general solution may be impossible, every camera seems to be totally different

soravux commented 9 years ago

Yes, the waiting time was twice as worst on the Canon than my Nikon.

The best, in my opinion, would be to either: 1) modify gphoto to remove most of its useless (for us) communications and (most importantly) remove the communication of ~30 Mb of data at each capture, or 2) capture the USB packets (using wireshark), remove the packets we don't need and replay them using usbreplay or alike when we want to capture (without using gphoto2).

Using one of these two solutions would allow us to perform 7 shots in minimal time, but would be limited to our camera model.

jflalonde commented 9 years ago

As we discussed, I vote for the option which will use gphoto2 as is. Therefore, I would encourage you to look at using the camera-specific aeb option, and investigating the stability issues, to make sure that it still works after several captures.

Perhaps doing things like resetting the USB connection every once in a while could help? I've had luck with this in the past... gphoto2 has the embedded --reset flag if I remember correctly.

soravux commented 9 years ago

@jflalonde : Will do.

I remember talking about it with @jacenfox which said to me that --reset did not work when it was in an invalid state. I'll test that further.

jflalonde commented 9 years ago

Yeah, but perhaps doing it periodically would prevent it from ever getting into an invalid state? Pure speculation, but could be worth trying...

Sent from my iPhone

On Nov 13, 2014, at 17:01, Yannick Hold notifications@github.com wrote:

@jflalonde : Will do.

I remember talking about it with @jacenfox which said to me that --reset did not work when it was in an invalid state. I'll test that further.

— Reply to this email directly or view it on GitHub.

jacenfox commented 9 years ago

Both of you are right, the --reset didn't work when the camera was waiting the 'trigger', if we --reset the camera in few minutes this may help to keep the camera fresh. Since the camera is working well at the begining, after many shootings it would enter an invalid state, if we --reset the camera periodically, the camera may be always stay in the begining state. May be this will help the camera never get into the invalid state.

jflalonde commented 9 years ago

@soravux Lots of maybes, but worth trying. :)

@MathGaron Another option to account for the differences between cameras is to allow the user to write the gphoto2 command directly in the web interface, and that command would be executed by the corresponding pi when the "capture" button is clicked. That could be some kind of superuser mode. Should I add this as another enhancement to avoid confusing the discussion threads?

soravux commented 9 years ago

@jflalonde : If we don't try, we won't ever know! :) I'll test whenever possible next week without preventing the skycam to take pictures.

I like your idea of an alternative command usable by powerusers. I made ticket #18 about it.

jflalonde commented 9 years ago

Great, thanks!

You can use the DRP camera for your tests.

On Nov 13, 2014, at 21:47 , Yannick Hold notifications@github.com wrote:

@jflalonde https://github.com/jflalonde : If we don't try, we won't ever know! :) I'll test whenever possible without preventing the skycam to take pictures.

I like your idea of an alternative command usable by powerusers. I made ticket #18 https://github.com/lvsn/CameraNetwork/issues/18 about it.

— Reply to this email directly or view it on GitHub https://github.com/lvsn/CameraNetwork/issues/12#issuecomment-63003130.

jacenfox commented 9 years ago

I have tested the camera again. I write the 3 gphoto2 AEB command in a .sh script. Then I use 'watch' to run this AEB script every 120 seconds. The camera will enter the invalid state when I using 'watch' to run the AEB script, I need to trigger the camera with by hand. However if I just run the AEB script in bash, the camre works well. I think the reason why the camera enter the invalid state is because when I was using "watch" to execute the AEB script every 120 seconds, the timer of the "watch" will confilt with the gphoto's timer in some times. Now I write a python script to run the AEB feature, the camera won't enter the invalid state for a long time. I should test the python script for a longer time. Here is the python script I use now:

import threading
import subprocess

# preset the ISO, fileformat etc.
def preset():
subprocess.call('gphoto2 --reset', shell=True)
# RAW 32; RAW+samall Fine JPG 12
subprocess.call('gphoto2 --set-config imageformat = 32', shell=True)

# keep photo in SD card
subprocess.call('gphoto2 --set-config capturetarget = 1', shell=True)
subprocess.call('gphoto2 --set-config iso = 1', shell=True)
subprocess.call('gphoto2 --set-config autopoweroff="0"', shell=True)

# refresh camera in every 300 seconds # if confilted with capture()?
def refeshCamera():
print "refeshCamera"    
# threading.Timer(120.0, refeshCamera).start()
preset()
print "Done"

# using auto-exposure bracketing capture images
def capturingAEB():
subprocess.call('gphoto2 --set-config /main/capturesettings/aeb="+/- 3" --set-config /main/capturesettings/aperture="16" --set-config /main/capturesettings/shutterspeed="1/1000" --set-config /main/actions/eosremoterelease=2 --wait-event=1s', shell=True)

subprocess.call('gphoto2 --set-config /main/capturesettings/aperture="4" --set-config /main/capturesettings/shutterspeed="1/30" --set-config /main/actions/eosremoterelease=2 --wait-event=1s', shell=True)

subprocess.call('gphoto2 --set-config /main/capturesettings/aeb=0 --set-config /main/capturesettings/shutterspeed="1" --capture-image', shell=True)

# take a group of images every 120 seconds
def capture():
print "Capturing"   
threading.Timer(120.0, capture).start()
capturingAEB()
print "Done"

refeshCamera()
capture()
jflalonde commented 9 years ago

@soravux did you also observe the invalid state when using watch, or were you doing something else?

@jacenfox how long did you test this? It would be good to leave it running all night (in your office), and see if it's still running the next day...

Sounds like a promising avenue to pursue!

jacenfox commented 9 years ago

I test this python script for about an hour, it worked well. I will test the python script for a longer time this week ;)

MathGaron commented 9 years ago

Good idea for the superuser hacker mode :p next weekend I will start exploring the possibility to check for aeb support before tacking hdr capture, if we can do this, the software will decide if it takes standard capture or aeb. Im sure it wont be too hard to do, the only thing we need to think is the way the user input data for aeb vs standard mode

jflalonde commented 9 years ago

@MathGaron One thing to keep in mind is that the current HDR mode works a bit differently than the AEB.

In the HDR mode, one has to specify all the individual parameters for each shot. E.g. shot 1: f=5.6, t=1/100s, shot 2: f=7.4, t=1/250s. This is completely custom.

In the AEB mode, one has to specify the "center" exposure, and the camera will automatically compute the other exposures based on the "+/-" setting, and the total number of shots. The "+/-" setting can be configured via gphoto2, but the total number of shots has to be entered manually in the menu, I don't think it can be set via gphoto2, unfortunately.

Based on this difference, I don't know whether the software can automatically decide if HDR or AEB is chosen... Also I think we should brainstorm about the UI before implementing anything, since the manner in which we're going to be interacting with the system might help you guys decide how to actually implement the feature...

MathGaron commented 9 years ago

Yes it wont be easy to make it transparent.. I think a brainstorm would be a good idea, we could talk about the features we want and things to stabilize for next release.

jacenfox commented 9 years ago

The python code won't make the camera enter the invalid state. I tested this script for almost two whole days, it works well. Yes, we need to set the total number of shots before we shooting in AEB mode, then we can leave it there. One thing would be great, if our webGUI could load or recommend a default Frequency and Quantity for different cameras, i.e. Frequency =120, Quantity = -1 for skycam.

jflalonde commented 9 years ago

Wonderful! Thanks for performing these experiments, @jacenfox! This is encouraging for the future, looks like AEB can in fact be stable.

MathGaron commented 9 years ago

Ok so my plan for aeb :

So this way, you will be able to take in one call normal pictures and bracket one. I believe the hard part will be to have a good timing for aeb to work well