Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jetsonhacks committed Jan 22, 2022
1 parent 795e113 commit e799919
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 2 deletions.
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: Issue report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: ''

---

**Describe the issue**
Please describe the issue

**What version of L4T/JetPack**
L4T/JetPack version:

**What version of OpenCV**
OpenCV version:

**Python Version**
Python version if applicable:

**To Reproduce**
Steps to reproduce the behavior:
For example, what command line did you run?

**Expected behavior**
A clear and concise description of what you expected to happen.

**Additional context**
Add any other context about the problem here.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE REQUEST]"
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
96 changes: 94 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,96 @@
# USB-Camera
Code example for running V4L2 USB Cameras on NVIDIA Jetson Developer Kits
Code examples for running V4L2 USB Cameras on NVIDIA Jetson Developer Kits

# WORK IN PROGRESS
Here are a few examples on how to interface a USB Camera with a Jetson Developer Kit through V4L2 and GStreamer.

Typically "plug and play" USB cameras on Linux use the kernel module uvcvideo to interface with the Video 4 Linux subsystem (v4l2). Several specialty cameras such as the Stereolabs ZED camera and Intel RealSense cameras also use uvcvideo.

In the Jetson Camera Architecture, you can use V4L2 or GStreamer (which runs on top of V4L2) to interface with such devices. OpenCV is used in these samples to demonstrate how to read the cameras. OpenCV works with multiple camera front ends, including V4L2 and GStreamer. OpenCV is included in the default Jetson software install, and supports V4L2 and GStreamer in the default configuration.

There are other ways to interface through the same camera interfaces. For example, here are samples from NVIDIA on how to interface with V4L2 cameras using Input/Output Control (ioctl)

```
https://github.com/dusty-nv/jetson-utils
```
Many people use OpenCV for the ease of use to open a camera, read frames, and then display the frames without having to worry bout configuring a video capture interface or GUI display interface.

## Samples
The intent of the samples is to give a minimal sample script to be able to work with a USB camera. You will need to configure the scripts to meet your needs, specifially you will need to assign the correct video address, i.e. /dev/videoX must match your camera address, where X is a number. Make sure you read through the code.

#### usb-camera-simple.py
usb-camera-simple.py uses the V4L2 backend for OpenCV to interface with the camera (cv2.CAP_V4L2). You are able to use the V4L2 camera properties to configure the camera, once created. Note that some properties are only available when integrated properly with OpenCV. For example, even though V4L2 has a fourcc description for H.264 video, the default OpenCV is not compiled with libx264. This means that the video will not be decoded correctly.

To run:
```
$ python3 usb-camera-simple.py
```

#### usb-camera-gst.py
usb-camera-gst.py uses the GStreamer backend for OpenCV to interface with the camera (cv2.CAP_GSTREAMER). You are *not* able to use the V4l2 camera properties when using the GStreamer backend. The sample has a H.264 pipeline described which is commented out.

To run:
```
$ python3 usb-camera-gst.py
```
GStreamer is a very flexible framework, which in practice means there may be some challenges in configuring the pipelines for maximum performance. Also, different cameras may have different results on the same pipelines. However, much of this is covered online.

Note that OpenCV requires a 'BGR' pixel output input. This is usually placed before the appsink element.

#### face-detect-usb.py
face-detect-usb.py is an example of reading frames and manipulating them in OpenCV. The face and eye detection is performes using Haar cascades. The sample Haar cascades are in the default Jetson distribution.
To run:
```
$ python3 face-detect-usb.py
```

### OpenCV
The samples use OpenCV to render frames. The standard OpenCV release on the Jetson currently uses GTK+ as its graphic output. Also, OpenCV is compiled here with support for GStreamer and V4L2 Camera input. If you encounter issues and do not have the standard OpenCV installed, check to make sure that these are loaded and selected.

In Python3, to examine the options that were selected when OpenCV was built:
```
>>> import cv2
>>> print(cv2.getBuildInformation())
The GUI sections lists the graphics backend, the Video I/O sections lists the video front ends.
### Tools
A valuable tool for working with V4L2 cameras is v4l2-ctl. To install:
```
$ sudo apt install v4l-utils
```
Useful commands:
#### Return a List of Cameras
```
$ v4l2-ctl --list-devices
```
#### Get Camera Pixel Formats
Get the list of supported pixel formats. /dev/videoX for camera address, e.g.
```
$ v4l2-ctl --list-formats-ext -d /dev/video0
```
#### Get All Information about a Camera
Get the list of supported pixel formats. /dev/videoX for camera address, e.g.
```
$ v4l2-ctl --all -d /dev/video0
```
Lists driver, pixel formats, frame sizes, controls
### canberra-gtk-module
If you see the error:
```
Failed to load module "canberra-gtk-module"
```
Generally, this will not cause issues. However, you can remove the error with:
```
$ sudo apt install libcanberra-gtk-module
```
## Release
### January, 20200
* Initial Release
* JetPack 4.6.1, L4T 32.6.1
* Tested on Jetson Nano and Jetson Xavier NX
* Cameras tested: Logitech C920, Stereolabs ZED, Intel Realsense D435
80 changes: 80 additions & 0 deletions face-detect-usb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# MIT License
# Copyright (c) 2019 JetsonHacks
# See LICENSE for OpenCV license and additional information

# https://docs.opencv.org/3.3.1/d7/d8b/tutorial_py_face_detection.html
# On the Jetson Nano, OpenCV comes preinstalled
# Data files are in /usr/sharc/OpenCV

import cv2

window_title = "Face Detect"

def face_detect():
face_cascade = cv2.CascadeClassifier(
"/usr/share/opencv4/haarcascades/haarcascade_frontalface_default.xml"
)
eye_cascade = cv2.CascadeClassifier(
"/usr/share/opencv4/haarcascades/haarcascade_eye.xml"
)
# ASSIGN CAMERA ADDRESS HERE
camera_id="/dev/video0"
# Full list of Video Capture APIs (video backends): https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
# For webcams, we use V4L2
video_capture = cv2.VideoCapture(camera_id, cv2.CAP_V4L2)
"""
# How to set video capture properties using V4L2:
# Full list of Video Capture Properties for OpenCV: https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
#Select Pixel Format:
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'YUYV'))
# Two common formats, MJPG and H264
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
# Default libopencv on the Jetson is not linked against libx264, so H.264 is not available
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'H264'))
# Select frame size, FPS:
video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
video_capture.set(cv2.CAP_PROP_FPS, 30)
"""

if video_capture.isOpened():
try:
cv2.namedWindow(window_title, cv2.WINDOW_AUTOSIZE)
# Start counting the number of frames read and displayed
# left_camera.start_counting_fps()
while True:
_, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
roi_gray = gray[y : y + h, x : x + w]
roi_color = frame[y : y + h, x : x + w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(
roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2
)

# Check to see if the user closed the window
# Under GTK+, WND_PROP_VISIBLE does not work correctly. Under Qt it does
# GTK - Substitute WND_PROP_AUTOSIZE to detect if window has been closed by user
if cv2.getWindowProperty(window_title, cv2.WND_PROP_AUTOSIZE) >= 0:
cv2.imshow(window_title, frame)
else:
break

keyCode = cv2.waitKey(30) & 0xFF
# Stop the program on the ESC key or 'q'
if keyCode == 27 or keyCode == ord('q'):
break
finally:
video_capture.release()
cv2.destroyAllWindows()
else:
print("Unable to open camera")


if __name__ == "__main__":
face_detect()
67 changes: 67 additions & 0 deletions usb-camera-gst.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
#
# USB Camera - Simple
#
# Copyright (C) 2021-22 JetsonHacks ([email protected])
#
# MIT License
#

import sys

import cv2

window_title = "USB Camera"

# ASSIGN CAMERA ADRESS to DEVICE HERE!
pipeline = " ! ".join(["v4l2src device=/dev/video0",
"video/x-raw, width=640, height=480, framerate=30/1",
"videoconvert",
"video/x-raw, format=(string)BGR",
"appsink"
])

# Sample pipeline for H.264 video, tested on Logitech C920
h264_pipeline = " ! ".join(["v4l2src device=/dev/video0",
"video/x-h264, width=1280, height=720, framerate=30/1, format=H264",
"avdec_h264",
"videoconvert",
"video/x-raw, format=(string)BGR",
"appsink sync=false"
])

def show_camera():

# Full list of Video Capture APIs (video backends): https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
# For webcams, we use V4L2
video_capture = cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)

if video_capture.isOpened():
try:
window_handle = cv2.namedWindow(
window_title, cv2.WINDOW_AUTOSIZE)
# Window
while True:
ret_val, frame = video_capture.read()
# Check to see if the user closed the window
# Under GTK+ (Jetson Default), WND_PROP_VISIBLE does not work correctly. Under Qt it does
# GTK - Substitute WND_PROP_AUTOSIZE to detect if window has been closed by user
if cv2.getWindowProperty(window_title, cv2.WND_PROP_AUTOSIZE) >= 0:
cv2.imshow(window_title, frame)
else:
break
keyCode = cv2.waitKey(10) & 0xFF
# Stop the program on the ESC key or 'q'
if keyCode == 27 or keyCode == ord('q'):
break

finally:
video_capture.release()
cv2.destroyAllWindows()
else:
print("Error: Unable to open camera")


if __name__ == "__main__":

show_camera()
64 changes: 64 additions & 0 deletions usb-camera-simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
#
# USB Camera - Simple
#
# Copyright (C) 2021-22 JetsonHacks ([email protected])
#
# MIT License
#

import sys

import cv2

window_title = "USB Camera"

def show_camera():
# ASSIGN CAMERA ADDRESS HERE
camera_id = "/dev/video0"
# Full list of Video Capture APIs (video backends): https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
# For webcams, we use V4L2
video_capture = cv2.VideoCapture(camera_id, cv2.CAP_V4L2)
"""
# How to set video capture properties using V4L2:
# Full list of Video Capture Properties for OpenCV: https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
#Select Pixel Format:
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'YUYV'))
# Two common formats, MJPG and H264
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
# Default libopencv on the Jetson is not linked against libx264, so H.264 is not available
# video_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'H264'))
# Select frame size, FPS:
video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
video_capture.set(cv2.CAP_PROP_FPS, 30)
"""
if video_capture.isOpened():
try:
window_handle = cv2.namedWindow(
window_title, cv2.WINDOW_AUTOSIZE )
# Window
while True:
ret_val, frame = video_capture.read()
# Check to see if the user closed the window
# Under GTK+ (Jetson Default), WND_PROP_VISIBLE does not work correctly. Under Qt it does
# GTK - Substitute WND_PROP_AUTOSIZE to detect if window has been closed by user
if cv2.getWindowProperty(window_title, cv2.WND_PROP_AUTOSIZE) >= 0:
cv2.imshow(window_title, frame)
else:
break
keyCode = cv2.waitKey(10) & 0xFF
# Stop the program on the ESC key or 'q'
if keyCode == 27 or keyCode == ord('q'):
break

finally:
video_capture.release()
cv2.destroyAllWindows()
else:
print("Unable to open camera")


if __name__ == "__main__":

show_camera()

0 comments on commit e799919

Please sign in to comment.