detect_image_corners.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *  Software License Agreement (BSD License)
00003 *  Copyright (c) 2013, Intelligent Robotics Lab, DLUT.
00004 *  All rights reserved.
00005 *  Author:Zhao Cilang,Yan Fei,Zhuang Yan
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Intelligent Robotics Lab nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 #include <ros/ros.h>
00034 #include <opencv/cvwimage.h>
00035 #include <opencv/highgui.h>
00036 #include <opencv/cv.h>
00037 
00038 #include <vector>
00039 #include <fstream>
00040 
00041 #define nWidth  1280
00042 #define nHeight 960
00043 #define board_w 3
00044 #define board_h 4
00045 #define FOREGROUND 255
00046 #define BACKGROUND 0
00047 
00048 using namespace std;
00049 
00050 bool integralImageThresholding (IplImage * src, IplImage * img_threshold, double t);
00051 
00052 bool integralImageThresholding (IplImage * src, IplImage * img_threshold, double t)
00053 {
00054   //safety test of the input image
00055   if (src == NULL || src->width != img_threshold->width || src->height != img_threshold->height)
00056     return false;
00057 
00058   //initialization of the parameters
00059   int w = src->width;
00060   int h = src->height;
00061   int s = w / 8;                /* The sliding window */
00062   int sum, num;
00063   int x1, y1, x2, y2;
00064   vector < vector < int > >integral;     /*Store the integral image */
00065 
00066   //Initialize the integral image
00067   integral.resize (h);
00068   for (int i = 0; i < h; i++)
00069     integral[i].resize (w);
00070 
00071   //calculate the integral image
00072   for (int i = 0; i < h; i++)
00073   {
00074     sum = 0;
00075     uchar *ptr = (uchar *) (src->imageData + src->widthStep * i);
00076     for (int j = 0; j < w; j++)
00077     {
00078       sum += ptr[j];
00079       if (0 == i)
00080         integral[i][j] = sum;
00081       else
00082         integral[i][j] = integral[i - 1][j] + sum;
00083     }
00084   }
00085 
00086   //Perform the adaptive threshold
00087   for (int i = 0; i < h; i++)
00088   {
00089     uchar *ptr = (uchar *) (src->imageData + src->widthStep * i);
00090     uchar *out = (uchar *) (img_threshold->imageData + img_threshold->widthStep * i);
00091     for (int j = 0; j < w; j++)
00092     {
00093       x1 = j - s / 2;
00094       x2 = j + s / 2;
00095       y1 = i - s / 2;
00096       y2 = i + s / 2;
00097 
00098       //Image border inspection
00099       if (x1 < 0)
00100         x1 = 0;
00101       if (x2 >= w)
00102         x2 = w - 1;
00103       if (y1 < 0)
00104         y1 = 0;
00105       if (y2 >= h)
00106         y2 = h - 1;
00107 
00108       num = (x2 - x1) * (y2 - y1);
00109 
00110       // calculate  the 'sum' according to different boundary conditions
00111       if (0 == x1 && y1 != 0)
00112         sum = integral[y2][x2] - integral[y1 - 1][x2];
00113       else if (0 == y1 && x1 != 0)
00114         sum = integral[y2][x2] - integral[y2][x1 - 1];
00115       else if (0 == x1 && 0 == y1)
00116         sum = integral[y2][x2];
00117       else
00118         sum = integral[y2][x2] - integral[y2][x1 - 1] - integral[y1 - 1][x2] + integral[y1 - 1][x1 - 1];
00119 
00120       //compare the adaptive threshold values 
00121       if ((int) (ptr[j]) * num <= sum * (1 - t))
00122         out[j] = FOREGROUND;
00123       else
00124         out[j] = BACKGROUND;
00125     }
00126   }
00127   return true;
00128 }
00129 
00130 
00131 int main (int argc, char **argv)
00132 {
00133   char *filename = argv[1];
00134   int r_t = atoi (argv[2]);
00135   int bg_t = atoi (argv[3]);
00136   int bg_diff = atoi (argv[4]);
00137 
00138   IplImage *image = cvLoadImage (filename, CV_LOAD_IMAGE_COLOR);        //load the image
00139   IplImage *raw_image = cvCreateImage (cvSize (nWidth, nHeight), 8, 3);
00140   cvCopy (image, raw_image, NULL);
00141 
00142   int **arr_image = new int *[nHeight];
00143   for (int i = 0; i < nHeight; i++)
00144   {
00145     arr_image[i] = new int[nWidth];
00146   }
00147 
00148   int x, y;
00149   int r, g, b;
00150   vector < CvPoint > red_points_vec;
00151   vector < CvPoint > detect_points_vec;
00152   vector < vector < CvPoint > >result_points_vec;
00153   CvPoint point;
00154 
00155   for (y = 0; y < nHeight; y++)
00156   {
00157     for (x = 0; x < nWidth; x++)
00158     {
00159       r = ((unsigned char *) (image->imageData + image->widthStep * y))[x * 3 + 2];
00160       g = ((unsigned char *) (image->imageData + image->widthStep * y))[x * 3 + 1];
00161       b = ((unsigned char *) (image->imageData + image->widthStep * y))[x * 3];
00162 
00163       if ((r > r_t) && (g < bg_t) && (b < bg_t) && (abs (g - b) < bg_diff))     //find the red points
00164       {
00165         arr_image[y][x] = 1;
00166         point.x = x;
00167         point.y = y;
00168         red_points_vec.push_back (point);
00169       }
00170       else
00171         arr_image[y][x] = 0;
00172     }
00173   }
00174   detect_points_vec.reserve (red_points_vec.size ());   //save the points we want to detect
00175   result_points_vec.reserve (red_points_vec.size ());   //save the result 
00176   for (int i = 0; i < (int) red_points_vec.size (); i++)        //clustering to find the red  border
00177   {
00178     if (arr_image[red_points_vec[i].y][red_points_vec[i].x] == 1)
00179     {
00180       arr_image[red_points_vec[i].y][red_points_vec[i].x] = 0;
00181       detect_points_vec.push_back (red_points_vec[i]);
00182       vector < CvPoint >::iterator ptr = detect_points_vec.begin ();
00183       while (ptr != detect_points_vec.end ())
00184       {
00185         if (arr_image[ptr->y - 1][ptr->x] == 1)
00186         {
00187           point.x = ptr->x;
00188           point.y = ptr->y - 1;
00189           detect_points_vec.push_back (point);
00190           arr_image[ptr->y - 1][ptr->x] = 0;
00191         }
00192         if (arr_image[ptr->y][ptr->x + 1] == 1)
00193         {
00194           point.x = ptr->x + 1;
00195           point.y = ptr->y;
00196           detect_points_vec.push_back (point);
00197           arr_image[ptr->y][ptr->x + 1] = 0;
00198         }
00199         if (arr_image[ptr->y + 1][ptr->x] == 1)
00200         {
00201           point.x = ptr->x;
00202           point.y = ptr->y + 1;
00203           detect_points_vec.push_back (point);
00204           arr_image[ptr->y + 1][ptr->x] = 0;
00205         }
00206         if (arr_image[ptr->y][ptr->x - 1] == 1)
00207         {
00208           point.x = ptr->x - 1;
00209           point.y = ptr->y;
00210           detect_points_vec.push_back (point);
00211           arr_image[ptr->y][ptr->x - 1] = 0;
00212         }
00213         ptr++;
00214       }
00215       result_points_vec.push_back (detect_points_vec);  //save the clustering result 
00216       detect_points_vec.clear ();
00217       ROS_INFO ("Find a class here");
00218     }
00219     else
00220     {
00221       continue;
00222     }
00223   }
00224 
00225   for (int i = 0; i < nHeight; i++)
00226   {
00227     delete[]arr_image[i];
00228   }
00229   delete[]arr_image;
00230   ROS_INFO ("There are all %d classes", result_points_vec.size ());
00231 
00232   int maxSize = (int) result_points_vec[0].size ();
00233   int k = 0;
00234   for (int i = 1; i < (int) result_points_vec.size (); i++)     //find the biggest class ,which is the red border
00235   {
00236     if ((int) result_points_vec[i].size () > maxSize)
00237     {
00238       maxSize = (int) result_points_vec[i].size ();
00239       k = i;
00240     }
00241 
00242   }
00243   ROS_INFO ("The biggst class has %d points", maxSize);
00244 
00245   int min_x, min_y, max_x, max_y;
00246   min_x = result_points_vec[k][0].x;
00247   min_y = result_points_vec[k][0].y;
00248   max_x = result_points_vec[k][0].x;
00249   max_y = result_points_vec[k][0].y;
00250 
00251   for (int i = 2; i < (int) result_points_vec[k].size (); i++)  //find the minimum and maximum of x and y 
00252   {
00253     if (result_points_vec[k][i].x > max_x)
00254     {
00255       max_x = result_points_vec[k][i].x;
00256     }
00257     if (result_points_vec[k][i].y > max_y)
00258     {
00259       max_y = result_points_vec[k][i].y;
00260     }
00261     if (result_points_vec[k][i].x < min_x)
00262     {
00263       min_x = result_points_vec[k][i].x;
00264     }
00265     if (result_points_vec[k][i].y < min_y)
00266     {
00267       min_y = result_points_vec[k][i].y;
00268     }
00269   }
00270   CvPoint min_point, max_point;
00271   min_point.x = min_x;
00272   min_point.y = min_y;
00273   max_point.x = max_x;
00274   max_point.y = max_y;
00275   cvRectangle (image, min_point, max_point, CV_RGB (0, 200, 0), 8, 8, 0);       //draw the border
00276 
00277   //cut the chess board from the whole image 
00278   CvScalar s;
00279   IplImage *chessboard_image =
00280     cvCreateImage (cvSize (max_point.x - min_point.x + 1, max_point.y - min_point.y + 1), 8, 3);
00281   for (int i = min_point.y; i < max_point.y; i++)
00282   {
00283     for (int j = min_point.x; j < max_point.x; j++)
00284     {
00285       s.val[2] = ((unsigned char *) (raw_image->imageData + raw_image->widthStep * i))[j * 3 + 2];
00286       s.val[1] = ((unsigned char *) (raw_image->imageData + raw_image->widthStep * i))[j * 3 + 1];
00287       s.val[0] = ((unsigned char *) (raw_image->imageData + raw_image->widthStep * i))[j * 3];
00288       cvSet2D (chessboard_image, i - min_point.y, j - min_point.x, s);
00289     }
00290   }
00291 
00292   IplImage *chessboard_grayimage_ = cvCreateImage (cvGetSize (chessboard_image), 8, 1);
00293   cvCvtColor (chessboard_image, chessboard_grayimage_, CV_RGB2GRAY);
00294   IplImage *chessboard_grayimage = cvCreateImage (cvGetSize (chessboard_image), 8, 1);
00295   bool bIsInteg = integralImageThresholding (chessboard_grayimage_, chessboard_grayimage, 0.15);        // do integral for image and thresholding 
00296   if (bIsInteg)
00297   {
00298     ROS_INFO ("GOOD");
00299   }
00300   else
00301   {
00302     ROS_INFO ("Fail to thresholding");
00303     return -1;
00304   }
00305 
00306   CvPoint2D32f *corners = new CvPoint2D32f[board_w * board_h];
00307   int corner_count;
00308   CvSize board_sz = cvSize (board_w, board_h);
00309   //find the corners of chessboard
00310   int found = cvFindChessboardCorners (chessboard_grayimage,
00311                                        board_sz,
00312                                        corners,
00313                                        &corner_count,
00314                                        CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
00315   ROS_INFO ("CORNER_COUMT = %d", corner_count);
00316   if (found == 1)
00317   {
00318     ROS_INFO ("FIND CORNERS OK");
00319   }
00320   else
00321     ROS_INFO ("FAIL TO FIND CORNERS");
00322 
00323   cvFindCornerSubPix (chessboard_grayimage, corners, corner_count, cvSize (11, 11), cvSize (-1, -1),
00324                       cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
00325 
00326   CvPoint corner_point[corner_count];
00327   CvPoint corner_point_raw[corner_count];
00328   //Save the corners
00329   ofstream my_w ("visionpts.txt");
00330   if (!my_w.is_open ())
00331   {
00332     ROS_INFO ("open the file visionpts.txt fail\n");
00333     return -1;
00334   }
00335   else
00336     ROS_INFO ("open the file ok\n");
00337 
00338   for (int i = 0; i < corner_count; i++)
00339   {
00340     corner_point[i].x = corners[i].x;
00341     corner_point[i].y = corners[i].y;
00342     corner_point_raw[i].x = corners[i].x + min_point.x;
00343     corner_point_raw[i].y = corners[i].y + min_point.y;
00344     my_w << corner_point_raw[i].x * 1.0 << "  " << corner_point_raw[i].y * 1.0 << "\n";
00345 
00346   }
00347   my_w.close ();
00348   //draw the corners
00349   for (int i = 0; i < corner_count; i++)
00350   {
00351     cvCircle (chessboard_grayimage, corner_point[i], 5, CV_RGB (200, 0, 0));
00352     cvCircle (raw_image, corner_point_raw[i], 5, CV_RGB (200, 0, 0));
00353 
00354   }
00355   delete[]corners;
00356 
00357   cvNamedWindow ("detect_egde", 0);
00358   cvNamedWindow ("detect_corners", 0);
00359   cvNamedWindow ("raw_image", 0);
00360   cvShowImage ("detect_egde", image);
00361   cvShowImage ("detect_corners", chessboard_grayimage);
00362   cvShowImage ("raw_image", raw_image);
00363   cvWaitKey (0);
00364   cvDestroyWindow ("detect_egde");
00365   cvDestroyWindow ("detect_corners");
00366   cvDestroyWindow ("raw_image");
00367   cvReleaseImage (&image);
00368   cvReleaseImage (&chessboard_grayimage);
00369   cvReleaseImage (&raw_image);
00370 
00371   return 0;
00372 }


camera_laser_calibration
Author(s): Zhao Cilang,Yan Fei,Zhuang Yan/zhuang@dlut.edu.cn
autogenerated on Sun Jan 5 2014 11:05:02