📄 p2cmv.cc
字号:
/* * Player - One Hell of a Robot Server * Copyright (C) 2000 * Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard * Andrew Martignoni III * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* * $Id: P2CMV.cc,v 1.26 2005/11/16 00:56:01 gerkey Exp $ * * Uses CMVision to retrieve the blob data *//** @ingroup drivers *//** @{ *//** @defgroup driver_cmvision cmvision@brief CMVisionCMVision (Color Machine Vision) is a fastcolor-segmentation (aka blob-finding) software library.CMVision was written by Jim Bruce at CMU and is Freely <ahref=http://www-2.cs.cmu.edu/~jbruce/cmvision/>available</a> underthe GNU GPL. But you don't have to download CMVision yourself, becausePlayer's cmvision driver includes the CMVision code. The cmvision driverprovides a stream of camera images to the CMVision code and assemblesthe resulting blob information into Player's data format.Consult the CMVision documentation for details on writing a CMVisionconfiguration file.@par Compile-time dependencies- none@par Provides- @ref interface_blobfinder@par Requires- @ref interface_camera : camera device to get image data from@par Configuration requests- none@par Configuration file options- debuglevel (int) - Default: 0 - If set to 1, the blobfinder will output a testpattern of three blobs.- colorfile (string) - Default: "" - CMVision configuration file. In the colors section, the tuple is the RGB value of the intended color. In the thresholds section, the values are the min:max of the respective YUV channels.@verbatim[Colors](255, 0, 0) 0.000000 10 Red( 0,255, 0) 0.000000 10 Green( 0, 0,255) 0.000000 10 Blue[Thresholds]( 25:164, 80:120,150:240)( 20:220, 50:120, 40:115)( 15:190,145:255, 40:120)@endverbatim@par Example@verbatimdriver( name "cmvision" provides ["blobfinder:0"] requires ["camera:0"])@endverbatim@author Andy Martignoni III, Brian Gerkey, Brendan Burns,Ben Grocholsky, Brad Kratochvil*//** @} */#include <assert.h>#include <stdio.h>#include <unistd.h> /* close(2),fcntl(2),getpid(2),usleep(3),execvp(3),fork(2)*/#include <signal.h> /* for kill(2) */#include <fcntl.h> /* for fcntl(2) */#include <string.h> /* for strncpy(3),memcpy(3) */#include <stdlib.h> /* for atexit(3),atoi(3) */#include <pthread.h> /* for pthread stuff */#include <math.h> /* for rint */#include <libplayercore/playercore.h>#include <libplayercore/error.h>#include "conversions.h"#include "cmvision.h"#include "capture.h"#define CMV_NUM_CHANNELS CMV_MAX_COLORS#define CMV_HEADER_SIZE 4*CMV_NUM_CHANNELS#define CMV_BLOB_SIZE 16#define CMV_MAX_BLOBS_PER_CHANNEL 10#define DEFAULT_CMV_WIDTH CMV_DEFAULT_WIDTH#define DEFAULT_CMV_HEIGHT CMV_DEFAULT_HEIGHT/********************************************************************/class CMVisionBF: public Driver{ private: int mDebugLevel; // debuglevel 0=none, // 1=basic, // 2=everything uint16_t mWidth; uint16_t mHeight; // the image dimensions uint8_t* mImg; const char* mColorFile; player_blobfinder_data_t mData; player_devaddr_t mCameraAddr; Device* mCameraDev; CMVision* mVision; // this will output a testpattern for debugging void TestPattern(); // print the blobs to the console void Print(); public: int Setup(); int Shutdown(); // constructor CMVisionBF(ConfigFile* cf, int section); // This method will be invoked on each incoming message virtual int ProcessMessage(MessageQueue* resp_queue, player_msghdr * hdr, void * data); virtual void Main(); void ProcessImageData();};// a factory creation functionDriver*CMVision_Init( ConfigFile* cf, int section){ return((Driver*)(new CMVisionBF( cf, section)));}// a driver registration functionvoidCMVision_Register(DriverTable* table){ table->AddDriver("cmvision", CMVision_Init);}CMVisionBF::CMVisionBF( ConfigFile* cf, int section) : Driver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_BLOBFINDER_CODE), mWidth(0), mHeight(0), mImg(NULL), mColorFile(NULL), mCameraDev(NULL), mVision(NULL){ mColorFile = cf->ReadString(section, "colorfile", ""); mDebugLevel = cf->ReadInt(section, "debuglevel", 0); // Must have an input camera if (cf->ReadDeviceAddr(&mCameraAddr, section, "requires", PLAYER_CAMERA_CODE, -1, NULL) != 0) { PLAYER_ERROR("this driver requires a camera in the .cfg file"); return; }}intCMVisionBF::Setup(){ printf("CMVision server initializing..."); fflush(stdout); // Subscribe to the camera device if (!(this->mCameraDev = deviceTable->GetDevice(this->mCameraAddr))) { PLAYER_ERROR("unable to locate suitable camera device"); return(-1); } if(0 != this->mCameraDev->Subscribe(this->InQueue)) { PLAYER_ERROR("unable to subscribe to camera device"); return(-1); } mVision = new CMVision; // clean our data memset(&mData,0,sizeof(mData)); puts("done."); StartThread(); return(0);}intCMVisionBF::Shutdown(){ /* if Setup() was never called, don't do anything */ if (mVision==NULL) return 0; StopThread(); // Unsubscribe from the laser this->mCameraDev->Unsubscribe(this->InQueue); delete mVision; delete mImg; puts("CMVision server has been shutdown"); return(0);}voidCMVisionBF::Main(){ // The main loop; interact with the device here for(;;) { // wait to receive a new message (blocking) Wait(); // test if we are supposed to cancel pthread_testcancel(); // Process incoming messages, and update outgoing data ProcessMessages(); } return;}voidCMVisionBF::ProcessImageData(){ // this shouldn't change often if ((mData.width != mWidth) || (mData.height != mHeight)) { //printf("CMVision server initializing..."); fflush(stdout); if(!(mVision->initialize(mWidth, mHeight))) { PLAYER_ERROR("Vision init failed."); exit(-1); } if(mColorFile[0]) { if (!mVision->loadOptions(const_cast<char*>(mColorFile))) { PLAYER_ERROR("Error loading color file"); exit(-1); } } else { PLAYER_ERROR("No color file given. Use the \"mColorFile\" " "option in the configuration file."); exit(-1); } mData.width = mWidth; mData.height = mHeight; printf("cmvision using camera: [w %d h %d]\n", mWidth, mHeight); } if (!mVision->processFrame(reinterpret_cast<image_pixel*>(mImg))) { PLAYER_ERROR("Frame error."); } mData.blobs_count = 0; for (int ch = 0; ch < CMV_MAX_COLORS; ++ch) { // Get the descriptive color rgb c = mVision->getColorVisual(ch);; // Grab the regions for this color CMVision::region* r = NULL; for (r = mVision->getRegions(ch); r != NULL; r = r->next) { if (mData.blobs_count >= PLAYER_BLOBFINDER_MAX_BLOBS) break; player_blobfinder_blob_t *blob; blob = mData.blobs + mData.blobs_count; mData.blobs_count++; blob->color = uint32_t(c.red) << 16 | uint32_t(c.green) << 8 | uint32_t(c.blue); // stage puts the range in here to simulate stereo mVision. we // can't do that (yet?) so set the range to zero - rtv blob->range = 0; // get the area first blob->area = static_cast<uint32_t>(r->area); blob->x = static_cast<uint32_t>(rint(r->cen_x+.5)); blob->y = static_cast<uint32_t>(rint(r->cen_y+.5)); blob->left = static_cast<uint32_t>(r->x1); blob->right = static_cast<uint32_t>(r->x2); blob->top = static_cast<uint32_t>(r->y1); blob->bottom = static_cast<uint32_t>(r->y2); } } // if we're debugging, output the test blobs if (0 != mDebugLevel) TestPattern(); /* got the data. now publish it */ uint size = sizeof(mData) - sizeof(mData.blobs) + mData.blobs_count * sizeof(mData.blobs[0]); Publish(device_addr, NULL, PLAYER_MSGTYPE_DATA, PLAYER_BLOBFINDER_DATA_BLOBS, reinterpret_cast<void*>(&mData), size, NULL);}voidCMVisionBF::TestPattern(){ mData.blobs_count = 3; for (uint i=0; i<mData.blobs_count; ++i) { uint x = mWidth/5*i + mWidth/5; uint y = mHeight/2; mData.blobs[i].x = x; mData.blobs[i].y = y; mData.blobs[i].top = y+10; mData.blobs[i].bottom = y-10; mData.blobs[i].left = x-10; mData.blobs[i].right = x+10; mData.blobs[i].color = 0xff << i*8; }}voidCMVisionBF::Print(){ // this is mainly for debugging purposes for (uint i=0; i<mData.blobs_count; ++i) { printf("%i: ", i); printf("%i, ", mData.blobs[i].x); printf("%i, ", mData.blobs[i].y); printf("%i, ", mData.blobs[i].top); printf("%i, ", mData.blobs[i].left); printf("%i, ", mData.blobs[i].bottom); printf("%i\n", mData.blobs[i].right); } printf("-----\n");}intCMVisionBF::ProcessMessage(MessageQueue* resp_queue, player_msghdr* hdr, void* data){ // Handle new data from the camera if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE, this->mCameraAddr)) { // we can't quite do this so easily with camera data // because the images are different than the max size //assert(hdr->size == sizeof(player_camera_data_t)); player_camera_data_t* camera_data; camera_data = reinterpret_cast<player_camera_data_t *>(data); mWidth = camera_data->width; mHeight = camera_data->height; if (NULL == mImg) { // we need to allocate some memory mImg = new uint8_t[mWidth*mHeight*2]; } else { // now deal with the data rgb2uyvy(camera_data->image, mImg, mWidth*mHeight); } // we have a new image, ProcessImageData(); return(0); } // Tell the caller that you don't know how to handle this message return(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -