Robobot camera

From Rsewiki
(Difference between revisions)
Jump to: navigation, search
(Raspberry Pi OS)
(Use from OpenCV (C++))
 
(13 intermediate revisions by one user not shown)
Line 2: Line 2:
  
 
== camera settings ==
 
== camera settings ==
<!--
 
=== On Raspberry PI Debian OS. ===
 
  
The used camera has limited possibilities.
+
=== Data formats ===
 
+
640 x 480 at 25 FPS using MJPG coding seems like a working resolution.
+
 
+
All higher resolutions seem to crash the camera driver, requiring a reboot.
+
 
+
BUT, after a few, sometimes, successful captures, things go wrong, and 'sudo dmesg' shows something like:
+
 
+
[  237.889889] usb 1-1.5: new high-speed USB device number 6 using dwc2
+
[  237.991458] usb 1-1.5: New USB device found, idVendor=1224, idProduct=2a25, bcdDevice= 1.00
+
[  237.991505] usb 1-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=0
+
[  237.991524] usb 1-1.5: Product: USB PHY 2.0
+
[  237.991540] usb 1-1.5: Manufacturer: Jieli Technology
+
[  237.993188] usb 1-1.5: Found UVC 1.00 device USB PHY 2.0 (1224:2a25)
+
[  237.996497] input: USB PHY 2.0: GENERAL Webcam as /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/input/input1
+
[  238.004536] usb 1-1.5: set resolution quirk: cval->res = 16
+
[  348.102430] dwc2 3f980000.usb: dwc2_hc_halt() Channel can't be halted
+
[  348.109275] dwc2 3f980000.usb: dwc2_hc_halt() Channel can't be halted
+
 
+
A google search suggests that it is the USB driver 'dwc2_hc' that is to blame.
+
 
+
Trying Raspberry Pi OS instead.
+
-->
+
=== Raspberry Pi OS ===
+
  
 
The used camera is a 'Jieli Technology' camera of type 'USB PHY 2.0' (packed by Sandberg).
 
The used camera is a 'Jieli Technology' camera of type 'USB PHY 2.0' (packed by Sandberg).
Line 37: Line 12:
 
* MJPG coded 1280 x 720 pixels at 25 or 30 FPS
 
* MJPG coded 1280 x 720 pixels at 25 or 30 FPS
 
* MJPG coded 1920 x 1080 pixels at 25 or 30 FPS
 
* MJPG coded 1920 x 1080 pixels at 25 or 30 FPS
* MJPG coded 640 x 480 pixels at 25 or 30 FPS, cuts parts of the image to fit the format
+
* MJPG coded 640 x 480 pixels at 25 or 30 FPS; this mode cuts parts of the image width to fit the format
  
 
It also supports "raw" format as YUYV 4:2:2, but it seems like data loss occurs (fragmented images), so do not use this format.
 
It also supports "raw" format as YUYV 4:2:2, but it seems like data loss occurs (fragmented images), so do not use this format.
 +
 +
=== Use from OpenCV (C++) ===
 +
 +
First, open and set the camera format:
 +
 +
cv::VideoCapture cap;
 +
 +
void setup()
 +
{
 +
  int deviceID = 0;       
 +
  int apiID = cv::CAP_V4L2;
 +
  // open selected camera using selected API
 +
  cap.open(deviceID, apiID);
 +
  // check if we succeeded
 +
  camIsOpen = cap.isOpened();
 +
  if (not camIsOpen)
 +
  {
 +
    cerr << "ERROR! Unable to open camera\n";
 +
  }
 +
  else
 +
  {
 +
    uint32_t fourcc = cv::VideoWriter::fourcc('M','J','P','G');
 +
    cap.set(cv::CAP_PROP_FOURCC, fourcc);
 +
    // possible resolutions in JPEG coding
 +
    // (rows x columns) 320x640, 720x1280
 +
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
 +
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
 +
    cap.set(cv::CAP_PROP_FPS, 25);
 +
    // now the camera is ready for frame capture.
 +
    //
 +
    // debug print of accepted format:
 +
    union FourChar
 +
    { // the four characters are coded into a 32-bit integer.
 +
      uint32_t cc4;
 +
      char ccc[4];
 +
    } fmt;
 +
    fmt.cc4 = cap.get(cv::CAP_PROP_FOURCC); // get format
 +
    printf("# Video device %d: width=%g, height=%g, format=%c%c%c%c, FPS=%g\n",
 +
          dev,
 +
          cap.get(cv::CAP_PROP_FRAME_WIDTH),
 +
          cap.get(cv::CAP_PROP_FRAME_HEIGHT),
 +
          fmt.ccc[0], fmt.ccc[1], fmt.ccc[2], fmt.ccc[3],
 +
          cap.get(cv::CAP_PROP_FPS));
 +
  }
 +
 +
Then capture an image to a matrix called 'frame':
 +
 +
cv::Mat frame;
 +
bool gotFrame = false;
 +
 +
cap.read(frame);
 +
// mark as available
 +
gotFrame = not frame.empty();
 +
 +
The frame has 3 channels in BGR format.
 +
 +
To get the most recent image, it is a good idea to keep the buffer empty by discarding unneeded images by:
 +
 +
cap.grab();
 +
 +
In the template code, this is done in a thread (called loop())
 +
 +
=== Camera calibration ===
 +
 +
The camera has significant lens distortion and can be calibrated and rectified using the openCV calibration functions.
 +
 +
But, close to the centre of the image, this may not be needed.
 +
The main parameter here is the focal length.
 +
 +
The focal length f is approximately 1008 pixels, when the image format is 1280 x 720.
 +
 +
=== Finding 3D position of a known object ===
 +
 +
The relation between an object with pixel size '''Px''' and the focal length '''f''' is the same as the actual object size '''S''' and the distance '''D''' from the camera to the object along the centre axis of the camera, i.e.
 +
 +
Px    S
 +
--- = ---
 +
  f    D
 +
The unit of S and D could be in meters.
 +
 +
This can be used to find the 3D position of a known object.
 +
 +
The distance along the camera axis is thus (when the size of the object is known):
 +
* D = S * f / Px
 +
 +
The 3D position of the object can then be found in camera coordinates as (with x being to the right and y directed down
 +
 +
* xm = (xi - xc) * D / f
 +
* ym = (yi - yc) * D / f
 +
 +
where xm and ym are distances in meters from the camera axis, xi and yi is the image column and row for the (centre of the object), xc and yc are the column and row for the centre of the image, D is the distance to the object in meters and f is the focal length in pixels.

Latest revision as of 12:55, 6 December 2022

Back to Robobot

Contents

[edit] camera settings

[edit] Data formats

The used camera is a 'Jieli Technology' camera of type 'USB PHY 2.0' (packed by Sandberg).

The camera has limited control capabilities but supports the following data formats.

  • MJPG coded 640 x 320 pixels at 25 or 30 FPS
  • MJPG coded 1280 x 720 pixels at 25 or 30 FPS
  • MJPG coded 1920 x 1080 pixels at 25 or 30 FPS
  • MJPG coded 640 x 480 pixels at 25 or 30 FPS; this mode cuts parts of the image width to fit the format

It also supports "raw" format as YUYV 4:2:2, but it seems like data loss occurs (fragmented images), so do not use this format.

[edit] Use from OpenCV (C++)

First, open and set the camera format:

cv::VideoCapture cap;

void setup()
{
 int deviceID = 0;        
 int apiID = cv::CAP_V4L2;
 // open selected camera using selected API
 cap.open(deviceID, apiID);
 // check if we succeeded
 camIsOpen = cap.isOpened();
 if (not camIsOpen)
 {
   cerr << "ERROR! Unable to open camera\n";
 }
 else
 {
   uint32_t fourcc = cv::VideoWriter::fourcc('M','J','P','G'); 
   cap.set(cv::CAP_PROP_FOURCC, fourcc);
   // possible resolutions in JPEG coding
   // (rows x columns) 320x640, 720x1280
   cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
   cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
   cap.set(cv::CAP_PROP_FPS, 25);
   // now the camera is ready for frame capture. 
   //
   // debug print of accepted format:
   union FourChar
   { // the four characters are coded into a 32-bit integer.
     uint32_t cc4;
     char ccc[4];
   } fmt;
   fmt.cc4 = cap.get(cv::CAP_PROP_FOURCC); // get format
   printf("# Video device %d: width=%g, height=%g, format=%c%c%c%c, FPS=%g\n", 
          dev, 
          cap.get(cv::CAP_PROP_FRAME_WIDTH), 
          cap.get(cv::CAP_PROP_FRAME_HEIGHT), 
          fmt.ccc[0], fmt.ccc[1], fmt.ccc[2], fmt.ccc[3], 
          cap.get(cv::CAP_PROP_FPS));
 }

Then capture an image to a matrix called 'frame':

cv::Mat frame;
bool gotFrame = false;

cap.read(frame);
// mark as available
gotFrame = not frame.empty();

The frame has 3 channels in BGR format.

To get the most recent image, it is a good idea to keep the buffer empty by discarding unneeded images by:

cap.grab();

In the template code, this is done in a thread (called loop())

[edit] Camera calibration

The camera has significant lens distortion and can be calibrated and rectified using the openCV calibration functions.

But, close to the centre of the image, this may not be needed. The main parameter here is the focal length.

The focal length f is approximately 1008 pixels, when the image format is 1280 x 720.

[edit] Finding 3D position of a known object

The relation between an object with pixel size Px and the focal length f is the same as the actual object size S and the distance D from the camera to the object along the centre axis of the camera, i.e.

Px     S
--- = ---
 f     D

The unit of S and D could be in meters.

This can be used to find the 3D position of a known object.

The distance along the camera axis is thus (when the size of the object is known):

  • D = S * f / Px

The 3D position of the object can then be found in camera coordinates as (with x being to the right and y directed down

  • xm = (xi - xc) * D / f
  • ym = (yi - yc) * D / f

where xm and ym are distances in meters from the camera axis, xi and yi is the image column and row for the (centre of the object), xc and yc are the column and row for the centre of the image, D is the distance to the object in meters and f is the focal length in pixels.

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox