00001 /* --------------------------------------------------------------------------- 00002 Phission : 00003 Realtime Vision Processing System 00004 00005 Copyright (C) 2003 Philip D.S. Thoren (pthoren@cs.uml.edu) 00006 University of Massachusetts at Lowell, 00007 Laboratory for Artificial Intelligence and Robotics 00008 00009 This file is part of Phission. 00010 00011 ---------------------------------------------------------------------------*/ 00012 #include <EffectsTest.h> 00013 #include <stdio.h> 00014 #include <phission.h> 00015 00016 /* ------------------------------------------------------------------------ */ 00017 int glbl_disable_displays = 0; 00018 int glbl_preload_images = 1; 00019 00020 /* ------------------------------------------------------------------------ */ 00021 int usage() 00022 { 00023 printf("\n\n\tUsage:\n"); 00024 printf("\t\t\t--delay <delay value in microseconds>\tdelay between frame updates\n"); 00025 printf("\t\t\t--fps <fps>\t\tframes per second speed for the displaying of the video.\n"); 00026 printf("\t\t\t--loop <value>\tloop the video <value> times; -1 for infinity\n"); 00027 printf("\t\t\t--help\t\t\tdisplay usage\n"); 00028 printf("\t\t\t--nodisplay\tdisable the allocation, opening or any use of a display.\n"); 00029 printf("\t\t\t--test <value>\tload 'value' number of frames/files/images\n"); 00030 printf("\t\t\t--file <avi_data_file>\t\t\tavi source (required)\n"); 00031 printf("\n\n"); 00032 exit(1); 00033 } 00034 00035 00036 /* ------------------------------------------------------------------------ */ 00037 class phEffectsThread : public phThread 00038 { 00039 private: 00040 phImage *m_input[2]; 00041 uint32_t m_input_count; 00042 00043 float m_alpha; 00044 00045 uint32_t m_output_format; 00046 phImage *m_output; 00047 00048 uint8_t *m_buf; 00049 uint32_t m_buf_size; 00050 00051 protected: 00052 int run(); 00053 int wakeup(); 00054 00055 public: 00056 phEffectsThread( phLiveObject *one, phLiveObject *two, uint32_t output_format ); 00057 ~phEffectsThread(); 00058 00059 int mosaic_images( phImage *one, phImage *two, phImage *out); 00060 int overlay_images( phImage *one, phImage *two, phImage *out ); 00061 00062 phLiveObject *getLiveSourceOutput() { return this->m_output; }; 00063 }; 00064 00065 /* ------------------------------------------------------------------------ */ 00066 phEffectsThread::phEffectsThread( phLiveObject *one, 00067 phLiveObject *two, 00068 uint32_t output_format ) 00069 { 00070 phFUNCTION("phEffectsThread::phEffectsThread") 00071 int locked = 0; 00072 00073 phTHIS_LOOSE_LOCK(locked); 00074 00075 this->setName("phEffectsThread"); 00076 this->m_input[0] = (phImage *)one; 00077 this->m_input[1] = (phImage *)two; 00078 this->m_input_count = 2; 00079 00080 this->m_alpha = 0.00; 00081 00082 this->m_output_format = output_format; 00083 00084 this->m_output = new phImage(); 00085 00086 this->m_buf = NULL; 00087 this->m_buf_size = 0; 00088 00089 phTHIS_LOOSE_UNLOCK(locked); 00090 } 00091 00092 /* ------------------------------------------------------------------------ */ 00093 phEffectsThread::~phEffectsThread() 00094 { 00095 phFree(this->m_buf); 00096 this->m_buf_size = 0; 00097 phDelete(this->m_output); 00098 } 00099 00100 /* ------------------------------------------------------------------------ */ 00101 int phEffectsThread::mosaic_images( phImage *one, phImage *two, phImage *out ) 00102 { 00103 phFUNCTION("phEffectsThread::mosaic_images") 00104 int locked = 0; 00105 uint8_t *ptr[2]; 00106 uint32_t height[2]; 00107 uint32_t width[2]; 00108 uint32_t offset; 00109 uint32_t output_height = 0; 00110 uint32_t output_width = 0; 00111 00112 uint32_t i = 0; 00113 uint32_t j = 0; 00114 00115 uint32_t depth = 0; 00116 00117 if ((one == NULL) || 00118 (two == NULL) || 00119 (one->isNull()) || 00120 (two->isNull())) 00121 { 00122 return phFAIL; 00123 } 00124 00125 phTHIS_LOCK(locked); 00126 00127 /* Convert the input images to one color space */ 00128 rc = one->convert(this->m_output_format); 00129 phPRINT_RC(rc,NULL,"one->convert(%s)", 00130 phImageFormatToString(this->m_output_format)); 00131 00132 rc = two->convert(this->m_output_format); 00133 phPRINT_RC(rc,NULL,"two->convert(%s)", 00134 phImageFormatToString(this->m_output_format)); 00135 00136 /* Make sure our buffer is large enough */ 00137 phDALLOC_RESIZE(this->m_buf, 00138 this->m_buf_size, 00139 one->getSize() + two->getSize(), 00140 uint8_t ); 00141 00142 depth = phImageFormatToDepth(this->m_output_format); 00143 00144 /* Get the pointers to the image only after the conversions */ 00145 ptr[0] = (uint8_t*)one->getImage(); 00146 ptr[1] = (uint8_t*)two->getImage(); 00147 00148 height[0] = one->getHeight(); 00149 height[1] = two->getHeight(); 00150 00151 width[0] = one->getWidth(); 00152 width[1] = two->getWidth(); 00153 00154 output_height = (height[0] > height[1] ? height[0] : height[1]); 00155 output_width = width[0] + width[1]; 00156 00157 offset = 0; 00158 for (j = 0; j < this->m_input_count; j++) 00159 { 00160 for (i = 0; i < height[j]; i++ ) 00161 { 00162 phMemcpy(&(this->m_buf[((i * output_width) + offset) * depth]), 00163 &(ptr[j][i * width[j] * depth]), 00164 width[j] * depth); 00165 } 00166 offset += width[j]; 00167 } 00168 00169 rc = out->setImage(output_width, 00170 output_height, 00171 this->m_output_format, 00172 this->m_buf_size, 00173 this->m_buf); 00174 phCHECK_RC(rc,NULL,"out->setImage"); 00175 00176 phTHIS_UNLOCK(locked); 00177 00178 return phSUCCESS; 00179 error: 00180 00181 phTHIS_ERROR_UNLOCK(locked); 00182 00183 return phFAIL; 00184 } 00185 00186 /* ------------------------------------------------------------------------ */ 00187 int phEffectsThread::overlay_images( phImage *one, phImage *two, phImage *out ) 00188 { 00189 phFUNCTION("phEffectsThread::mosaic_images") 00190 int locked = 0; 00191 00192 float alpha = this->m_alpha; 00193 float alphainv = 1.0 - alpha; 00194 00195 float tmp = 0; 00196 uint8_t *outptr = NULL; 00197 uint8_t *ptr[2]; 00198 uint32_t height[2]; 00199 uint32_t width[2]; 00200 uint32_t offset; 00201 uint32_t output_height = 0; 00202 uint32_t output_width = 0; 00203 00204 uint32_t i = 0; 00205 uint32_t j = 0; 00206 00207 uint32_t depth = 0; 00208 uint32_t limit = 0; 00209 00210 if ((one == NULL) || 00211 (two == NULL) || 00212 (one->isNull()) || 00213 (two->isNull())) 00214 { 00215 return phFAIL; 00216 } 00217 00218 phTHIS_LOCK(locked); 00219 00220 /* Convert the input images to one color space */ 00221 rc = one->convert(this->m_output_format); 00222 phPRINT_RC(rc,NULL,"one->convert(%s)", 00223 phImageFormatToString(this->m_output_format)); 00224 00225 rc = two->convert(this->m_output_format); 00226 phPRINT_RC(rc,NULL,"two->convert(%s)", 00227 phImageFormatToString(this->m_output_format)); 00228 00229 rc = two->resize(one->getWidth(),one->getHeight()); 00230 phPRINT_RC(rc,NULL,"two->resize"); 00231 00232 /* Make sure our buffer is large enough */ 00233 phDALLOC_RESIZE(this->m_buf, 00234 this->m_buf_size, 00235 one->getSize(), 00236 uint8_t ); 00237 00238 depth = phImageFormatToDepth(this->m_output_format); 00239 00240 /* Get the pointers to the image only after the conversions */ 00241 ptr[0] = (uint8_t*)one->getImage(); 00242 ptr[1] = (uint8_t*)two->getImage(); 00243 00244 height[0] = one->getHeight(); 00245 height[1] = two->getHeight(); 00246 00247 width[0] = one->getWidth(); 00248 width[1] = two->getWidth(); 00249 00250 output_width = one->getWidth(); 00251 output_height = one->getHeight(); 00252 00253 limit = one->getWidth() * one->getHeight() * depth; 00254 outptr = this->m_buf; 00255 00256 for (j = 0; j < limit; j++) 00257 { 00258 tmp = ((*ptr[0]) * alphainv) + ((*ptr[1]) * alpha); 00259 if (tmp < 0) tmp = 0; 00260 *outptr = (uint8_t)(tmp > 255 ? 255 : tmp); 00261 outptr++; 00262 ptr[0]++; 00263 ptr[1]++; 00264 } 00265 00266 rc = out->setImage(output_width, 00267 output_height, 00268 this->m_output_format, 00269 this->m_buf_size, 00270 this->m_buf); 00271 phCHECK_RC(rc,NULL,"out->setImage"); 00272 00273 phTHIS_UNLOCK(locked); 00274 00275 return phSUCCESS; 00276 error: 00277 00278 phTHIS_ERROR_UNLOCK(locked); 00279 00280 return phFAIL; 00281 } 00282 00283 /* ------------------------------------------------------------------------ */ 00284 int phEffectsThread::run() 00285 { 00286 phFUNCTION("phEffectsThread::run") 00287 phImage local_copy[2]; 00288 uint32_t i = 0; 00289 uint32_t counter = 0; 00290 int32_t direction = 1; 00291 00292 for (i = 0; i < 2; i++ ) 00293 { 00294 rc = local_copy[i].connect(this->m_input[i]); 00295 phCHECK_RC(rc,NULL,"this->local_copy[%d].connect(%p)",i,this->m_input[i]); 00296 } 00297 00298 rc = this->signal_running(); 00299 phCHECK_RC(rc,NULL,"this->signal_running"); 00300 00301 while (this->isRunning()) 00302 { 00303 for (i = 0; i < 2; i++ ) 00304 { 00305 rc = local_copy[i].update(); 00306 phPRINT_RC(rc,NULL,"this->local_copy[%d].update()",i); 00307 } 00308 #if 0 00309 rc = this->mosaic_images(&(local_copy[0]),&(local_copy[1]),this->m_output); 00310 phPRINT_RC(rc,NULL,"this->mosaic_images"); 00311 #else 00312 rc = this->overlay_images(&(local_copy[0]),&(local_copy[1]),this->m_output); 00313 phPRINT_RC(rc,NULL,"this->mosaic_images"); 00314 #endif 00315 00316 if (counter == 0) 00317 { 00318 if (this->m_alpha >= 1.00) 00319 direction = -1; 00320 if (this->m_alpha <= 0.00) 00321 direction = 1; 00322 00323 this->m_alpha += 0.1 * direction; 00324 counter = 0; 00325 } 00326 else 00327 { 00328 counter++; 00329 } 00330 } 00331 00332 for (i = 0; i < 2; i++ ) 00333 { 00334 rc = local_copy[i].disconnect(); 00335 phPRINT_RC(rc,NULL,"this->local_copy[%d].disconnect()",i); 00336 } 00337 00338 return phSUCCESS; 00339 error: 00340 rc = this->signal_error(); 00341 phPRINT_RC(rc,NULL,"this->signal_error"); 00342 00343 return phFAIL; 00344 } 00345 00346 /* ------------------------------------------------------------------------ */ 00347 int phEffectsThread::wakeup() 00348 { 00349 phFUNCTION("phEffectsThread::wakeup") 00350 uint32_t i = 0; 00351 00352 for (i = 0; i < 2; i++ ) 00353 { 00354 rc = this->m_input[i]->wakeup_clients(); 00355 phCHECK_RC(rc,NULL,"this->m_input[%d]->wakeup_clients();",i); 00356 } 00357 00358 return phSUCCESS; 00359 error: 00360 return phFAIL; 00361 } 00362 00363 /* ------------------------------------------------------------------------ */ 00364 int main(int argc, char *argv[] ) 00365 { 00366 phFUNCTION("main") 00367 00368 int displaysOpen= 1; 00369 00370 unsigned int i = 0; 00371 unsigned int image_count = 50; 00372 char* filename = NULL; 00373 00374 phDisplayInterface *display = NULL; 00375 00376 int delay = 0; 00377 int fps = 0; 00378 int loop = 0; 00379 00380 /* Utility class to ease the starting and stopping of displays, captures and 00381 * pipelines */ 00382 phSystem system; 00383 phAvcodecSource *capture = new phAvcodecSource(); 00384 V4LCapture *capture2 = new V4LCapture(); 00385 00386 phEffectsThread mosaic(capture->getOutput(), 00387 capture2->getOutput(), 00388 phImageRGBA32); 00389 00390 /* Remove the code below when using this code as an example. 00391 * 00392 * This just checks whether "--test" has been specified with 00393 * a time value argument. It's for testing all the examples 00394 * without the need for human intervention. */ 00395 int test = 0; 00396 00397 phArgTable *arg_parser = new phArgTable(); 00398 00399 /* Setup and parse all the arguments */ 00400 rc = arg_parser->add("--delay", &delay, phARG_INT); 00401 phCHECK_RC(rc, NULL, "arg_parser->add"); 00402 rc = arg_parser->add("--fps", &fps, phARG_INT); 00403 phCHECK_RC(rc, NULL, "arg_parser->add"); 00404 rc = arg_parser->add("--file", &filename, phARG_CHAR); 00405 phCHECK_RC(rc, NULL, "arg_parser->add"); 00406 rc = arg_parser->add("--test", &test, phARG_INT); 00407 phCHECK_RC(rc,NULL,"arg_parser->add"); 00408 rc = arg_parser->add("--nodisplay", (void *)&glbl_disable_displays, phARG_BOOL); 00409 phCHECK_RC(rc,NULL,"arg_parser->add"); 00410 rc = arg_parser->add("--loop",&loop, phARG_INT); 00411 phCHECK_RC(rc,NULL,"arg_parser->add"); 00412 rc = arg_parser->add("--help",(void *)&usage, phARG_FUNC); 00413 phCHECK_RC(rc,NULL,"arg_parser->add"); 00414 00415 rc = arg_parser->parse(argc,argv); 00416 phCHECK_RC(rc,NULL,"arg_parser->parse"); 00417 00418 if (filename == NULL) 00419 { 00420 phCHECK_PTR(filename,NULL,"filename not given"); 00421 } 00422 00423 capture->setDelay(delay); 00424 if (fps) 00425 capture->setFps(fps); 00426 capture->setLoop(loop); 00427 capture->setFormat(phImageRGB24); 00428 00429 rc = capture->setPath(filename); 00430 phCHECK_RC(rc,NULL,"capture->setPath(%s)",filename); 00431 00432 rc = system.add(capture); 00433 phCHECK_RC(rc,NULL,"system.add(capture:%p)",capture); 00434 00435 /* Set up the capture parameters */ 00436 capture2->set ( 320, 240, "/dev/video0" ); 00437 capture2->setChannel ( 1 ); 00438 capture2->setFormat ( phImageRGB24 ); 00439 00440 rc = system.add(capture2); 00441 phCHECK_RC(rc,NULL,"system.add(capture2:%p)",capture2); 00442 00443 /* TODO: init capture */ 00444 if (glbl_disable_displays == 0) 00445 { 00446 #if 0 00447 display = new X11Display(capture->getWidth(), 00448 capture->getHeight(), 00449 "phAvcodecSourceTest"); 00450 phCHECK_PTR(display,"new","new X11Display failed."); 00451 00452 display->setLiveSourceInput(capture->getLiveSourceOutput()); 00453 #else 00454 display = new X11Display(160,120, 00455 "EffectsTest"); 00456 phCHECK_PTR(display,"new","new X11Display failed."); 00457 00458 display->setLiveSourceInput(mosaic.getLiveSourceOutput()); 00459 #endif 00460 rc = system.addDisplay(display); 00461 } 00462 00463 rc = system.add(&mosaic); 00464 phCHECK_RC(rc,NULL,"system.add(&mosaic)"); 00465 00466 /* startup */ 00467 rc = system.startup(); 00468 phPRINT_RC(rc,NULL,"system.startup()"); 00469 00470 // now loop continuously for as long as we have a display open and a frame available from the avi file 00471 while ((displaysOpen) && (system.capturesActive())) 00472 { 00473 if (glbl_disable_displays == 0) 00474 { 00475 displaysOpen = 0; 00476 if (system.displaysOpen()) 00477 { 00478 displaysOpen = 1; 00479 } 00480 } 00481 00482 /* Remove this if block when using this code as an example */ 00483 /* Set the loop control value to end the loop when testing */ 00484 if (test > 0) 00485 { 00486 /* loop once through for this test */ 00487 if (i == (image_count - 1)) 00488 { 00489 displaysOpen = 0; 00490 } 00491 } 00492 00493 phMSleep(100); 00494 } 00495 00496 error: 00497 rc = system.shutdown(); 00498 phPRINT_RC(rc,NULL,"system.shutdown()"); 00499 00500 phDelete(display); 00501 phDelete(capture); 00502 phDelete(capture2); 00503 00504 // free up the filename string allocation 00505 phFree(filename); 00506 00507 phDelete(arg_parser); 00508 00509 return phSUCCESS; 00510 }
Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |