Module: Framegrabber

Defined in:
lib/framegrabber.rb,
lib/framegrabber/version.rb

Constant Summary collapse

VERSION =
'0.2.0'

Class Method Summary collapse

Class Method Details

.grab_frame ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'ext/grab_frame_ext/grab_frame_ext.cpp', line 55

static VALUE grab_frame(VALUE _self) {
  Mat frame = grab();

  VALUE result = rb_ary_new_capa(frame.cols);

  if(frame.empty()) {
    return result;
  }

  int i = 0, j = 0;
  for(i=0; i<frame.rows; ++i) {
    VALUE row = rb_ary_new_capa(frame.cols);
    for(j=0; j<frame.cols; j++) {
      VALUE pixel = rb_ary_new_capa(3);
      unsigned char * p = frame.ptr(i, j); // Y first, X after
      rb_ary_store(pixel, 0, ULL2NUM(p[2])); // R
      rb_ary_store(pixel, 1, ULL2NUM(p[1])); // G
      rb_ary_store(pixel, 2, ULL2NUM(p[0])); // B

      rb_ary_store(row, j, pixel);
    }
    rb_ary_store(result, i, row);
  }
  return result;
}

.grab_image ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/framegrabber.rb', line 12

def self.grab_image
  # Discard first frame (original hack to ensure camera is ready)
  grab_frame
  frame = grab_frame

  # Use system ImageMagick to convert raw RGB data to image
  require 'tempfile'
  Tempfile.open(['framegrabber', '.rgb']) do |temp_rgb|
    temp_rgb.binmode
    temp_rgb.write(frame.flatten.pack('C*'))
    temp_rgb.close

    Tempfile.open(['framegrabber', '.png']) do |temp_png|
      temp_png.close

      # Convert RGB data to PNG using ImageMagick
      system('magick', '-size', "#{frame.first.size}x#{frame.size}",
             '-depth', '8', "rgb:#{temp_rgb.path}", temp_png.path)

      # Read the PNG with RMagick
      img = Magick::Image.read(temp_png.path).first
      return img
    end
  end
end

.open(deviceID) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'ext/grab_frame_ext/grab_frame_ext.cpp', line 10

static VALUE open(VALUE _self, VALUE deviceID) {
    int camID = NUM2INT(deviceID);
    cap.open(camID);

    if (!cap.isOpened()) {
      rb_raise(rb_eRuntimeError, "Unable to open camera %d", camID);
    }

    // Wait for camera to provide a valid frame
    Mat frame;
    int attempts = 0;
    const int max_attempts = 50; // 5 seconds at 100ms intervals
    while (attempts < max_attempts) {
      cap.read(frame);
      if (!frame.empty()) {
        break;
      }
      usleep(100000); // 100ms
      attempts++;
    }

    if (frame.empty()) {
      cap.release();
      rb_raise(rb_eRuntimeError, "Camera %d failed to provide valid frame within timeout", camID);
    }

    return Qnil;
}

.release ⇒ Object



39
40
41
42
# File 'ext/grab_frame_ext/grab_frame_ext.cpp', line 39

static VALUE release(VALUE _self) {
    cap.release();
    return Qnil;
}