Git Product home page Git Product logo

picam's Introduction

Picam

Hex version

Picam is an Elixir library that provides a simple API for streaming MJPEG video and capturing JPEG stills using the camera module on Raspberry Pi devices running Linux.

Features currently supported by the API:

  • Set sharpness, contrast, brightness, saturation, ISO, and shutter speed values
  • Set the exposure, sensor, metering, and white balance modes
  • Set image and color effects
  • Rotate and flip the image vertically and horizontally
  • Set the exposure compensation (EV) level
  • Change the image size
  • Adjust JPEG fidelity through quality level, restart intervals, and region of interest
  • Enable or disable video stabilization
  • Adjust the video framerate
  • Render fullscreen or windowed video preview to HDMI and CSI displays

For specifics on the above features, please consult the Hex docs.

Requirements

Requirement Notes
Host Device Raspberry Pi 1, 2, 3, Zero/W Zero and Zero W require a special ribbon cable
Operating System Linux Works out of the box with Raspbian and Nerves builds
Camera Module V1, V2 Regular, NoIR. Note for V2 module, gpu_mem in /boot/config.txt must be set >= 192
C Libraries Broadcom VideoCore Located in /opt/vc by default. Override with VIDEOCORE_DIR

Installation

The package can be installed by adding picam to your list of dependencies in mix.exs:

def deps do
  [{:picam, "~> 0.4.0"}]
end

Usage

Picam uses a port application named raspijpgs that interfaces with the underlying Multi-Media Abstraction Layer (MMAL) API in VideoCore. The port is started by the Picam.Camera process.

For example, to write a JPEG still using the :sketch image effect to /tmp/frame.jpg:

iex(1)> Picam.Camera.start_link
{:ok, #PID<0.160.0>}

iex(2)> Picam.set_img_effect(:sketch)
:ok

iex(3)> Picam.set_size(640, 0) # 0 automatically calculates height
:ok

iex(4)> File.write!(Path.join(System.tmp_dir!, "frame.jpg"), Picam.next_frame)
:ok

iex(5)> Picam.set_img_effect(:none) # Disable the effect
:ok

If you receive an :unexpected_exit error immediately after starting the Picam.Camera process and you're using a V2 camera module, please check that you've set gpu_mem to a value >= 192 in /boot/config.txt. You can verify this has taken effect in your terminal using vcgencmd get_mem gpu.

More than likely you'll want to put the Picam.Camera process in your supervision tree rather than starting it manually:

# lib/my_app/application.ex

children = [
  worker(Picam.Camera, []),
  # ...
]

Faking the camera for development and testing

In order to facilitate running in dev and test modes on your development host, you can override the real Picam.Camera worker with Picam.FakeCamera by setting the :camera config option:

# config.exs

# ...

import_config "#{Mix.Project.config[:target]}.exs"
# config/host.exs

use Mix.Config
config :picam, camera: Picam.FakeCamera

This will cause Picam to use the FakeCamera back-end instead of the real Camera back-end, which streams a static image of the specified size at approximately the specified fps rate (using a naïve sleep-based delay between frames). In order for this to work, you will need to make sure you are staring the matching worker for your environment:

# lib/my_app/application.ex

camera = Application.get_env(:picam, :camera, Picam.Camera)

children = [
  worker(camera, []),
  # ...
]

When using the FakeCamera, all the normal Picam API commands will be validated but silently ignored, with the following exceptions:

  • Picam.set_fps/1 will set the desired frame rate (in frames per second)

  • Picam.set_size/2 only has static images built-in for the following resolutions:

    • 1920 x 1080
    • 1280 x 720
    • 640 x 480

    If any other resolution is specified, the static image will default back to 1280 x 720. If you want to test with an image of a particular size or with specific image contents, you can specify your own image with Picam.FakeCamera.set_image/1, which accepts a JPEG-encoded binary.

    For example:

    "image.jpg"
    |> File.read!()
    |> Picam.FakeCamera.set_image()

Examples

The examples directory is where you can find other useful demos of Picam in action. More examples will be added over time.

Directory Demo
picam_http Streaming MJPEG video using plug

Limitations

  • Currently only one camera is supported. If you intend to use more than one camera through an add-on compute module, please submit an issue.

Copyright and License

Copyright (c) 2013-2017, Broadcom Europe Ltd, Silvan Melchior, James Hughes, Frank Hunleth, Jeff Smith

Picam source code is licensed under the BSD 3-Clause License.

picam's People

Contributors

electricshaman avatar fhunleth avatar gregmefford avatar jmerriweather avatar raksonibs avatar visciang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

picam's Issues

PI 4 HQ Camera

Hi,

Thank you for such a great package.

I wonder if that's possible to add support for PI4 and their new HQ camera?

Thank you,
Pavel.

Issue on PI 4

I opened an issue about this on the nerves_system_rpi4 repo, but am now wondering if the issue is within Picam, and not the PI4 build root.

nerves-project/nerves_system_rpi4#45

When using PiCam on a PI 4, I get the following error. The same application software works fine on a PI 3.

iex(10)> File.write!(Path.join(System.tmp_dir!, "frame.jpg"), Picam.next_frame)
** (exit) exited in: GenServer.call(Picam.FakeCamera, :next_frame, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
    (elixir 1.10.4) lib/gen_server.ex:1013: GenServer.call/3

I intentionally don't have a FakeCamera enabled. If I enable one, I get fake output.

But, if I stop the nerves software, I am able to run raspistill and save a JPG on the PI 4:

iex> Application.stop(:camera)
iex> Application.stop(:picam) 
iex> System.cmd("/usr/bin/raspistill", ["-v", "-o", "/tmp/image.jpg"], stderr_to_stdout: true)

Any ideas on why Picam errors on the PI 4? What would be useful to help debug / isolate / resolve the issue?

no issue

Hello

I opend this issue accidentally, sorry!

Thank you for your great work!

Cryptic error when burning firmware

I'm trying to build firmware with Nerves and Picam, but so far I haven't been able to, due to an error that I cannot quite understand.

I'm trying to build formware for a "Raspberry Pi Zero W", which should be supported, at least that's what's the README.md seems to say.

Updating base firmware image with Erlang release...
scrub-otp-release.sh: ERROR: Unexpected executable format for '/home/jesterprince/Projects/elixir/nervesy/camera/_build/_nerves-tmp/rootfs-additions/srv/erlang/lib/picam-0.4.0/priv/raspijpgs'

Got:
 readelf:ARM;0x5000400, Version5 EABI, hard-float ABI

Expecting:
 readelf:ARM;0x5000200, Version5 EABI, soft-float ABI

This file was compiled for the host or a different target and probably
will not work.

Check the following:

1. Are you using a path dependency in your mix deps? If so, run
   'mix clean' in that directory to avoid pulling in any of its
   build products.

2. Did you recently upgrade to Nerves 1.3 or Distillery 2.0? Make
   sure that your 'rel/config.exs' has 'plugin Nerves'. See
   https://hexdocs.pm/nerves/updating-projects.html#updating-from-v1-0-to-v1-3-0

3. Did you recently upgrade or change your Nerves system? If so,
   try cleaning and rebuilding this project and its deps.

4. Are you building outside of Nerves' mix integration? If so,
   make sure that you've sourced 'nerves-env.sh'.

If you're still having trouble, please file an issue on Github
at https://github.com/nerves-project/nerves_system_br/issues.

** (Mix) Nerves encountered an error. %IO.Stream{device: :standard_io, line_or_bytes: :line, raw: true}

It's definitely an error related to Picam, because the firmware builds when I don't use Picam. The source is literally just a default Nerves project with {:picam, "~> 0.4.0"} added to the mix.exs.

I also checked the 4 suggestions, and I'm sure none of them are the reason for the problem.

Is this a bug, am I doing something blatantly wrong or am I just being an idiot? Any Help would be appreciated.

Support annotations

MMAL supports annotating videos with arbitrary overlaid text. It would be really nice if we could set this from Elixir.

Using an USB webcam instead of the Raspi Camera

I already have an USB webcam lying around, and would rather not buy an extra hardware component if not really necessary, so therefore:

Is it possible to use a USB webcam instead of the Raspberry Pi Camera module? (Or if not, how difficult would it for me to fork the project and add this, possibly creating a Pull Request if desired?)

Add support for multiple simultaneous resolution, color, and codec settings

It would be great to be able to configure multiple outputs with different resolution and color space.

For example in my https://github.com/GregMefford/omni_eye training project, we use the Picam video to both stream a video to a display and to use zbar to scan for barcodes in the image. Ideally, we would send high-resolution color video to the screen and low-resolution luma-only images to the barcode-scanner, so that it has to do less processing work.

Another example would be to have a lower resolution for video preview being displayed on a small screen and a higher resolution for video being streamed or captured to a file. Similarly, it might be useful to have the preview as an RGB bitmap and the full video encoded as H.264 or MJPEG.

GenServer exiting with :unexpected_exit

Hi,

I just tried to use picam on my Raspberry Pi 3 running Nerves but I only get this error:

iex([email protected])1> Picam.Camera.start_link
{:ok, #PID<0.440.0>}
iex([email protected])2>
20:10:04.387 [warn] Camera GenServer exiting: :unexpected_exit

22:10:24.982 [error] GenServer Picam.Camera terminating
** (stop) :unexpected_exit
Last message: {#Port<6189.2630>, {:exit_status, 1}}
State: %{port: #Port<6189.2630>, requests: []}
** (EXIT from #PID<0.437.0>) :unexpected_exit

Am I doing something wrong?

Report motion vectors

A side effect of encoding video is calculating motion vectors in hardware. It would be nice to get the motion vectors in Elixir to support things like simple motion detection and optical flow calculations. It wouldn't be as good as what can be done with OpenCV, but it's computationally cheap and would provide for some fun experiments.

Support HDMI video preview

There was a question on the Nerves Slack channel about whether it was possible to preview the video on the HDMI output, and I've also wanted to do this in the past but haven't gotten around to working on support for it yet. Just creating an issue here in case someone gets a chance to work on it.

Receiving timeout when taking a photo for larger image sizes

I am trying to take photos at full resolution of my camera using a Raspberry Pi 3.
Setting the size of the image to anything above 1024x768 and a high quality (80) using:

Picam.set_size(1024, 768)
Picam.set_quality(80)

results in a timeout:

** (exit) exited in: GenServer.call(Picam.Camera, :next_frame, 5000)
    ** (EXIT) time out
    (elixir) lib/gen_server.ex:774: GenServer.call/3

I've tried explicitly changing the timeout calling GenServer.call(Picam.Camera, :next_frame, 10000) directly (rather than Picam.next_frame) but changing the timeout never results in a successful image.

Is there a way around this? or something that I'm perhaps doing wrong here?

Can't run Picam.Camera.start_link()

I've installed a fresh version of Raspbian as well as Elixir and Nerves. I also downloaded this file and moved it into /home/pi. When I SSH into the file picam/lib/picam, I open up iex and type c("camera.ex"). Once I do this, it says
[Picam.Camera]
which I assume is correct. However when I go to run Picam.Camera.start_link() I get the following error.
image

Any help is much appreciated.

Add support for querying the current camera configuration

As I was working on my training materials for LoneStar, I really wanted to have a way that I could ask the camera what its current configuration is, so I started my own GenServer to keep track of the config commands it's sending to Picam, but this is the wrong way to go because it'll get inconsistent with crashes, has to know too much about the Picam API, etc.

I think the Picam.Camera is the right place to store the current state, since it's already handling all the messages coming through, and it's already a GenServer.

Very poor performance

This library works great when using very low quality settings but as soon as as I set jpeg quality over like 30 or 40 I get timeouts. This is for still images. Also full hd 1920x1080 stills don't work with quality of 20. Is this why the default quality is set to 15?

I'm using a pi zero, so maybe it is just not powerful enough? I'm using nerves. I'll try installing raspbian and use the command line tools (https://www.raspberrypi.org/documentation/raspbian/applications/camera.md), see if they yield the same disappointed results.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.