00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <opencv/cv.h>
00029 #include <iostream>
00030 #include <sstream>
00031 #include <fstream>
00032 #include <string>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <cv_bridge/cv_bridge.h>
00036 #include <opencv/cvwimage.h>
00037 #include <image_transport/image_transport.h>
00038 #include <ros/ros.h>
00039 #include <vision_msgs/Rect.h>
00040
00041 #define NCAMS 6 // not to be changed! For single cam output use: -m 1 to -m 6
00042 #define IMAGE_HEIGHT 616
00043 #define IMAGE_WIDTH 808
00044 #define PANO_HEIGHT 375
00045 #define PANO_WIDTH 750
00046 #define PANO_RADIUS 20
00047 using namespace std;
00048
00049
00050 template<class T> class Image
00051 {
00052 private:
00053 IplImage* imgp;
00054 public:
00055 Image(IplImage* img=0) {imgp=img;}
00056 ~Image(){imgp=0;}
00057 void operator=(IplImage* img) {imgp=img;}
00058 inline T* operator[](const int rowIndx) {
00059 return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
00060 };
00061 typedef struct{
00062 unsigned char b,g,r;
00063 } RgbPixel;
00064 typedef struct{
00065 float b,g,r;
00066 } RgbPixelFloat;
00067
00068 typedef Image<RgbPixel> RgbImage;
00069 typedef Image<RgbPixelFloat> RgbImageFloat;
00070 typedef Image<unsigned char> BwImage;
00071 typedef Image<float> BwImageFloat;
00072
00073
00074 class CLut
00075 {
00076 public:
00077 CLut(int nRows, int nCols, int nCams);
00078 ~CLut();
00079 int getValue(int iRow, int iCol, int iCam);
00080 void setValue(int iRow, int iCol, int iCam, int iVal);
00081 int fillArray(string cFileName[]);
00082 private:
00083 void initArray();
00084 int *m_array;
00085 int m_Rows;
00086 int m_Cols;
00087 int m_Cams;
00088 };
00089 CLut::CLut(int nRows, int nCols, int nCams)
00090 {
00091 m_Rows = nRows;
00092 m_Cols = nCols;
00093 m_Cams = nCams;
00094 initArray();
00095 }
00096 CLut::~CLut(){
00097 delete m_array;
00098 }
00099 void CLut::initArray()
00100 {
00101 m_array = new int [m_Rows*m_Cols*NCAMS];
00102 }
00103 inline int CLut::getValue(int iRow, int iCol, int iCam)
00104 {
00105 if (iRow<m_Rows && iCol<m_Cols && iCam <m_Cams)
00106 return m_array[iCol+iRow*m_Cols+iCam*m_Cols*m_Rows];
00107 else
00108 return 0;
00109 }
00110 inline void CLut::setValue(int iRow, int iCol, int iCam, int iVal)
00111 {
00112 if (iRow<m_Rows && iCol<m_Cols && iCam <m_Cams)
00113 m_array[iCol+iRow*m_Cols+iCam*m_Cols*m_Rows] = iVal;
00114 }
00115 int CLut::fillArray(string cFileName[])
00116 {
00117 const char * pFileName;
00118 int indCam = 0;
00119 int value = 0;
00120 int linenum = 0;
00121 int itemnum = 0;
00122 string line, item;
00123
00124
00125 for(indCam = 0; indCam<6; indCam++)
00126 {
00127 linenum = 0;
00128 pFileName = cFileName[indCam].c_str();
00129 ifstream inFile(pFileName);
00130 if (inFile.is_open())
00131 {
00132 while (getline (inFile, line))
00133 {
00134 if (linenum <m_Rows)
00135 {
00136 istringstream linestream(line);
00137 while (getline (linestream, item, ',') && (itemnum<m_Cols))
00138 {
00139 istringstream is(item);
00140 is >> value;
00141 m_array[itemnum+linenum*m_Cols+indCam*m_Cols*m_Rows] = value-1;
00142 itemnum++;
00143 }
00144 }
00145 linenum++;
00146 itemnum = 0;
00147 }
00148 inFile.close();
00149 cout << "LUT uploaded: " << pFileName << endl;
00150 }
00151 else
00152 {
00153 ROS_ERROR("Unable to open following LUT file: '%s'\n", pFileName);
00154
00155 exit (1);
00156 }
00157 }
00158 return 0;
00159
00160 }
00161 void setlabels(string (&labelset)[NCAMS], char path[], int pheight, int pwidth, int iheight, int iwidth, int prange, char xory)
00162 {
00163 char label[200];
00164 for(int i = 1; i <= NCAMS; i++) {
00165 sprintf(label, "%s/LUT_img_%ix%i_pano_%ix%ir%i_%c%i.txt", path, iwidth, iheight, pwidth, pheight, prange, xory, i);
00166 labelset[i-1] = label;
00167 }
00168 }
00169
00170
00171 int mode = 1;
00172 int imgh = IMAGE_HEIGHT;
00173 int imgw = IMAGE_WIDTH;
00174 int panoh = PANO_HEIGHT;
00175 int panow = PANO_WIDTH;
00176 int panor = PANO_RADIUS;
00177
00178 CLut *pLUTX;
00179 CLut *pLUTY;
00180 CLut *pLUTA;
00181 IplImage *frame;
00182 IplImage *out;
00183 image_transport::Publisher pub;
00184 ros::Publisher camera_info_pub;
00185 sensor_msgs::CameraInfo msg_cam;
00186
00187 void imageCallback(const sensor_msgs::ImageConstPtr& msg)
00188 {
00189 sensor_msgs::CvBridge bridge;
00190 try {
00191 frame = bridge.imgMsgToCv(msg, "bgr8");
00192 int w,h;
00193 w = frame->height/6;
00194 h = frame->width;
00195 if ((mode>=1)&&(mode<=6)){
00196 out = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);
00197 RgbImage imgA(frame);
00198 RgbImage imgB(out);
00199 int i = mode;
00200 for (int u=0; u<w; u++){
00201 for (int v=0; v<h; v++){
00202 imgB[v][w-u-1].b = imgA[u+(i-1)*w][v].b;
00203 imgB[v][w-u-1].r = imgA[u+(i-1)*w][v].r;
00204 imgB[v][w-u-1].g = imgA[u+(i-1)*w][v].g;
00205 }
00206 }
00207 }
00208 if (mode == 7) {
00209 out = cvCreateImage(cvSize(panow, panoh), IPL_DEPTH_8U, 3);
00210 RgbImage imgA(frame);
00211 RgbImage imgB(out);
00212 if ((frame->height/6 == imgh) && (frame->width == imgw)) {
00213 int x = 0;
00214 int y = 0;
00215 unsigned int avgb, avgr, avgg, count;
00216 for (int u = 0; u < panoh; u++) {
00217 for (int v = 0; v < panow; v++) {
00218 count = avgb = avgr = avgg =0;
00219
00220 for(int c=0; c<NCAMS; c++){
00221 x = pLUTX->getValue(u, v, c);
00222 y = pLUTY->getValue(u, v, c);
00223
00224 if (x >= 0 && y >= 0){
00225 unsigned int a = pLUTA->getValue(u, v, c);
00226 avgb = avgb + (unsigned int) imgA[y][x].b * a;
00227 avgr = avgr + (unsigned int) imgA[y][x].r * a;
00228 avgg = avgg + (unsigned int) imgA[y][x].g * a;
00229 count++;
00230 }
00231 }
00232 if (count > 0) {
00233 imgB[u][v].b = (unsigned char) (avgb / 255);
00234 imgB[u][v].r = (unsigned char) (avgr / 255);
00235 imgB[u][v].g = (unsigned char) (avgg / 255);
00236 }
00237 }
00238 }
00239 }
00240 else {
00241 ROS_ERROR("Input image size '%ix%i' does not match the expected '%ix%i'\n",frame->width, frame->height, imgw, imgh );
00242 ros::shutdown();
00243
00244 }
00245 }
00246 cv::WImageBuffer3_b image( out );
00247 sensor_msgs::ImagePtr msg_out = sensor_msgs::CvBridge::cvToImgMsg(image.Ipl(), "bgr8");
00248 msg_out->header = msg->header;
00249 if (mode >= 1 && mode <= 6) {
00250 char buffer[100];
00251 sprintf(buffer ,"tflbcamera%d", mode - 1);
00252 msg_out->header.frame_id = string(buffer);
00253 }
00254 pub.publish(msg_out);
00255
00256 msg_cam.header = msg_out->header;
00257 msg_cam.height = out->height;
00258 msg_cam.width = out->width;
00259 camera_info_pub.publish(msg_cam);
00260 }
00261 catch (sensor_msgs::CvBridgeException& e) {
00262 ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
00263 }
00264 }
00265
00266 int main(int argc, char ** argv)
00267 {
00268
00269 char topic_name[200];
00270 char topic_name_out[200];
00271 char lutpath[500];
00272 strcpy( topic_name, "/camera/image");
00273 strcpy( topic_name_out, "/viz/image_out");
00274 for(int i = 0; i < argc; ++i) {
00275 if(strcmp(argv[i], "-t") == 0) {
00276 if(i == argc - 1) {
00277 fprintf(stderr, "Missing input topic name after -t, default topic %s is used.\n", topic_name);
00278 }
00279 else {
00280 ++i;
00281 strcpy( topic_name, argv[i] );
00282 }
00283 }
00284 if(strcmp(argv[i], "-o") == 0) {
00285 if(i == argc - 1) {
00286 fprintf(stderr, "Missing output topic name after -o, default topic %s is used.\n", topic_name_out);
00287 }
00288 else {
00289 ++i;
00290 strcpy( topic_name_out, argv[i] );
00291 }
00292 }
00293 if(strcmp(argv[i], "-m") == 0) {
00294 if(i == argc - 1) {
00295 fprintf(stderr, "Missing mode number after -m, default topic %d is used.\n", mode);
00296 }
00297 else {
00298 ++i;
00299 mode = atoi(argv[i]);
00300 }
00301 }
00302 if(strcmp(argv[i], "-ph") == 0) {
00303 if(i == argc - 1) {
00304 fprintf(stderr, "Missing pano_height after -ph, default pano_height %d is used.\n", panoh);
00305 }
00306 else {
00307 ++i;
00308 panoh = atoi(argv[i]);
00309 }
00310 }
00311 if(strcmp(argv[i], "-pw") == 0) {
00312 if(i == argc - 1) {
00313 fprintf(stderr, "Missing pano_width after -pw, default pano_width %d is used.\n", panow);
00314 }
00315 else {
00316 ++i;
00317 panow = atoi(argv[i]);
00318 }
00319 }
00320 if(strcmp(argv[i], "-ih") == 0) {
00321 if(i == argc - 1) {
00322 fprintf(stderr, "Missing image_height after -ih, default image_height %d is used.\n", panoh);
00323 }
00324 else {
00325 ++i;
00326 imgh = atoi(argv[i]);
00327 }
00328 }
00329 if(strcmp(argv[i], "-iw") == 0) {
00330 if(i == argc - 1) {
00331 fprintf(stderr, "Missing image_width after -iw, default image_width %d is used.\n", imgw);
00332 }
00333 else {
00334 ++i;
00335 imgw = atoi(argv[i]);
00336 }
00337 }
00338 if(strcmp(argv[i], "-r") == 0) {
00339 if(i == argc - 1) {
00340 fprintf(stderr, "Missing camera range after -r, default camera range %d is used.\n", imgh);
00341 }
00342 else {
00343 ++i;
00344 panor = atoi(argv[i]);
00345 }
00346 }
00347 if(strcmp(argv[i], "-path") == 0) {
00348 if(i == argc - 1) {
00349 fprintf(stderr, "Missing path to LUT files after -path");
00350 }
00351 else {
00352 ++i;
00353 strcpy( lutpath, argv[i] );
00354 }
00355 }
00356 }
00357
00358
00359
00360 string LABELSLUTX[NCAMS], LABELSLUTY[NCAMS], LABELSLUTA[NCAMS];
00361 setlabels(LABELSLUTX, lutpath, panoh, panow, imgh, imgw, panor, 'x');
00362 setlabels(LABELSLUTY, lutpath, panoh, panow, imgh, imgw, panor, 'y');
00363 setlabels(LABELSLUTA, lutpath, panoh, panow, imgh, imgw, panor, 'a');
00364 CLut LUTX(panoh, panow, NCAMS);
00365 CLut LUTY(panoh, panow, NCAMS);
00366 CLut LUTA(panoh, panow, NCAMS);
00367
00368 LUTX.fillArray(LABELSLUTX);
00369 LUTY.fillArray(LABELSLUTY);
00370 LUTA.fillArray(LABELSLUTA);
00371
00372 pLUTX = &LUTX;
00373 pLUTY = &LUTY;
00374 pLUTA = &LUTA;
00375
00376
00377 ros::init(argc, argv, "image_listener");
00378 ros::NodeHandle nh;
00379 image_transport::ImageTransport it(nh);
00380 image_transport::Subscriber sub = it.subscribe(topic_name, 1, imageCallback);
00381 image_transport::ImageTransport it2(nh);
00382 pub = it2.advertise(topic_name_out, 1);
00383 camera_info_pub = nh.advertise<sensor_msgs::CameraInfo>("/viz/camera_info", 100);
00384 sensor_msgs::CameraInfo msg_cam;
00385
00386 ros::spin();
00387
00388 return 0;
00389 }
00390