void frame_diff (cc3_frame_diff_pkt_t * pkt) { uint8_t old_coi = cc3_g_pixbuf_frame.coi; cc3_pixbuf_frame_set_coi (pkt->coi); cc3_image_t img; img.channels = 1; img.width = cc3_g_pixbuf_frame.width; img.height = 1; // 1 row for scanline processing img.pix = (void*)tempBuffer; if (cc3_frame_diff_scanline_start (pkt) != 0) { while (cc3_pixbuf_read_rows (img.pix, 1)) { cc3_frame_diff_scanline (&img, pkt); } cc3_frame_diff_scanline_finish (pkt); } else printf ("frame diff start error\r"); cc3_pixbuf_frame_set_coi (old_coi); }
/** * Get the pixel located at x, y in the image data structure. Just stores * the values at that pixel into the passed-in pixel data struct. */ int get_pixel(lua_State *_l) { cc3_pixel_t *pixel = checkpixel(_l, 1); int x = luaL_checknumber(_l, 2); int y = luaL_checknumber(_l, 3); // verify the x, y values luaL_argcheck(_l, x < cc3_g_pixbuf_frame.width, 2, "x is outside the bounds of the image."); luaL_argcheck(_l, y < cc3_g_pixbuf_frame.height, 3, "y is outside the bounds of the image"); // Only rewind the frame if we are accessing data behind current point in FIFO if(g_img_prev_y<y || g_img_prev_y==-1) { cc3_pixbuf_rewind(); g_img_prev_y=-1; } // only load a new row if we need to int idy = g_img_prev_y; while( idy<y) { cc3_pixbuf_read_rows(g_img.pix, 1); idy++; } cc3_get_pixel(&g_img, x, 0, pixel); // update position in global image g_img_prev_y=idy; g_img_prev_x=x; return 0; }
/** * Function to capture a ppm */ void capture_ppm(FILE *f) { uint32_t x, y; uint32_t size_x, size_y; uint32_t time, time2; int write_time; cc3_pixbuf_load (); uint8_t *row = cc3_malloc_rows(1); size_x = cc3_g_pixbuf_frame.width; size_y = cc3_g_pixbuf_frame.height; fprintf(f,"P6\n%d %d\n255\n",size_x,size_y ); time = cc3_timer_get_current_ms(); for (y = 0; y < size_y; y++) { cc3_pixbuf_read_rows(row, 1); for (x = 0; x < size_x * 3U; x++) { uint8_t p = row[x]; if (fputc(p, f) == EOF) { perror("fputc failed"); } } fprintf(stderr, "."); fflush(stderr); } time2 = cc3_timer_get_current_ms(); write_time = time2 - time; free(row); }
void simple_track_color(cc3_track_pkt_t * t_pkt) { cc3_image_t img; img.channels = 3; img.width = cc3_g_pixbuf_frame.width; img.height = 1; // image will hold just 1 row for scanline processing img.pix = cc3_malloc_rows (1); if (img.pix == NULL) { return; } cc3_pixbuf_load (); if (cc3_track_color_scanline_start (t_pkt) != 0) { while (cc3_pixbuf_read_rows (img.pix, 1)) { // This does the HSV conversion // cc3_rgb2hsv_row(img.pix,img.width); cc3_track_color_scanline (&img, t_pkt); } } cc3_track_color_scanline_finish (t_pkt); free (img.pix); return; }
/** * Wrapper function for cc3_pixbuf_read_rows. After double-checking the * lua arguments, just call the function and stick the return value on * the lua stack. */ int pixbuf_read_rows(lua_State *_l) { int rv; cc3_image_t *img = checkimage(_l); int num_rows = luaL_checkinteger(_l, 2); luaL_argcheck(_l, num_rows > 0 && num_rows <= img->height, 2, "Num Rows cannot be bigger than img:"); rv = cc3_pixbuf_read_rows(img->pix, num_rows); lua_pushinteger(_l, rv); return 1; }
/** * Sends the picture currently in the pixbuf over serial */ int send_picture_msg(lua_State *_l) { uint32_t x, y; uint32_t size_x, size_y; // only send if we're in debug mode if (debug_on) { init_packet(); // First the header // first the ID we have to put it in two bytes // big endian put_slip_char(get_msg_id_most_repr(PPM_MSG_ID)); put_slip_char(get_msg_id_least_repr(PPM_MSG_ID)); // now the param count. 1 bytes put_slip_char(1); cc3_pixbuf_rewind(); // just in case uint8_t *row = cc3_malloc_rows(1); // now parameters size_x = cc3_g_pixbuf_frame.width; size_y = cc3_g_pixbuf_frame.height; char* head = malloc(20); sprintf(head,"P6\n%d %d\n255\n",size_x,size_y ); uint32_t size = strlen(head)+size_x*size_y*3; // size is 3 bytes, so we first get // rid of most representative byte put_slip_char(get_size_most_repr(size)); put_slip_char(get_size_middle_repr(size)); put_slip_char(get_size_least_repr(size)); put_slip_string(head); free(head); bool led_on = false; for (y = 0; y < size_y; y++) { cc3_pixbuf_read_rows(row, 1); cc3_led_set_state(0, led_on=!led_on); for (x = 0; x < size_x * 3U; x++) { /* Sleep to prevent byte-loss. Seems a bit extreme, but I saw problems with even 1000 and 500 as intervals. */ if (x % 100 == 0) { cc3_timer_wait_ms (5); } put_slip_char(row[x]); } } cc3_led_set_state(0, false); free(row); finish_packet(); } return 0; }
char* get_PPM_char(ParamBodyByteStream* bstream) { PPMData* ppm = (PPMData*)bstream->state.blob; uint8_t* next_c = NULL; if ( bstream->state.idx < 15 ) { next_c = (uint8_t*)&ppm->header[bstream->state.idx]; bstream->state.idx++; } else if ( bstream->state.idx == 15 ) { cc3_pixbuf_read_rows(ppm->row, 1); bstream->state.idx++; // y=0, x=0 for the regular loop next_c = &ppm->row[ppm->x++]; } else if ( ppm->x < ppm->size_x * 3U ) { next_c = &ppm->row[ppm->x++]; } else if ( ppm->y < ppm->size_y-1 ) { // size_y-1 because we come here AFTER we read the row (size_x) cc3_pixbuf_read_rows(ppm->row, 1); ppm->y++; ppm->x = 0; next_c = &ppm->row[ppm->x++]; } return (char*)next_c; }
void get_mean (cc3_color_info_pkt_t * s_pkt) { cc3_image_t img; img.channels = 1; img.width = cc3_g_pixbuf_frame.width; img.height = 1; img.pix = (void*)tempBuffer; if (cc3_color_info_scanline_start (s_pkt) != 0) { while (cc3_pixbuf_read_rows (img.pix, 1)) { cc3_color_info_scanline (&img, s_pkt); } cc3_color_info_scanline_finish (s_pkt); } }
void simple_get_mean (cc3_color_info_pkt_t * s_pkt) { cc3_image_t img; img.channels = 3; img.width = cc3_g_pixbuf_frame.width; img.height = 1; // image will hold just 1 row for scanline processing img.pix = malloc (3 * img.width); cc3_pixbuf_load (); if (cc3_color_info_scanline_start (s_pkt) != 0) { while (cc3_pixbuf_read_rows (img.pix, 1)) { cc3_color_info_scanline (&img, s_pkt); } cc3_color_info_scanline_finish (s_pkt); } free (img.pix); }
void get_histogram (cc3_histogram_pkt_t * h_pkt) { cc3_image_t img; img.channels = 3; img.width = cc3_g_pixbuf_frame.width; img.height = 1; img.pix = (void*)tempBuffer; if (cc3_histogram_scanline_start (h_pkt) != 0) { while (cc3_pixbuf_read_rows (img.pix, 1)) { // This does the HSV conversion // cc3_rgb2hsv_row(img.pix,img.width); cc3_histogram_scanline (&img, h_pkt); } } cc3_histogram_scanline_finish (h_pkt); }
/** * Function to save the image currently in the pixbuf onto the MMC card * using the passed filename. */ int save_picture(lua_State *_l) { char fname[20]; uint32_t x, y; uint32_t size_x, size_y; FILE *f; // make sure filename is legal FAT16 const char *name = luaL_checkstring(_l, 1); /* get the parameter */ luaL_argcheck(_l, is_format_8_3(name), 1, "Illegal Filename! Filename must be FAT16 <8,3> format."); strcpy(fname,"c:/"); strcat(fname,name); f = fopen(fname, "w"); cc3_pixbuf_rewind(); // just in case uint8_t *row = cc3_malloc_rows(1); size_x = cc3_g_pixbuf_frame.width; size_y = cc3_g_pixbuf_frame.height; char* head = malloc(20); sprintf(head,"P6\n%d %d\n255\n",size_x,size_y ); fprintf(f,"P6\n%d %d\n255\n",size_x,size_y ); free(head); for (y = 0; y < size_y; y++) { cc3_pixbuf_read_rows(row, 1); for (x = 0; x < size_x * 3U; x++) { fputc(row[x], f); } } free(row); fclose(f); return 0; }
/** * Get and send information about the specified point in the pixbuf. * Look at the 5x5 rectangle within two pixels of x, y, and send back: * R, G, B at (x, y) * average R, G, B */ void send_image_info(int x, int y) { int BUFFER = 2; cc3_image_t img; cc3_pixel_t pixel; image_info_pkt_t* info_pkt = malloc(sizeof(image_info_pkt_t)); info_pkt->x = x; info_pkt->y = y; // make sure we got legal values if (x > cc3_g_pixbuf_frame.width || y > cc3_g_pixbuf_frame.height) { send_debug_msg("(%d, %d) is outside the bounds of the pixbuf.", x, y); return; } info_pkt->x = x; info_pkt->y = y; info_pkt->avg_r = info_pkt->avg_g = info_pkt->avg_b = 0; // get mins and maxes, in case we're near the edge of an image int y_min = y - BUFFER; if (y_min < 0) { y_min = 0; } int y_max = y + BUFFER; if (y_max > cc3_g_pixbuf_frame.height) { y_max = cc3_g_pixbuf_frame.height; } int x_min = x - BUFFER; if (x_min < 0) { x_min = 0; } int x_max = x + BUFFER; if (x_max > cc3_g_pixbuf_frame.width) { x_max = cc3_g_pixbuf_frame.width; } // get to the min row first cc3_pixbuf_rewind(); img.pix = cc3_malloc_rows(1); int idx = 0; while (idx < y_min) { cc3_pixbuf_read_rows(img.pix, 1); idx++; } int num_pix = 0; for (; idx < y_max+1; idx++) { cc3_pixbuf_read_rows(img.pix, 1); for (int j = x_min; j < x_max+1; j++) { cc3_get_pixel(&img, j, 0, &pixel); info_pkt->avg_r += pixel.channel[0]; info_pkt->avg_g += pixel.channel[1]; info_pkt->avg_b += pixel.channel[2]; if (idx == y && j == x) { info_pkt->r = pixel.channel[0]; info_pkt->g = pixel.channel[1]; info_pkt->b = pixel.channel[2]; } num_pix++; } } info_pkt->avg_r = info_pkt->avg_r / num_pix; info_pkt->avg_g = info_pkt->avg_g / num_pix; info_pkt->avg_b = info_pkt->avg_b / num_pix; free(img.pix); // free img.pix info_pkt gets freed in send_image_info_msg send_image_info_msg(info_pkt); }
/* simple hello world, showing features and compiling*/ int main (void) { uint32_t start_time, end_time, val; char c; FILE *fp; cc3_image_t img; // init filesystem driver cc3_filesystem_init (); // configure uarts cc3_uart_init (0, CC3_UART_RATE_115200, CC3_UART_MODE_8N1, CC3_UART_BINMODE_TEXT); // Make it so that stdout and stdin are not buffered val = setvbuf (stdout, NULL, _IONBF, 0); val = setvbuf (stdin, NULL, _IONBF, 0); printf( "Calling camera init\n" ); cc3_camera_init (); printf( "Camera init done\n" ); cc3_camera_set_colorspace (CC3_COLORSPACE_RGB); cc3_camera_set_resolution (CC3_CAMERA_RESOLUTION_LOW); cc3_camera_set_auto_white_balance (true); cc3_camera_set_auto_exposure (true); printf ("Hello World...\n"); cc3_led_set_state (0, false); cc3_led_set_state (1, false); cc3_led_set_state (2, false); // sample wait command in ms cc3_timer_wait_ms (1000); cc3_led_set_state (0, true); // sample showing how to write to the MMC card printf ("Type y to test MMC card, type n if you do not have the card\n"); c = getchar (); if (c == 'y' || c == 'Y') { int result; printf ("\nMMC test...\n"); fp = fopen ("c:/test.txt", "w"); if (fp == NULL) { perror ("fopen failed"); } fprintf (fp, "This will be written to the MMC...\n"); result = fclose (fp); if (result == EOF) { perror ("fclose failed"); } printf ("A string was written to test.txt on the mmc card.\n"); } // sample showing how to read button printf ("push button on camera back to continue\n"); start_time = cc3_timer_get_current_ms (); while (!cc3_button_get_state ()); cc3_led_set_state (1, true); // sample showing how to use timer printf ("It took you %dms to press the button\n", cc3_timer_get_current_ms () - start_time); // setup an image structure cc3_pixbuf_load (); img.channels = 3; img.width = cc3_g_pixbuf_frame.width; img.height = 1; // image will hold just 1 row for scanline processing img.pix = cc3_malloc_rows (1); printf ("Now we will use image data...\n"); val = 0; /* * Track the brightest red spot on the image */ while (1) { int y; uint16_t my_x, my_y; uint8_t max_red; cc3_pixel_t my_pix; if (val & 0x1) cc3_led_set_state (0, true); else cc3_led_set_state (0, false); if (val & 0x2) cc3_led_set_state (1, true); else cc3_led_set_state (1, false); if (val & 0x3) cc3_led_set_state (2, true); else cc3_led_set_state (2, false); if (val & 0x4) cc3_led_set_state (3, true); else cc3_led_set_state (3, false); val++; // This tells the camera to grab a new frame into the fifo and reset // any internal location information. cc3_pixbuf_frame_set_coi(CC3_CHANNEL_ALL); cc3_pixbuf_load (); // red search! // *** slow method for red search start_time = cc3_timer_get_current_ms(); max_red = 0; my_x = 0; my_y = 0; y = 0; while (cc3_pixbuf_read_rows (img.pix, 1)) { // read a row into the image picture memory from the camera for (uint16_t x = 0; x < img.width; x++) { // get a pixel from the img row memory cc3_get_pixel (&img, x, 0, &my_pix); if (my_pix.channel[CC3_CHANNEL_RED] > max_red) { max_red = my_pix.channel[CC3_CHANNEL_RED]; my_x = x; my_y = y; } } y++; } end_time = cc3_timer_get_current_ms(); printf ("Found max red value %d at %d, %d\n", max_red, my_x, my_y); printf (" cc3_get_pixel version took %d ms to complete\n", end_time - start_time); // *** faster method for red search cc3_pixbuf_rewind(); // use exactly the same pixbuf contents start_time = cc3_timer_get_current_ms(); max_red = 0; my_x = 0; my_y = 0; y = 0; while (cc3_pixbuf_read_rows (img.pix, 1)) { // read a row into the image picture memory from the camera for (uint16_t x = 0; x < img.width * 3; x+=3) { uint8_t red = ((uint8_t *) img.pix)[x + CC3_CHANNEL_RED]; if (red > max_red) { max_red = red; my_x = x; my_y = y; } } y++; } my_x /= 3; // correct channel offset end_time = cc3_timer_get_current_ms(); printf ("Found max red value %d at %d, %d\n", max_red, my_x, my_y); printf (" faster version took %d ms to complete\n", end_time - start_time); // *** even faster method for red search cc3_pixbuf_rewind(); // use exactly the same pixbuf contents cc3_pixbuf_frame_set_coi(CC3_CHANNEL_RED); start_time = cc3_timer_get_current_ms(); max_red = 0; my_x = 0; my_y = 0; y = 0; while (cc3_pixbuf_read_rows (img.pix, 1)) { // read a row into the image picture memory from the camera for (uint16_t x = 0; x < img.width; x++) { uint8_t red = ((uint8_t *) img.pix)[x]; if (red > max_red) { max_red = red; my_x = x; my_y = y; } } y++; } end_time = cc3_timer_get_current_ms(); printf ("Found max red value %d at %d, %d\n", max_red, my_x, my_y); printf (" even faster version took %d ms to complete\n", end_time - start_time); printf("\n"); // sample non-blocking serial routine if (!cc3_uart_has_data (0)) break; } free (img.pix); // don't forget to free! printf ("You pressed %c to escape\n", fgetc (stdin)); // stdio actually works... printf ("Type in a number followed by return to test scanf: "); scanf ("%d", &val); printf ("You typed %d\n", val); printf ("Good work, now try something on your own...\n"); while (1); return 0; }