Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend picamera with more parameters #521

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

nvtkaszpir
Copy link
Contributor

@nvtkaszpir nvtkaszpir commented Dec 29, 2019

I needed to adjust donkey to work with NoIR camera, so I extended picamera class with extra options.

I suggest experimenting with PICAMERA_IMAGE_EFFECT='emboss' or PICAMERA_ROTATION=180 :)

@codecov-io
Copy link

Codecov Report

Merging #521 into dev will increase coverage by 0.07%.
The diff coverage is 47.5%.

Impacted file tree graph

@@            Coverage Diff             @@
##              dev     #521      +/-   ##
==========================================
+ Coverage   37.11%   37.18%   +0.07%     
==========================================
  Files          30       30              
  Lines        5510     5548      +38     
  Branches      635      636       +1     
==========================================
+ Hits         2045     2063      +18     
- Misses       3317     3337      +20     
  Partials      148      148
Impacted Files Coverage Δ
donkeycar/templates/complete.py 20.44% <0%> (ø) ⬆️
donkeycar/templates/cfg_complete.py 100% <100%> (ø) ⬆️
donkeycar/parts/camera.py 22.05% <4.76%> (-2.4%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3bd8541...b17b614. Read the comment docs.

Copy link
Collaborator

@tikurahul tikurahul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for sending us the PR.

However, I think there are too many parameters being exposed in the config, and I am not sure what the eventual goal is. It might also be too confusing, to someone who does not know what they are doing.

My main problem with this change is that it exposes a lot of implementation detail via config, so if ever we moved away from our current camera driver, we would have to break backward compatibility which would be extremely unfortunate.

I will let in the other core contributors chime in for their opinion. I think in general, changes like these are better a part of your fork, so you can point people to it if they would like to know how that works.

@nvtkaszpir
Copy link
Contributor Author

  1. There are many additional parameters to control camera, which are very useful when handling car in different light conditions or with different camera model (like NoIR cameras) or in different mounting options (rotation). Frankly speaking I was surprised that it was not implemented earlier - I suspect that most people used normal cameras in very good lighting conditions and the issues were non existent, thus no need to implement improvements for the camera performance. Also using specific camera in specific conditions may render it really hard to use (for example the images from NoIR camera in certain light condition become extremely pink and may present issues for some people).

  2. Yes it's exposes quite a lot of parameters, but only for PiCamera. I skipped some parameters but indeed looking at it now on the next day morning the list may be too excessive.

The list of parameters is indeed long but I tried to keep the variables in config prefixed with PICAMERA_ so that it is easily distinguishable from other cameras.
Also that's why there are config.py to set default values, so that user does not have to have all of them in the config.

  1. There are already exposed parameters that may break backward compatibility or are applied only to picam (vflip/hflip for example), but on the other hand used pi camera python module is rather well maintained and there may be hardly any other alternative out there.
    But then I believe other python modules are more problematic than camera itself (for example bumping tensorflow to 2.x in the future?)

4.There are already parameters in the configs that are not usable for everyone (just take example of parameters for different cameras). Maybe it is time to think about refactoring the config itself?

@tikurahul
Copy link
Collaborator

tikurahul commented Dec 29, 2019

I agree it’s useful to have these options. My disagreement is about config bloat. I was actually not thrilled about some of the other configuration options that you mention before. And I think we might want to undo those changes as well.

I think making everything a configuration has diminishing returns because at this point the amount of config for the camera actually exceeds the lines of code for the camera part. I would much rather advanced users forked the repo to add their camera optimizations.

@adammconway
Copy link
Contributor

Would breaking this out into a separate config file for camera settings make sense? I know that can cause other issues down the line, but at least it could be retired as we move to new cameras etc.

@tawnkramer
Copy link
Contributor

I like that the camera part has all the options available. I'm not 100% confident those defaults are the ones we want. Have you looked at the driver code to see what the defaults are?

@nvtkaszpir
Copy link
Contributor Author

Yes, I've taken defaults from the python PiCamera library.

Copy link
Contributor

@DocGarbanzo DocGarbanzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change is good but should be a little bit re-factored, addressing previous comments. I believe, having access to the camera parameters can be quite useful, maybe we can improve the camera settings to make donkey's eyesight better - I experience a significant impact from light conditions in the inferencing performance. Maybe some settings here can help to create more uniform pictures? Would be great if folks could play around with that.

@@ -11,7 +11,7 @@ def run_threaded(self):
return self.frame

class PiCamera(BaseCamera):
def __init__(self, image_w=160, image_h=120, image_d=3, framerate=20, vflip=False, hflip=False):
def __init__(self, image_w=160, image_h=120, image_d=3, framerate=20, vflip=False, hflip=False, awb_mode='auto', awb_gains=(1.0, 1.0), brightness=50, color_effects=None, contrast=0, exposure_compensation=0, exposure_mode='auto', image_denoise=True, image_effect='none', image_effect_params=None, iso=0, meter_mode='average', rotation=0, saturation=0, sharpness=0, video_denoise=True, video_stabilization=False, zoom=(0.0, 0.0, 1.0, 1.0)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the additional parameters should be passed by dictionary (i.e. **kwargs) here, otherwise the interface is overloaded.

@@ -22,6 +22,32 @@ def __init__(self, image_w=160, image_h=120, image_d=3, framerate=20, vflip=Fals
self.camera.framerate = framerate
self.camera.vflip = vflip
self.camera.hflip = hflip
self.camera.awb_mode = awb_mode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then here, you would iterate through all the possible parameters of the camera using get() and providing a default values. Hence only required overwrites would need to be in the dictionary.

@@ -32,6 +32,25 @@
CAMERA_FRAMERATE = DRIVE_LOOP_HZ
CAMERA_VFLIP = False
CAMERA_HFLIP = False
# PI Camera specitic options, for more details see https://picamera.readthedocs.io/en/release-1.13/api_camera.html
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here, instead of passing all camera parameters, you would add a single dictionary as camera parameters. This should be empty, here and then different users can overwrite this to their needs. This should also address @tikurahul comment.

@@ -98,7 +98,7 @@ def drive(cfg, model_path=None, use_joystick=False, model_type=None, camera_type
inputs = ['angle', 'throttle']
elif cfg.CAMERA_TYPE == "PICAM":
from donkeycar.parts.camera import PiCamera
cam = PiCamera(image_w=cfg.IMAGE_W, image_h=cfg.IMAGE_H, image_d=cfg.IMAGE_DEPTH, framerate=cfg.CAMERA_FRAMERATE, vflip=cfg.CAMERA_VFLIP, hflip=cfg.CAMERA_HFLIP)
cam = PiCamera(image_w=cfg.IMAGE_W, image_h=cfg.IMAGE_H, image_d=cfg.IMAGE_DEPTH, framerate=cfg.CAMERA_FRAMERATE, vflip=cfg.CAMERA_VFLIP, hflip=cfg.CAMERA_HFLIP, awb_mode=cfg.PICAMERA_AWB_MODE, awb_gains=cfg.PICAMERA_AWB_GAINS, brightness=cfg.PICAMERA_BRIGHTNESS, color_effects=cfg.PICAMERA_COLOR_EFFECTS, contrast=cfg.PICAMERA_CONTRAST, exposure_compensation=cfg.PICAMERA_EXPOSURE_COMPENSATION, exposure_mode=cfg.PICAMERA_EXPOSURE_MODE, image_denoise=cfg.PICAMERA_IMAGE_DENOISE, image_effect=cfg.PICAMERA_IMAGE_EFFECT, image_effect_params=cfg.PICAMERA_IMAGE_EFFECT_PARAMS, iso=cfg.PICAMERA_ISO, meter_mode=cfg.PICAMERA_METER_MODE, rotation=cfg.PICAMERA_ROTATION, saturation=cfg.PICAMERA_SATURATION, sharpness=cfg.PICAMERA_SHARPNESS, video_denoise=cfg.PICAMERA_VIDEO_DENOISE, video_stabilization=cfg.PICAMERA_VIDEO_STABILIZATION, zoom=cfg.PICAMERA_ZOOM)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then here you would just add cfg.CAMERA_ARGS - or whatever you want to call it.

Copy link
Contributor Author

@nvtkaszpir nvtkaszpir Apr 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about var naming:

  • CAMERA_ARGS one could be used by any camera (but then it would be on user side to keep compatible parameters)
  • PICAMERA_ARGS would expliclty control picamera parameters, based on the module version. But this inroduces more config options bloat.

Moreover:

  • should the args contain the full set of args, such as image_w, image_h options or just extra args (which means image_w, image_h, framerate and some other would be added 'by default'?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would opt for PICAMERA_ARGS and keep the current image_w, etc parameters to maintain backward compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants