<< return to Pixycam.com

Python : grab images from PixyCam

Hi all !

I assume that this kind of topic remains a lot … But in this one, I would like to know if there is a way to get image/snap from pixy using Python ?

I’ve seen a topic where users provide a code C++ to do that :
*http://cmucam.org/boards/9/topics/5106?page=1&r=6834

Well, If solution in Python doesn’t exist, then is it possible to get the c++ images and use them in a Python program ?

thanks
Marino

Hi Marino,
I don’t believe we have chirpCall support in python yet. I’ll pass this on to our development team.

I just replied regarding getting frame data in libpixyusb2:

It requires C++ though.

Edward

Hi Edward,

Sorry I didn’t specify I have the Pixy CMUcam5 (the PixyCam1).

I tried to modify and to compile the code to grab frames from :
http://cmucam.org/boards/9/topics/5106?r=5242#message-5242

as a function “get_frame”:

int get_frame(void){
unsigned char current_frame[72000]; // ~largest possible given current hardware
unsigned char *pixels;  //returned pointer to video frame buffer
int32_t response, fourcc;
int8_t renderflags;
int return_value, res;
uint16_t width, height;
uint32_t  numPixels;

//  stop blob processing    
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
printf("STOP returned %d response %d\n", return_value, response);

response = 0;
return_value = pixy_command("cam_getFrame",  // String id for remote procedure
                             0x01, 0x00,      // mode 0 = 1280x800 25 fps
                             0x02,   0,        // xoffset
                             0x02,   0,         // yoffset
                             0x02, 1280,       // width
                             0x02, 40,       // height (56 max @ 1280 w)
                             0,              // separator
                             &response,      // pointer to mem address for return value
                            &fourcc,         //contrary to docs, the next 5 args are needed
                            &renderflags,
                            &width,
                            &height,
                            &numPixels,
                             &pixels,        // pointer to mem address for returned frame
                             0);

printf("getFrame returned %d response %d\n", return_value, response);
printf("returned w %d h %d npix %d\n",width,height,numPixels);

// quit now if not successful:
if(return_value != 0) return return_value;

// save this block
memcpy(&current_frame, pixels,numPixels);

// display average and 8x8 pixel dump

unsigned int i,j,ind,start;

// dump a few raw pixels

start=(height/2)*width+width/2; //roughly in middle of frame
for (i=0; i<8; i++) {
    for (j=0; j<8; j++) {
        ind = i*width + j + start;
        printf(" %02x",current_frame[ind]);
    }
    printf("\n");
 }
 // Sleep for 1/10 sec //
 //while(1) usleep(100000); //(exit on ^C)

// return_value = pixy_command("start", END_OUT_ARGS, &response, END_IN_ARGS);
// printf("START returned %d response %d\n", return_value, response);
} //end local

And call it in the main c++ PanTilt program (the function is called many times):

[...]
while(run_flag) {

  get_frame();      <======= HERE

  // Wait for new blocks to be available //
  while(!pixy_blocks_are_new() && run_flag);
[...]

But problems are :

  • it sometimes grab frame(s) then stops working and returns errors like “invalid command (-152)” or “Undefined error (-7)” for the pixy_command(“cam_getFrame”)
  • it just returns the previous errors without getting frames
  • after get_frame() (and closing the simulation) , Pixy does not react to any colors, I have to disconnect and reconnect the USB to reset Pixy

The only moment the function to grab frame works is just during the few time Pixy initialize itself when I connect it to the USB.

I don’t really understand why, any help would be appreciated

Marino

The idea then for Python is to copy the function “get_frame()” I wrote in the interpreter.cpp, and add this function in the pixy.i before building the Python panTilt program.

Yes, I succeed in doing this last step, I can call gate_frame() in python, but the function doesn’t work as I explained above : logically it has to work first in c++ before working on python …

In the python interpreter (after initializing Pixy) :

>>> get_frame()
STOP returned 0 response 0
getFrame returned -7 response 0
returned w 0 h 0 npix 0
-7

if I call it a second time :

>>> get_frame()
STOP returned -152 response 0
getFrame returned -152 response 0
returned w 0 h 0 npix 0
-152

Those results are what I get on the c++ program too.

Thanks for your help ! :slight_smile:

Hi Marino,
I would try this (pseudo code)

send “stop” command
while(1)
get_frames();

send “run” command // not completely necessary

In other words, don’t send stop multiple times – you are sending “stop” one time per “cam_getFrame”.

Hope this helps!

Edward

Hi Edward,

Thank you for your answer ! :slight_smile:

*1.*Actually, when the “stop” command is before the loop, without getting blocks and moving, and without the “run” command as you advised, it returns frames in an infinite loop :slight_smile: :

+ Pixy Tracking Demo Started +
STOP returned 0 response 0

getFrame returned 0 response 0
returned w 40 h 40 npix 1600
0a 09 0a 09 0b 0a 0b 09
09 07 09 09 09 08 09 09
09 09 09 09 09 08 09 09
08 08 08 07 08 06 08 08
08 08 08 07 08 08 08 08
08 07 07 07 08 07 08 07
08 07 08 07 07 07 07 08
08 07 07 07 08 07 07 07

getFrame returned 0 response 0
returned w 40 h 40 npix 1600
09 08 0a 09 0a 0a 0b 0b
09 08 09 09 0a 09 09 0a
08 09 09 0a 09 09 09 09
08 08 09 07 08 07 08 08
08 08 08 08 09 08 09 08
07 07 08 07 08 06 08 08
08 08 08 07 09 08 08 07
09 07 07 06 08 07 08 07

...

*2.*Then, when I try to add the tracking code with the get_frame() function inside the while loop, it doesn’t work anymore :

_(pseudo code)_:
command "stop"
while : 
  get_frame()
  tracking codes    // get_blocks, move motors, ...

It freezes at the frame 0 :

+ Pixy Tracking Demo Started +
STOP returned 0 response 0

frame 0:

getFrame returned 0 response 0
returned w 40 h 40 npix 1600
1a 17 26 34 3a 23 1a 10
12 1b 2c 30 2f 13 13 0c
1b 1d 2b 2e 37 18 16 0f
16 24 2f 24 24 0f 10 0d
1d 25 34 2b 24 12 12 0e
1b 2b 2e 1b 18 0e 0f 0e
20 2b 32 25 1c 10 12 0e
24 2d 2f 13 12 0c 0e 0e
sig: 1 x: 233 y: 194 width:  27 height:  10
sig: 1 x: 178 y: 192 width:  11 height:   3
sig: 1 x: 118 y:  49 width:   5 height:   7

^C

*3.*Using the command “run” makes Pixy return frames (before loop) and track after (in loop):

_(pseudo codes)_:
command "stop"
get_frame()        // as many times as I want
command "run"      // without "run" the tracking codes do not execute, it freezes
while : 
    tracking codes

This code prooves that grab_frame() and tracking() could work together then, doesn’it ?

*4.*I even tried to call “stop” with “run” many times … Sorry you advised not to but I was curious, and it seems to work:

_(pseudo codes)_:
command "stop"    
get_frame()       
command "run"
command "stop"
get_frame()
command "run" 
while : 
    tracking codes

:thinking:

*5.*But my objective is still to grab frame at any times (e.g. each 50 frames) while tracking. And when the codes look like :

_(pseudo codes)_:
command "stop"    
get_frame()       
command "run"
while : 
    command "stop"
    get_frame()
    command "run"
    tracking codes

the first grab_frame() works but not the inside while one, it returns the same errors ([-152] invalid command and [-7] undefined error :

  getFrame returned -7 response 0
  returned w 40 h 40 npix 1600
  Undefined error: [-7]

Plus, I don’t understand why the get_frame() works fine and sometimes it stops working when I execute the program a 2nd time… The code has to be reexecuted many times until it works again by disconnecting/reconnecting Pixy USB.

(Sorry for the long story :smiley:)

Marino

Hello Marino,
There are some runtime restrictions when it comes to getting raw frames and/or block data and/or line tracking data.

In general, you need to be running the color_connected_components program to get block data. And you need to be running the line_tracking program to get line data.

When you issue a “stop” command, the program that is currently running will stop. When the program is stopped, you can grab raw frames and not interfere with the program (which is also grabbing frames). If you want block data you need to run the color_connected_components program. Normally, this only requires the “run” command, assuming you were already running color_connected_components when you issued the “stop” command.

If you issue a “stop” command and then try to get block data, it won’t work because the color_connected_components program (or any program) is not running.

Hope this helps.

Edward