00001 /*!@file saliency.C simple Maemo saliency app to run on the Nokia N810 */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 00033 #include <string.h> 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <cerrno> 00037 #include <fcntl.h> 00038 #include <sys/ioctl.h> 00039 #include <sys/mman.h> 00040 #include <sys/stat.h> 00041 #include <unistd.h> 00042 #include <sys/time.h> 00043 00044 #include <linux/videodev.h> // needed for some type definitions?? 00045 #include <linux/videodev2.h> 00046 00047 #include <linux/fb.h> 00048 #include <asm-arm/arch-omap/omapfb.h> 00049 #include <X11/Xlib.h> 00050 #include <X11/Xutil.h> 00051 00052 #define INT_IS_32_BITS 1 00053 #define LONG_IS_32_BITS 1 00054 #include "Envision/env_config.h" 00055 #include "Envision/env_alloc.h" 00056 #include "Envision/env_c_math_ops.h" 00057 #include "Envision/env_stdio_interface.h" 00058 #include "Envision/env_image.h" 00059 #include "Envision/env_image_ops.h" 00060 #include "Envision/env_log.h" 00061 #include "Envision/env_visual_cortex.h" 00062 #include "Envision/env_params.h" 00063 00064 #include <pthread.h> 00065 00066 #include "Envision/env_alloc.c" 00067 #include "Envision/env_c_math_ops.c" 00068 #include "Envision/env_stdio_interface.c" 00069 #include "Envision/env_image.c" 00070 #include "Envision/env_image_ops.c" 00071 #include "Envision/env_log.c" 00072 #include "Envision/env_visual_cortex.c" 00073 #include "Envision/env_params.c" 00074 #include "Envision/env_channel.c" 00075 #include "Envision/env_math.c" 00076 #include "Envision/env_motion_channel.c" 00077 #include "Envision/env_pyr.c" 00078 00079 #include "Image/font6x10.h" 00080 #define FONTW 6 00081 #define FONTH 10 00082 00083 #include <libosso.h> 00084 00085 #define LINFO printf("\n")&&printf 00086 #define LFATAL printf("\n")&&printf 00087 #define PLFATAL printf("\n")&&printf 00088 #define PLERROR printf("\n")&&printf 00089 00090 // grab: format is RGB565 00091 #define GRABDEV "/dev/video0" 00092 #define GRABNBUF 1 00093 #define GRABW 320 00094 #define GRABH 240 00095 00096 // display: format is RGB565 00097 #define HRES 800 00098 #define VRES 480 00099 #define BPP 16 00100 00101 #define BCOL intg16(0x3FFF) 00102 #define TCOL intg16(0x3F3F) 00103 #define TCOL2 intg16(0xFF3F) 00104 #define SCOL intg16(0x3F30) 00105 00106 #define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 00107 #define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 00108 00109 // Some of the code here is heavily inspired from this message: 00110 // http://lists.maemo.org/pipermail/maemo-developers/2008-February/050357.html 00111 00112 00113 // ###################################################################### 00114 // Thunk to convert from env_size_t to size_t 00115 static void* malloc_thunk(env_size_t n) 00116 { return malloc(n); } 00117 00118 // ###################################################################### 00119 void draw_rect(intg16 *buf, const int x, const int y, const int w, const int h, const intg16 col) 00120 { 00121 intg16 *b = buf + x + y * HRES; 00122 00123 const int offy = (h-1) * HRES; 00124 for (int xx = 0; xx < w; ++xx) { b[xx] = col; b[xx + offy] = col; } 00125 00126 const int offx = w-1; 00127 for (int yy = 0; yy < h * HRES; yy += HRES) { b[yy] = col; b[yy + offx] = col; } 00128 } 00129 00130 // ###################################################################### 00131 void draw_filled_rect(intg16 *buf, const int x, const int y, const int w, const int h, const intg16 col) 00132 { 00133 intg16 *b = buf + x + y * HRES; 00134 00135 for (int yy = 0; yy < h; ++yy) { 00136 for (int xx = 0; xx < w; ++xx) *b++ = col; 00137 b += HRES - w; 00138 } 00139 } 00140 00141 // ###################################################################### 00142 void write_text(intg16 *buf, const char *txt, int x0, int y0, const intg16 col) 00143 { 00144 const int len = int(strlen(txt)); 00145 00146 // auto centering? 00147 if (x0 == -1) x0 = (HRES - FONTW * len) / 2; 00148 00149 for (int i = 0; i < len; i ++) 00150 { 00151 const unsigned char *ptr = ((const unsigned char *)font6x10) + (txt[i] - 32) * FONTW * FONTH; 00152 00153 for (int y = 0; y < FONTH; y ++) 00154 for (int x = 0; x < FONTW; x ++) 00155 if (!ptr[y * FONTW + x]) buf[x0 + x + HRES * (y0 + y)] = col; else buf[x0 + x + HRES * (y0 + y)] = 0; 00156 x0 += FONTW; 00157 } 00158 } 00159 00160 // ###################################################################### 00161 void draw_map(intg16 *buf, const env_image *img, const int xoff, const int yoff, const env_size_t scale) 00162 { 00163 intg16 *d = buf + xoff + yoff * HRES;; 00164 intg32 *s = img->pixels; 00165 00166 const env_size_t w = img->dims.w, h = img->dims.h; 00167 const env_size_t ws = w * scale; 00168 00169 for (env_size_t jj = 0; jj < h; ++jj) { 00170 const intg16 *dd = d; 00171 for (env_size_t ii = 0; ii < w; ++ii) { 00172 const intg16 val = intg16( (*s++) >> 3 ); 00173 for (env_size_t k = 0; k < scale; ++k) *d++ = val; 00174 } 00175 d += HRES - ws; 00176 for (env_size_t k = 1; k < scale; ++k) { memcpy(d, dd, ws * 2); d += HRES; } 00177 } 00178 draw_rect(buf, xoff, yoff, scale * w, scale * h, BCOL); 00179 } 00180 00181 // ###################################################################### 00182 void print_help(intg16 *buf, const bool doit) { 00183 draw_filled_rect(buf, 0, 450, 800, 30, intg16(0)); // clear any old help message 00184 if (doit) { 00185 write_text(buf, "saliency - Copyright (c) 2009 by Laurent Itti and the iLab team - See http://iLab.usc.edu for more info about visual saliency", -1, 450, TCOL2); 00186 write_text(buf, "This program analyzes the input video to determine which point is most likely to attract human visual attention and gaze", -1, 460, TCOL2); 00187 write_text(buf, "Press <SPACE> for more info. Press <ESC> or square key at center of cursor pad to exit application", -1, 470, TCOL2); 00188 } 00189 } 00190 00191 // ###################################################################### 00192 void print_help2(intg16 *buf, const bool doit) { 00193 draw_filled_rect(buf, 0, 300, 800, 180, intg16(0)); // clear any old help message 00194 if (doit) { 00195 //---------------0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00196 write_text(buf, "saliency - Copyright (c) 2009 by Laurent Itti and the iLab team - See http://iLab.usc.edu for more info about visual saliency", -1, 310, TCOL2); 00197 write_text(buf, "This program analyzes the input video to determine which point is most likely to attract human visual attention and gaze.", -1, 320, TCOL2); 00198 //write_text(buf, "", -1, 330, TCOL2); 00199 write_text(buf, "In this biologically-inspired system (Itti, Koch & Niebur, IEEE Transactions on Pattern Analysis and Machine Intelligence, 1998),", -1, 340, TCOL2); 00200 write_text(buf, "each input image is decomposed into a set of multiscale neural ``feature maps,'' which extract local spatial discontinuities in the", -1, 350, TCOL2); 00201 write_text(buf, "modalities of color, intensity, orientation, flicker and motion. Each feature map is endowed with non-linear spatially competitive", -1, 360, TCOL2); 00202 write_text(buf, "dynamics, so that the response of a neuron at a given location in a map is modulated by the activity of neighboring neurons. Such", -1, 370, TCOL2); 00203 write_text(buf, "contextual modulation, inspired by recent neurobiological findings, enhances salient targets from cluttered backgrounds. All feature", -1, 380, TCOL2); 00204 write_text(buf, "maps are then combined into a unique scalar saliency map which encodes for the salience of a location in the scene, irrespectively", -1, 390, TCOL2); 00205 write_text(buf, "of the particular feature which detected this location as conspicuous. A winner-take-all neural network then detects the point of", -1, 400, TCOL2); 00206 write_text(buf, "highest salience in the map at any given time, and draws the focus of attention towards this location (small cyan square marker).", -1, 410, TCOL2); 00207 write_text(buf, "", -1, 420, TCOL2); 00208 write_text(buf, "This Maemo program uses a fast integer-only saliency algorithm implemented by Robert J. Peters, see Peters & Itti, ACM Transactions", -1, 430, TCOL2); 00209 write_text(buf, "on Applied Perception, 2008.", -1, 440, TCOL2); 00210 //write_text(buf, "", -1, 450, TCOL2); 00211 //write_text(buf, "", -1, 460, TCOL2); 00212 write_text(buf, "Press <SPACE> to switch back to full display mode.", -1, 470, TCOL2); 00213 } 00214 } 00215 00216 /**************************************************************************************************************/ 00217 int main(int argc, char **argv) 00218 { 00219 // initialize OSSO, we will need it to prevent the screen from dimming: 00220 osso_context_t *osso = osso_initialize("saliency", "1.00", true, 0); 00221 if (osso == NULL) LFATAL("Cannot initialize OSSO"); 00222 00223 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00224 // setup V4L2 mmap'ed video grabbing: 00225 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00226 int gfd = open(GRABDEV, O_RDWR); 00227 if (gfd == -1) PLFATAL("Cannot open V4L2 device %s", GRABDEV); 00228 00229 // set grab format: 00230 struct v4l2_format fmt; 00231 memset(&fmt, 0, sizeof(fmt)); 00232 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00233 fmt.fmt.pix.width = GRABW; 00234 fmt.fmt.pix.height = GRABH; 00235 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 00236 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; 00237 00238 if (ioctl(gfd, VIDIOC_S_FMT, &fmt) == -1) PLFATAL("Cannot set requested video mode/resolution"); 00239 00240 // prepare mmap interface: 00241 const int nbuf = GRABNBUF; 00242 struct v4l2_requestbuffers req; 00243 memset(&req, 0, sizeof(req)); 00244 req.count = nbuf; 00245 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00246 req.memory = V4L2_MEMORY_MMAP; 00247 00248 if (ioctl(gfd, VIDIOC_REQBUFS, &req) == -1) PLFATAL("Cannot allocate %d mmap'ed video frame buffers", nbuf); 00249 if (int(req.count) != nbuf) LFATAL("Hardware only supports %d video buffers (vs. %d requested)", req.count, nbuf); 00250 00251 byte **itsMmapBuf = new byte*[req.count]; 00252 int *itsMmapBufSize = new int[req.count]; 00253 00254 for (uint i = 0; i < req.count; ++i) { 00255 struct v4l2_buffer buf; 00256 memset(&buf, 0, sizeof(buf)); 00257 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00258 buf.memory = V4L2_MEMORY_MMAP; 00259 buf.index = i; 00260 if (ioctl(gfd, VIDIOC_QUERYBUF, &buf) == -1) PLFATAL("Could not query for MMAP buffer"); 00261 00262 itsMmapBufSize[i] = buf.length; 00263 itsMmapBuf[i] = static_cast<byte*>(mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, gfd, buf.m.offset)); 00264 if (itsMmapBuf[i] == MAP_FAILED) PLFATAL("Error MMAP'ing video buffer number %d", i); 00265 } 00266 00267 // get ready to grab frames, starting with buffer/frame 0: 00268 int itsCurrentFrame = 0; 00269 bool *itsGrabbing = new bool[nbuf]; 00270 for (int i = 0; i < nbuf; ++i) itsGrabbing[i] = false; 00271 00272 // start streaming by putting grab requests for all our buffers: 00273 struct v4l2_buffer buf; 00274 memset(&buf, 0, sizeof(buf)); 00275 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00276 buf.memory = V4L2_MEMORY_MMAP; 00277 00278 for (int i = 0; i < nbuf; ++i) 00279 if (itsGrabbing[i] == true) { 00280 buf.index = i; 00281 if (ioctl(gfd, VIDIOC_DQBUF, &buf) == -1) PLFATAL("VIDIOC_DQBUF (frame %d)", i); 00282 itsGrabbing[i] = false; 00283 } 00284 00285 for (int i = 0; i < nbuf; ++i) { 00286 // now start a fresh grab for buffer i: 00287 buf.index = i; 00288 if (ioctl(gfd, VIDIOC_QBUF, &buf)) PLFATAL("VIDIOC_QBUF (frame %d)", i); 00289 itsGrabbing[i] = true; 00290 } 00291 00292 // tell grabber to stream: 00293 enum v4l2_buf_type typ = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00294 if (ioctl(gfd, VIDIOC_STREAMON, &typ)) PLFATAL("VIDIOC_STREAMON"); 00295 00296 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00297 // setup display via direct OMAPFB access: 00298 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00299 00300 // setup display, screen and window 00301 Display *display = XOpenDisplay(getenv ("DISPLAY")); 00302 if (display == NULL) LFATAL("cannot open X display"); 00303 int screen_num = DefaultScreen(display); 00304 00305 Window win = XCreateSimpleWindow(display, RootWindow(display, screen_num), 0, 0, HRES, VRES, 0, 00306 WhitePixel(display, screen_num), BlackPixel (display, screen_num)); 00307 XMapWindow(display, win); 00308 XSelectInput(display, win, ExposureMask | KeyPressMask); 00309 XFlush(display); 00310 00311 XEvent xev; 00312 XWindowEvent(display, win, ExposureMask, &xev); 00313 00314 // bring window to fullscreen 00315 xev.xclient.type = ClientMessage; 00316 xev.xclient.serial = 0; 00317 xev.xclient.send_event = True; 00318 xev.xclient.message_type = XInternAtom (display, "_NET_WM_STATE", False); 00319 xev.xclient.window = win; 00320 xev.xclient.format = 32; 00321 xev.xclient.data.l[0] = 1; 00322 xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False); 00323 xev.xclient.data.l[2] = 0; 00324 xev.xclient.data.l[3] = 0; 00325 xev.xclient.data.l[4] = 0; 00326 00327 if (!XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev)) 00328 LFATAL("cannot bring X window to fullscreen"); 00329 XSync(display, False); 00330 00331 // open framebuffer device 00332 int fbfd = open("/dev/fb0", O_RDWR); 00333 if (!fbfd) LFATAL("cannot open framebuffer device"); 00334 00335 size_t ssize = HRES * BPP / 8 * VRES; 00336 00337 // map framebuffer 00338 char* fbp = (char*)mmap(0, ssize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); 00339 if ((int)fbp == -1) LFATAL("failed to memory map framebuffer"); 00340 intg16 *fbp16 = (intg16 *)fbp; 00341 00342 // setup fullscreen update info struct 00343 struct omapfb_update_window update; 00344 00345 // copy full screen from fb to lcd video ram 00346 update.x = 0; 00347 update.y = 0; 00348 update.width = HRES; 00349 update.height = VRES; 00350 00351 // request native pixel format, tearsync and vsync 00352 update.format = OMAPFB_COLOR_RGB565 | OMAPFB_FORMAT_FLAG_TEARSYNC; // | OMAPFB_FORMAT_FLAG_FORCE_VSYNC; 00353 00354 00355 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00356 // Setup Envision: 00357 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00358 00359 // Instantiate our various ModelComponents: 00360 struct env_params envp; 00361 env_params_set_defaults(&envp); 00362 00363 envp.maxnorm_type = ENV_VCXNORM_MAXNORM; 00364 envp.scale_bits = 16; 00365 env_allocation_init(&malloc_thunk, &free); 00366 00367 struct env_visual_cortex ivc; 00368 env_visual_cortex_init(&ivc, &envp); 00369 struct env_dims indims; indims.w = GRABW; indims.h = GRABH; 00370 struct env_rgb_pixel* input = (struct env_rgb_pixel*)env_allocate(GRABW * GRABH * sizeof(struct env_rgb_pixel)); 00371 00372 // initially print help message at bottom: 00373 int helpmode = 30; print_help(fbp16, true); 00374 bool helpmode2 = false; bool refresh = true; 00375 00376 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00377 // Main loop: 00378 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00379 for (int fram = 0; /* */ ; ++fram) 00380 { 00381 //////////////////// grab 00382 intg16* result = (intg16*)(itsMmapBuf[itsCurrentFrame]); 00383 // int siz = itsMmapBufSize[itsCurrentFrame]; 00384 struct v4l2_buffer buf; 00385 memset(&buf, 0, sizeof(buf)); 00386 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00387 buf.memory = V4L2_MEMORY_MMAP; 00388 buf.index = itsCurrentFrame; 00389 00390 // are we already grabbing buffer 'itsCurrentFrame'? otherwise, 00391 // start the grab now: 00392 if (itsGrabbing[itsCurrentFrame] == false) { 00393 if (ioctl(gfd, VIDIOC_QBUF, &buf)) PLFATAL("VIDIOC_QBUF (frame %d)", itsCurrentFrame); 00394 itsGrabbing[itsCurrentFrame] = true; 00395 } 00396 00397 // wait until buffer 'itsCurrentFrame' has been fully captured: 00398 if (ioctl(gfd, VIDIOC_DQBUF, &buf) == -1) PLFATAL("VIDIOC_DQBUF (frame %d)", itsCurrentFrame); 00399 itsGrabbing[itsCurrentFrame] = false; 00400 00401 // get ready for capture of that frame again (for later): 00402 itsGrabbing[itsCurrentFrame] = true; 00403 if (ioctl(gfd, VIDIOC_QBUF, &buf) < 0) PLFATAL("VIDIOC_QBUF (frame %d)", itsCurrentFrame); 00404 00405 // switch to another frame: 00406 ++itsCurrentFrame; 00407 if (itsCurrentFrame >= nbuf) itsCurrentFrame = 0; 00408 00409 ///////////// saliency 00410 00411 // convert image to RGB, rescaling the 5 or 6-bit values to full 8-bit: 00412 unsigned char *in = ((unsigned char *)input) + 2; // point to blue of first pixel 00413 intg16 *data = result; 00414 for (uint ii = 0; ii < GRABW * GRABH; ++ii) { 00415 intg16 x = *data++; 00416 *in-- = ((byte(x)) << 3) & byte(0xF8); // blue 00417 x >>= 3; *in-- = (byte(x)) & byte(0xFC); // green 00418 x >>= 5; *in = (byte(x)) & byte(0xF8); // red 00419 in += 5; // go to blue of next pixel 00420 } 00421 00422 struct timeval real1, real2; 00423 gettimeofday(&real1, /* timezone */ 0); 00424 00425 // process saliency map: 00426 struct env_image ivcout = env_img_initializer; 00427 struct env_image intens = env_img_initializer; 00428 struct env_image color = env_img_initializer; 00429 struct env_image ori = env_img_initializer; 00430 #ifdef ENV_WITH_DYNAMIC_CHANNELS 00431 struct env_image flicker = env_img_initializer; 00432 struct env_image motion = env_img_initializer; 00433 #endif 00434 00435 env_visual_cortex_input(&ivc, &envp, "visualcortex", input, 0, indims, 0, 0, &ivcout, &intens, &color, &ori 00436 #ifdef ENV_WITH_DYNAMIC_CHANNELS 00437 , &flicker, &motion 00438 #endif 00439 ); 00440 00441 env_visual_cortex_rescale_ranges(&ivcout, &intens, &color, &ori 00442 #ifdef ENV_WITH_DYNAMIC_CHANNELS 00443 , &flicker, &motion 00444 #endif 00445 ); 00446 00447 gettimeofday(&real2, /* timezone */ 0); 00448 const double real_secs = (real2.tv_sec - real1.tv_sec) + (real2.tv_usec - real1.tv_usec) / 1000000.0; 00449 00450 if (helpmode2 == false) { 00451 if (helpmode == 0) { 00452 char msg[255]; 00453 sprintf(msg, "frame %06d, %0.2ffps", fram, 1.0 / real_secs); 00454 write_text(fbp16, msg, -1 /*336*/, 464, TCOL); 00455 } else { if (--helpmode == 0) print_help(fbp16, false); } // clear help message 00456 } 00457 00458 //////////////////// render 00459 00460 // "render" whole frame, we scale it up by 25% to 400x300 by duplicating every 4th row & column: 00461 intg16 *bf = fbp16; 00462 intg16 *img = result; 00463 for (uint jj = 0; jj < GRABH/4; ++jj) { 00464 // copy first row twice: 00465 for (uint ii = 0; ii < GRABW/4; ++ii) 00466 { *bf++ = *img; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; } bf+=HRES-400; img-=GRABW; 00467 for (uint ii = 0; ii < GRABW/4; ++ii) 00468 { *bf++ = *img; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; } bf += HRES - 400; 00469 // then the next 3 once: 00470 for (uint ii = 0; ii < GRABW/4; ++ii) 00471 { *bf++ = *img; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; } bf += HRES - 400; 00472 for (uint ii = 0; ii < GRABW/4; ++ii) 00473 { *bf++ = *img; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; } bf += HRES - 400; 00474 for (uint ii = 0; ii < GRABW/4; ++ii) 00475 { *bf++ = *img; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; *bf++ = *img++; } bf += HRES - 400; 00476 } 00477 00478 draw_rect(fbp16, 0, 0, 400, 300, BCOL); 00479 00480 // draw the maps: 00481 draw_map(fbp16, &ivcout, 400, 0, 20); 00482 write_text(fbp16, "saliency map", 800 - 12*6-3, 3, TCOL); 00483 if (helpmode2 == false) { 00484 draw_map(fbp16, &intens, 0, 325, 8); 00485 draw_map(fbp16, &color, GRABW/2, 325, 8); 00486 draw_map(fbp16, &ori, GRABW, 325, 8); 00487 draw_map(fbp16, &flicker, (GRABW*3)/2, 325, 8); 00488 draw_map(fbp16, &motion, GRABW*2, 325, 8); 00489 } 00490 00491 // find most salient point: 00492 intg32 *sm = ivcout.pixels; 00493 env_size_t mx = 0, my = 0; 00494 intg32 mv = *sm; 00495 const env_size_t smw = ivcout.dims.w, smh = ivcout.dims.h; 00496 for (env_size_t j = 0; j < smh; ++j) 00497 for (env_size_t i = 0; i < smw; ++i) 00498 if (*sm > mv) { mv = *sm++; mx = i; my = j; } else ++sm; 00499 draw_filled_rect(fbp16, mx * 20+6, my * 20 + 6, 8, 8, SCOL); 00500 draw_rect(fbp16, mx * 20+5, my * 20 + 5, 10, 10, 0); 00501 draw_filled_rect(fbp16, mx * 20+6 + 400, my * 20 + 6, 8, 8, SCOL); 00502 00503 00504 // display some text labels (only necessary on first frame since we won't erase them): 00505 if (refresh) { 00506 write_text(fbp16, "intensity", 80 - 30, 314, TCOL); 00507 write_text(fbp16, "color", 240 - 15, 314, TCOL); 00508 write_text(fbp16, "orientation", 400 - 33, 314, TCOL); 00509 write_text(fbp16, "flicker", 560 - 18, 314, TCOL); 00510 write_text(fbp16, "motion", 720 - 15, 314, TCOL); 00511 } 00512 00513 env_img_make_empty(&ivcout); 00514 env_img_make_empty(&intens); 00515 env_img_make_empty(&color); 00516 env_img_make_empty(&ori); 00517 env_img_make_empty(&flicker); 00518 env_img_make_empty(&motion); 00519 00520 // check for keypress, abort when the square buttonat middle of cursor is pressed: 00521 XEvent event; refresh = false; 00522 if (XCheckWindowEvent(display, win, KeyPressMask, &event) == True && event.type == KeyPress) { 00523 if (event.xkey.keycode == 0x68 || event.xkey.keycode == 0x9) break; // square or esc 00524 else if (event.xkey.keycode == 0x41) { helpmode2 = !helpmode2; print_help2(fbp16, helpmode2); helpmode = 0; if (helpmode2 == false) refresh = true; } // space 00525 else if (helpmode2 == false) { helpmode = 20; print_help(fbp16, true); } 00526 } 00527 00528 // wait for fb->lcd video ram transfer complete 00529 ioctl(fbfd, OMAPFB_SYNC_GFX); 00530 00531 // wait for vsync 00532 ioctl (fbfd, OMAPFB_VSYNC); 00533 00534 // request transfer of fb-> lcd video ram for whole screen 00535 ioctl (fbfd, OMAPFB_UPDATE_WINDOW, &update); 00536 00537 // prevent display from automatically dimming: 00538 if (fram % 30 == 0) osso_display_blanking_pause(osso); 00539 } 00540 00541 // cleanup 00542 env_deallocate(input); 00543 env_visual_cortex_destroy(&ivc); 00544 env_allocation_cleanup(); 00545 00546 munmap(fbp, ssize); close(fbfd); 00547 00548 typ = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00549 if (ioctl(gfd, VIDIOC_STREAMOFF, &typ)) PLERROR("VIDIOC_STREAMOFF"); 00550 00551 for (int i = 0; i < nbuf; i ++) munmap(itsMmapBuf[i], itsMmapBufSize[i]); 00552 delete [] itsMmapBuf; itsMmapBuf = NULL; 00553 delete [] itsMmapBufSize; itsMmapBufSize = NULL; 00554 close(gfd); 00555 delete [] itsGrabbing; 00556 00557 // cleanup X stuff 00558 XCloseDisplay (display); 00559 00560 osso_deinitialize(osso); 00561 00562 return 0; 00563 }