daily pastebin goal
59%
SHARE
TWEET

Untitled

a guest Jun 13th, 2018 53 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifndef _CS440P0_H
  2. #define _CS440P0_H
  3.  
  4. #include <cv.h>
  5. #include "Image.h"
  6. #include <vector>
  7. #include <cstdlib>
  8. #include <utility>
  9. #include <iostream>
  10. #include <map>
  11. #include <algorithm>
  12.  
  13. class CS440P0
  14. {
  15. public:
  16.     CS440P0():
  17.       myChar(0)
  18.       {
  19.           //make a new window where we can show our processed results
  20.           namedWindow("detected",1);
  21.  
  22.       }
  23.  
  24.       CS440P0(Mat& frame):
  25.       myChar(0)
  26.       {
  27.  
  28.           //make a new window where we can show our processed results
  29.           namedWindow("detected",1);
  30.  
  31.           // release params = 4,10,255,3
  32.           this->bin_size = 4;
  33.           this->threshold = 10;
  34.           this->maxValue = 255;
  35.           this->MAX_ITEMS = 15;
  36.           this->MIN_MASS = 600/ (bin_size *bin_size);
  37.           this->filter = 0.1;
  38.  
  39.           // Get the cols and row values
  40.           this->ROWS = frame.rows;
  41.           this->COLS = frame.cols;
  42.  
  43.           // Initialize the boolean image array
  44.           this->bimage = new bool*[ROWS];
  45.  
  46.           for (int row = 0; row < ROWS; ++row)
  47.               bimage[row] = new bool[COLS];
  48.           for (int row = 0; row < ROWS; ++row)
  49.               for (int col = 0; col < COLS; ++col)
  50.                   bimage[row][col] = false;
  51.  
  52.           // Initialize the x and y projection vectors;
  53.           this->rp  = new int[ROWS]; //proj along x
  54.           this->cp =  new int[COLS]; //proj along y
  55.  
  56.           for (int row = 0; row < ROWS; ++row) { this->rp[row] =0;}
  57.           for (int col = 0; col < COLS; ++col) { this->cp[col] =0;}
  58.  
  59.           // Initialize the x and y bin vectors;
  60.           this->xbins  = new unsigned  int[COLS]; //bin along x
  61.           this->ybins =  new unsigned  int[ROWS]; //bin along y
  62.  
  63.           for (int row = 0; row < ROWS; ++row) { this->ybins[row] =0;}
  64.           for (int col = 0; col < COLS; ++col) { this->xbins[col] =0;}
  65.  
  66.           // Initialize the x and y boolean vectors;
  67.           this->xbool =  new bool [COLS/bin_size];
  68.           this->ybool =  new bool [ROWS/bin_size];
  69.  
  70.  
  71.           // Initialize the flood fill array
  72.           this->bin = new bool*[ROWS/bin_size];
  73.  
  74.           for (int row = 0; row < ROWS/bin_size; ++row)
  75.               this->bin[row] = new bool[COLS/bin_size];
  76.           for (int row = 0; row < ROWS/bin_size; ++row)
  77.               for (int col = 0; col < COLS/bin_size; ++col)
  78.                   this->bin[row][col] = false;
  79.  
  80.           // Initialize the flood fill array
  81.           this->fFill = new short*[ROWS/bin_size];
  82.  
  83.           for (int row = 0; row < ROWS/bin_size; ++row)
  84.               this->fFill[row] = new short[COLS/bin_size];
  85.           for (int row = 0; row < ROWS/bin_size; ++row)
  86.               for (int col = 0; col < COLS/bin_size; ++col)
  87.                   this->fFill[row][col] = 0;
  88.  
  89.  
  90.           // Initialize a new vector
  91.           this->areas = new int[MAX_ITEMS] ;
  92.           for (int ii = 0; ii < MAX_ITEMS; ++ii)
  93.           {
  94.               areas[ii]=0;
  95.           }
  96.  
  97.           // Make color chart
  98.           //this->colors = new cv::Scalar [];
  99.           int ii = 0; {}
  100.           this->colors.push_back(CV_RGB( 160,32 ,240));
  101.           this->colors.push_back(CV_RGB( 0  ,0  ,128));
  102.           this->colors.push_back(CV_RGB( 124,252,0)) ;
  103.           this->colors.push_back(CV_RGB( 200,0,0 ));
  104.           this->colors.push_back(CV_RGB( 255,255,0));
  105.           this->colors.push_back(CV_RGB( 255,165,0));
  106.           this->colors.push_back(CV_RGB( 255,105,180));
  107.           this->colors.push_back(CV_RGB( 0,0,0));
  108.           this->colors.push_back(CV_RGB( 255,255,255)) ;
  109.           this->colors.push_back(CV_RGB( 85,107,47));
  110.           this->colors.push_back(CV_RGB( 127,255,0));
  111.           this->colors.push_back(CV_RGB( 190,190,190));
  112.           this->colors.push_back(CV_RGB( 0,255,255));
  113.           this->colors.push_back(CV_RGB( 140,255,255));
  114.           this->colors.push_back(CV_RGB( 205,175,149));
  115.           this->colors.push_back(CV_RGB( 255,105,80));
  116.           this->colors.push_back(CV_RGB( 60,179,113));
  117.           this->colors.push_back(CV_RGB( 46,139,87));
  118.           this->colors.push_back(CV_RGB( 240,230,140));
  119.           this->colors.push_back(CV_RGB( 188,143,143));
  120.           this->colors.push_back(CV_RGB( 255,255,0));
  121.  
  122.  
  123.           // Min Max bounds
  124.           this->c_min = new short[MAX_ITEMS] ;
  125.           this->r_min = new short[MAX_ITEMS] ;
  126.           this->c_max = new short[MAX_ITEMS] ;
  127.           this->r_max = new short[MAX_ITEMS] ;
  128.  
  129.           for (int ii = 0; ii < MAX_ITEMS; ++ii) c_min[ii] = COLS/bin_size ;
  130.           for (int ii = 0; ii < MAX_ITEMS; ++ii) c_max[ii] = 0;
  131.           for (int ii = 0; ii < MAX_ITEMS; ++ii) r_min[ii] = ROWS/bin_size;
  132.           for (int ii = 0; ii < MAX_ITEMS; ++ii) r_max[ii] = 0;
  133.       }
  134.  
  135.       template < typename T>
  136.       void empty2D( T* myArray, int row_size, int col_size)
  137.       {
  138.           for (int row = 0; row < row_size; ++row)
  139.               for (int col = 0; col < col_size; ++col)
  140.                   myArray[row][col] = 0;
  141.  
  142.       }
  143.  
  144.       void projections()
  145.       {
  146.  
  147.           // Clear X sums
  148.           for (int col = 0; col < COLS; ++col) { this->cp[COLS] = false;}
  149.           // Clear Y sums
  150.           for (int row = 0; row < ROWS; ++row) { this->rp[ROWS] = false;}
  151.  
  152.  
  153.           // For every row and every column calculate the project and threshold
  154.           for(int rr= 0; rr<ROWS; rr++)
  155.           {
  156.               int r_sum = 0;
  157.               for(int cc=0; cc<COLS; cc++)
  158.               {
  159.  
  160.                   Color c = this->processed.get(cc,rr);
  161.                   c.r = c.r - .6*c.g - .6*c.b;
  162.                   c.r =  c.r > threshold ? maxValue : 0 ;
  163.                   c.g = 0;
  164.                   c.b = 0;
  165.  
  166.                   if (myChar == 'r'){ this->detected.set(cc,rr,c); }
  167.  
  168.                   // Running sum
  169.                   r_sum += c.r/255;
  170.  
  171.                   // Running sum the y projection
  172.                   this->cp[cc]+= c.r/255;
  173.                   this->bimage[rr][cc] = c.r ;
  174.               }
  175.               // Add the running sum to the x projection
  176.               this->rp[rr] = r_sum;
  177.           }
  178.       }
  179.  
  180.       // Adds up the values of a projection
  181.       int binning(unsigned int* toReturn, int bin_size, int length, int* projection)
  182.       {
  183.           //Clear toReturn
  184.           empty(toReturn,length);
  185.  
  186.           // Running overall maximum
  187.           int max = 0;
  188.           int average = 0;
  189.           for(int ii=0;ii<length;ii++)
  190.           {
  191.               toReturn[ii] = 0;
  192.               for(int jj=0;jj<bin_size;jj++)
  193.               {
  194.                   toReturn[ii] += projection[(ii*bin_size) + jj];
  195.  
  196.               }
  197.               average += toReturn[ii];
  198.               // max = toReturn[jj] > max ? toReturn[ii] : max ;
  199.               // Average
  200.               //toReturn[ii] /= bin_size;
  201.           }
  202.           return average/length;
  203.       }
  204.  
  205.       // Clears any arrays
  206.       template < typename T>
  207.       void empty( T * myArray, int length)
  208.       {
  209.           int ii =0 ;
  210.           while( ii < length )
  211.           {
  212.               myArray[ii++]=0;
  213.           }
  214.       }
  215.  
  216.       // Fill a single value into any array
  217.       template < typename T>
  218.       void fillArray( T * myArray, int length, int fill_value)
  219.       {
  220.           int ii =0 ;
  221.           while( ii < length )
  222.           {
  223.               myArray[ii++]= fill_value;
  224.           }
  225.       }
  226.  
  227.       // Threshold the binned values
  228.       void bound(unsigned int *bins, int length, int thresh, bool * valid)
  229.       {
  230.           empty(valid,length);
  231.           for ( int ii =0 ;  ii < length ;ii++)
  232.           {
  233.               if ( bins[ii] > thresh)
  234.               {
  235.                   valid[ii] = true ;
  236.               }
  237.               else
  238.               {  
  239.                   valid[ii] = false;
  240.               }
  241.           }
  242.       }
  243.  
  244.  
  245.       // Calculate the area
  246.       int getArea( int cc, int rr)
  247.       {
  248.           int sum = 0;
  249.           int ccMax = cc*bin_size+bin_size;
  250.           int rrMax = rr*bin_size+bin_size;
  251.           for ( int aa = cc*bin_size ;  (aa < COLS) && (aa< ccMax)  ;aa++)
  252.           {
  253.               for ( int bb = rr*bin_size ; (bb <ROWS) && (bb< rrMax) ;bb++)
  254.               {
  255.                   if ( bimage[bb][aa] )
  256.                   {
  257.                       sum++;
  258.                   }
  259.               }
  260.           }
  261.           return sum;
  262.       }
  263.  
  264.  
  265.       // Draw a box around the regions where we are above the threshold
  266.  
  267.       void box()
  268.       {
  269.           empty2D(this->bin, ROWS/bin_size, COLS/bin_size);
  270.  
  271.           for(int ii=0; ii< COLS/bin_size; ii++)
  272.           {
  273.               if ( this->xbool[ii] )
  274.               {
  275.                   for(int jj=0; jj<ROWS/bin_size; jj++ )
  276.                   {
  277.                       if( this->ybool[jj] )
  278.                       {
  279.                           // Calculate the saturation
  280.                           int area = getArea(ii,jj);
  281.                           double saturation = double (area) / double (bin_size*bin_size);
  282.  
  283.                           if ( saturation > .2 )
  284.                           {
  285.                               //flood[ii][jj] = true;
  286.                               bin[jj][ii] = true;
  287.  
  288.                               if (myChar == 'n')
  289.                               { Point p1(ii * bin_size,jj * bin_size);
  290.                               Point p2( (ii+1) * bin_size, (jj+1) * bin_size);
  291.                               cv::rectangle(detected.getImage(),p1,p2, CV_RGB(0,255,0),3);
  292.                               }
  293.                           }
  294.                           else
  295.                           {
  296.                               bin[jj][ii] = false;
  297.                           }
  298.                       }
  299.                   }
  300.               }
  301.           }
  302.       }
  303.  
  304.       // Cluster the touching points with flood fill
  305.       void cluster ()
  306.       {
  307.           empty2D(this->fFill, ROWS/bin_size, COLS/bin_size);
  308.           empty(this->areas,this->MAX_ITEMS);
  309.  
  310.           // Reset the bounding indices
  311.           fillArray(this->c_max,MAX_ITEMS, -1);
  312.           fillArray(this->r_max,MAX_ITEMS, -1);
  313.           fillArray(this->c_min,MAX_ITEMS,COLS/bin_size +1);
  314.           fillArray(this->r_min,MAX_ITEMS,ROWS/bin_size +1);
  315.  
  316.           short  index=0;
  317.           short  gCount=0;
  318.           std::map<int , short> good_values;
  319.           for (short ii=0 ; ii< COLS/bin_size; ii++ )
  320.  
  321.           {
  322.               for(short jj=0; jj<ROWS/bin_size; jj++ )
  323.               {
  324.                   // If we are max items skip
  325.                   if ( good_values.size() < MAX_ITEMS ){
  326.                       // Call flood fill and update the index if we have found a fill
  327.                       int sum = 0;
  328.                       int * psum = &sum;
  329.                       int result =  floodFill(jj,ii,index,psum);
  330.  
  331.                       // If we are large enough, start trackings
  332.                       if ( sum > MIN_MASS)
  333.                       {
  334.                           // result store
  335.                           good_values.insert( std::pair<int,short>( result,gCount++) );
  336.                       }
  337.                       // INcrement
  338.                       index++;
  339.                   }
  340.               }
  341.           }
  342.  
  343.  
  344.           index = 0;
  345.  
  346.           for (short ii=0 ; ii< COLS/bin_size; ii++ )
  347.           {
  348.               for(short jj=0; jj<ROWS/bin_size; jj++ )
  349.               {
  350.                   int gVal = good_values.count(fFill[jj][ii]);
  351.                   if( gVal )
  352.                   {
  353.  
  354.                       int item_index = good_values[ fFill[jj][ii] ];
  355.  
  356.                       if (myChar == 'b')
  357.                       {
  358.                           Point p1( ii * bin_size,jj * bin_size);
  359.                           Point p2( (ii+1) * bin_size, (jj+1) * bin_size);
  360.                           cv::rectangle(detected.getImage(),p1,p2, this->colors[ item_index ], -1);
  361.                       }
  362.  
  363.                       if (ii > c_max[item_index])
  364.                       { c_max[item_index] = ii; }  
  365.                       if (jj > r_max[item_index])
  366.                       { r_max[item_index] = jj; }  
  367.                       if (ii < c_min[item_index])
  368.                       { c_min[item_index] = ii; }  
  369.                       if (jj < r_min[item_index])
  370.                       { r_min[item_index] = jj; }  
  371.                   }
  372.                   index++;
  373.  
  374.               }
  375.           }
  376.  
  377.           for ( int ii=0 ; ii < MAX_ITEMS ; ii++)
  378.           {
  379.               if ( c_min[ii] != COLS/bin_size+1  &&  
  380.                   r_min[ii] != ROWS/bin_size+1  &&
  381.                   c_max[ii] != -1 &&
  382.                   r_max[ii] != -1
  383.                   )
  384.               {
  385.                   Point p1( c_min[ii] * bin_size, r_min[ii]  * bin_size);
  386.                   Point p2( c_max[ii] * bin_size, r_max[ii]  * bin_size);
  387.  
  388.                   cv::rectangle(detected.getImage(),p1,p2, this->colors[ ii ], 3);
  389.               }
  390.           }
  391.       }
  392.  
  393.  
  394.       // Fill
  395.       int floodFill(short rr, short cc, short index, int * sum)
  396.       {
  397.           // If out of bounds, return
  398.           if ( rr >= ROWS/bin_size || cc >= COLS/bin_size || rr < 0 || cc < 0 )
  399.           {
  400.               return index;
  401.           }
  402.           // If I am not a zero value in the bin, return
  403.           else if ( bin[rr][cc] == false )
  404.           {
  405.               return index;
  406.           }
  407.           // If I am zero, continue
  408.           else if ( fFill[rr][cc] == 0 )
  409.           {
  410.               fFill[rr][cc] = index+1;
  411.               // Increment the mass count
  412.               (*sum)++;
  413.  
  414.               floodFill(rr+1,cc,index,sum);
  415.               floodFill(rr-1,cc,index,sum);
  416.               floodFill(rr,cc+1,index,sum);
  417.               floodFill(rr,cc-1,index,sum);
  418.  
  419.               return index+1;
  420.           }
  421.           else
  422.           {
  423.               return index;
  424.           }
  425.  
  426.       }
  427.  
  428.       //double getFilter()
  429.       //{
  430.       //    if (myChar == ']')
  431.       //    {
  432.       //        filter += filter >= 1 ? 0 : 0.1 ;
  433.       //        std::cout << filter;
  434.       //    }
  435.       //    if (myChar == '[')
  436.       //    {
  437.       //        filter -= filter <= 0 ? 0 : 0.1 ;
  438.       //        std::cout << filter;
  439.       //    }
  440.       //    return filter;
  441.       //}
  442.  
  443.       bool doWork(Mat& frame)
  444.       {
  445.           // Preprocessed Blurring step
  446.           Mat blurred ,blurred2, blurred3;
  447.           // cv::GaussianBlur(frame , blurred , cv::Size(7,7),1.5);
  448.           int erosion_elem = 0;
  449.           int erosion_size = 0;
  450.           int dilation_elem = 0;
  451.           int dilation_size = 0;
  452.           int const max_elem = 2;
  453.           int const max_kernel_size = 21;
  454.           int erosion_type;
  455.           if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
  456.           else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
  457.           else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
  458.           Mat element = getStructuringElement( erosion_type,
  459.               Size( 2*erosion_size + 1, 2*erosion_size+1 ),
  460.               Point( erosion_size, erosion_size ) );
  461.  
  462.           /// Apply the erosion operation
  463.           erode( frame, blurred2, element );
  464.           dilate(blurred2, blurred3, element);
  465.           cv::blur(blurred3 , blurred , cv::Size(9,9)) ;
  466.           processed(blurred);
  467.           detected(blurred);
  468.  
  469.           // Calculate Projections
  470.           projections();
  471.  
  472.           // Calculate the bins and bounds
  473.           int xmax  = binning( this->xbins , bin_size, this->COLS/bin_size, this->cp );
  474.           int ymax  = binning( this->ybins , bin_size, this->ROWS/bin_size, this->rp );
  475.  
  476.           bound ( this->xbins , COLS/bin_size, xmax  * filter, this->xbool );
  477.           bound ( this->ybins , ROWS/bin_size, ymax * filter , this->ybool );
  478.  
  479.           box();
  480.           cluster();
  481.  
  482.           imshow("detected", detected.getImage());
  483.           cvWaitKey(40);
  484.  
  485.           return true;
  486.       }
  487.  
  488.  
  489.  
  490.       void project(bool xdirection, Image* image, int rows, int cols, int* toReturn)
  491.       {
  492.           int total = 0;
  493.           double average;
  494.           if(!xdirection)
  495.           {
  496.               for (int ii = 0; ii<rows; ii++)
  497.               {
  498.                   toReturn[ii] = 0;
  499.                   for(int jj=0; jj<cols; jj++)
  500.                   {
  501.                       toReturn[ii] += ((image->getR(jj,ii))/255);
  502.                       total += toReturn[ii];
  503.                   }
  504.               }
  505.           }
  506.           else
  507.           {
  508.               for (int ii = 0; ii<cols; ii++)
  509.               {
  510.                   toReturn[ii] = 0;
  511.                   for(int jj=0; jj<rows; jj++)
  512.                   {
  513.                       toReturn[ii] += ((image->getR(ii,jj))/255);
  514.                       int current = toReturn[ii];
  515.                       total += toReturn[ii];
  516.                   }
  517.               }
  518.           }
  519.           average = total/(rows*cols);
  520.           int length = cols;
  521.           if(!xdirection){length = rows;}
  522.           for (int ii=0;ii<length; ii++)
  523.           {
  524.               toReturn[ii] -= average;
  525.               if (toReturn[ii] < 0)
  526.               {
  527.                   toReturn[ii] = 0;
  528.               }
  529.           }
  530.       }
  531.  
  532.       void setKey(char c)
  533.       {
  534.           myChar = c;
  535.       }
  536.  
  537.       Image processed;
  538.       Image detected;
  539.  
  540.       // X and Y Projection vectors
  541.       int * rp;
  542.       int * cp;
  543.  
  544.       // Bins
  545.       unsigned int * ybins;
  546.       unsigned int * xbins;
  547.       // Binary image
  548. public: bool** bimage;
  549.         bool** bin;
  550.         char myChar;
  551.         short** fFill;
  552.  
  553.         // Row and column sizes
  554.         int ROWS;
  555.         int COLS;
  556.  
  557.         bool * xbool;
  558.         bool * ybool;
  559.  
  560.         // Members for the threshold and maxValue
  561.         int threshold;
  562.         int maxValue;
  563.         int bin_size ;
  564.         int MAX_ITEMS;
  565.         int MIN_MASS;
  566.  
  567.         // A vector to keep track of the area of each mass
  568.         int  * areas;
  569.  
  570.         // Color Array
  571.         vector<cv::Scalar> colors;
  572.  
  573.         double filter;
  574.  
  575.         // Arrays for bounds
  576.         short *c_max;
  577.         short *r_max;
  578.         short *c_min;
  579.         short *r_min;
  580.  
  581. };
  582.  
  583. #endif
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top