Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef _CS440P0_H
- #define _CS440P0_H
- #include <cv.h>
- #include "Image.h"
- #include <vector>
- #include <cstdlib>
- #include <utility>
- #include <iostream>
- #include <map>
- #include <algorithm>
- class CS440P0
- {
- public:
- CS440P0():
- myChar(0)
- {
- //make a new window where we can show our processed results
- namedWindow("detected",1);
- }
- CS440P0(Mat& frame):
- myChar(0)
- {
- //make a new window where we can show our processed results
- namedWindow("detected",1);
- // release params = 4,10,255,3
- this->bin_size = 4;
- this->threshold = 10;
- this->maxValue = 255;
- this->MAX_ITEMS = 15;
- this->MIN_MASS = 600/ (bin_size *bin_size);
- this->filter = 0.1;
- // Get the cols and row values
- this->ROWS = frame.rows;
- this->COLS = frame.cols;
- // Initialize the boolean image array
- this->bimage = new bool*[ROWS];
- for (int row = 0; row < ROWS; ++row)
- bimage[row] = new bool[COLS];
- for (int row = 0; row < ROWS; ++row)
- for (int col = 0; col < COLS; ++col)
- bimage[row][col] = false;
- // Initialize the x and y projection vectors;
- this->rp = new int[ROWS]; //proj along x
- this->cp = new int[COLS]; //proj along y
- for (int row = 0; row < ROWS; ++row) { this->rp[row] =0;}
- for (int col = 0; col < COLS; ++col) { this->cp[col] =0;}
- // Initialize the x and y bin vectors;
- this->xbins = new unsigned int[COLS]; //bin along x
- this->ybins = new unsigned int[ROWS]; //bin along y
- for (int row = 0; row < ROWS; ++row) { this->ybins[row] =0;}
- for (int col = 0; col < COLS; ++col) { this->xbins[col] =0;}
- // Initialize the x and y boolean vectors;
- this->xbool = new bool [COLS/bin_size];
- this->ybool = new bool [ROWS/bin_size];
- // Initialize the flood fill array
- this->bin = new bool*[ROWS/bin_size];
- for (int row = 0; row < ROWS/bin_size; ++row)
- this->bin[row] = new bool[COLS/bin_size];
- for (int row = 0; row < ROWS/bin_size; ++row)
- for (int col = 0; col < COLS/bin_size; ++col)
- this->bin[row][col] = false;
- // Initialize the flood fill array
- this->fFill = new short*[ROWS/bin_size];
- for (int row = 0; row < ROWS/bin_size; ++row)
- this->fFill[row] = new short[COLS/bin_size];
- for (int row = 0; row < ROWS/bin_size; ++row)
- for (int col = 0; col < COLS/bin_size; ++col)
- this->fFill[row][col] = 0;
- // Initialize a new vector
- this->areas = new int[MAX_ITEMS] ;
- for (int ii = 0; ii < MAX_ITEMS; ++ii)
- {
- areas[ii]=0;
- }
- // Make color chart
- //this->colors = new cv::Scalar [];
- int ii = 0; {}
- this->colors.push_back(CV_RGB( 160,32 ,240));
- this->colors.push_back(CV_RGB( 0 ,0 ,128));
- this->colors.push_back(CV_RGB( 124,252,0)) ;
- this->colors.push_back(CV_RGB( 200,0,0 ));
- this->colors.push_back(CV_RGB( 255,255,0));
- this->colors.push_back(CV_RGB( 255,165,0));
- this->colors.push_back(CV_RGB( 255,105,180));
- this->colors.push_back(CV_RGB( 0,0,0));
- this->colors.push_back(CV_RGB( 255,255,255)) ;
- this->colors.push_back(CV_RGB( 85,107,47));
- this->colors.push_back(CV_RGB( 127,255,0));
- this->colors.push_back(CV_RGB( 190,190,190));
- this->colors.push_back(CV_RGB( 0,255,255));
- this->colors.push_back(CV_RGB( 140,255,255));
- this->colors.push_back(CV_RGB( 205,175,149));
- this->colors.push_back(CV_RGB( 255,105,80));
- this->colors.push_back(CV_RGB( 60,179,113));
- this->colors.push_back(CV_RGB( 46,139,87));
- this->colors.push_back(CV_RGB( 240,230,140));
- this->colors.push_back(CV_RGB( 188,143,143));
- this->colors.push_back(CV_RGB( 255,255,0));
- // Min Max bounds
- this->c_min = new short[MAX_ITEMS] ;
- this->r_min = new short[MAX_ITEMS] ;
- this->c_max = new short[MAX_ITEMS] ;
- this->r_max = new short[MAX_ITEMS] ;
- for (int ii = 0; ii < MAX_ITEMS; ++ii) c_min[ii] = COLS/bin_size ;
- for (int ii = 0; ii < MAX_ITEMS; ++ii) c_max[ii] = 0;
- for (int ii = 0; ii < MAX_ITEMS; ++ii) r_min[ii] = ROWS/bin_size;
- for (int ii = 0; ii < MAX_ITEMS; ++ii) r_max[ii] = 0;
- }
- template < typename T>
- void empty2D( T* myArray, int row_size, int col_size)
- {
- for (int row = 0; row < row_size; ++row)
- for (int col = 0; col < col_size; ++col)
- myArray[row][col] = 0;
- }
- void projections()
- {
- // Clear X sums
- for (int col = 0; col < COLS; ++col) { this->cp[COLS] = false;}
- // Clear Y sums
- for (int row = 0; row < ROWS; ++row) { this->rp[ROWS] = false;}
- // For every row and every column calculate the project and threshold
- for(int rr= 0; rr<ROWS; rr++)
- {
- int r_sum = 0;
- for(int cc=0; cc<COLS; cc++)
- {
- Color c = this->processed.get(cc,rr);
- c.r = c.r - .6*c.g - .6*c.b;
- c.r = c.r > threshold ? maxValue : 0 ;
- c.g = 0;
- c.b = 0;
- if (myChar == 'r'){ this->detected.set(cc,rr,c); }
- // Running sum
- r_sum += c.r/255;
- // Running sum the y projection
- this->cp[cc]+= c.r/255;
- this->bimage[rr][cc] = c.r ;
- }
- // Add the running sum to the x projection
- this->rp[rr] = r_sum;
- }
- }
- // Adds up the values of a projection
- int binning(unsigned int* toReturn, int bin_size, int length, int* projection)
- {
- //Clear toReturn
- empty(toReturn,length);
- // Running overall maximum
- int max = 0;
- int average = 0;
- for(int ii=0;ii<length;ii++)
- {
- toReturn[ii] = 0;
- for(int jj=0;jj<bin_size;jj++)
- {
- toReturn[ii] += projection[(ii*bin_size) + jj];
- }
- average += toReturn[ii];
- // max = toReturn[jj] > max ? toReturn[ii] : max ;
- // Average
- //toReturn[ii] /= bin_size;
- }
- return average/length;
- }
- // Clears any arrays
- template < typename T>
- void empty( T * myArray, int length)
- {
- int ii =0 ;
- while( ii < length )
- {
- myArray[ii++]=0;
- }
- }
- // Fill a single value into any array
- template < typename T>
- void fillArray( T * myArray, int length, int fill_value)
- {
- int ii =0 ;
- while( ii < length )
- {
- myArray[ii++]= fill_value;
- }
- }
- // Threshold the binned values
- void bound(unsigned int *bins, int length, int thresh, bool * valid)
- {
- empty(valid,length);
- for ( int ii =0 ; ii < length ;ii++)
- {
- if ( bins[ii] > thresh)
- {
- valid[ii] = true ;
- }
- else
- {
- valid[ii] = false;
- }
- }
- }
- // Calculate the area
- int getArea( int cc, int rr)
- {
- int sum = 0;
- int ccMax = cc*bin_size+bin_size;
- int rrMax = rr*bin_size+bin_size;
- for ( int aa = cc*bin_size ; (aa < COLS) && (aa< ccMax) ;aa++)
- {
- for ( int bb = rr*bin_size ; (bb <ROWS) && (bb< rrMax) ;bb++)
- {
- if ( bimage[bb][aa] )
- {
- sum++;
- }
- }
- }
- return sum;
- }
- // Draw a box around the regions where we are above the threshold
- void box()
- {
- empty2D(this->bin, ROWS/bin_size, COLS/bin_size);
- for(int ii=0; ii< COLS/bin_size; ii++)
- {
- if ( this->xbool[ii] )
- {
- for(int jj=0; jj<ROWS/bin_size; jj++ )
- {
- if( this->ybool[jj] )
- {
- // Calculate the saturation
- int area = getArea(ii,jj);
- double saturation = double (area) / double (bin_size*bin_size);
- if ( saturation > .2 )
- {
- //flood[ii][jj] = true;
- bin[jj][ii] = true;
- if (myChar == 'n')
- { Point p1(ii * bin_size,jj * bin_size);
- Point p2( (ii+1) * bin_size, (jj+1) * bin_size);
- cv::rectangle(detected.getImage(),p1,p2, CV_RGB(0,255,0),3);
- }
- }
- else
- {
- bin[jj][ii] = false;
- }
- }
- }
- }
- }
- }
- // Cluster the touching points with flood fill
- void cluster ()
- {
- empty2D(this->fFill, ROWS/bin_size, COLS/bin_size);
- empty(this->areas,this->MAX_ITEMS);
- // Reset the bounding indices
- fillArray(this->c_max,MAX_ITEMS, -1);
- fillArray(this->r_max,MAX_ITEMS, -1);
- fillArray(this->c_min,MAX_ITEMS,COLS/bin_size +1);
- fillArray(this->r_min,MAX_ITEMS,ROWS/bin_size +1);
- short index=0;
- short gCount=0;
- std::map<int , short> good_values;
- for (short ii=0 ; ii< COLS/bin_size; ii++ )
- {
- for(short jj=0; jj<ROWS/bin_size; jj++ )
- {
- // If we are max items skip
- if ( good_values.size() < MAX_ITEMS ){
- // Call flood fill and update the index if we have found a fill
- int sum = 0;
- int * psum = ∑
- int result = floodFill(jj,ii,index,psum);
- // If we are large enough, start trackings
- if ( sum > MIN_MASS)
- {
- // result store
- good_values.insert( std::pair<int,short>( result,gCount++) );
- }
- // INcrement
- index++;
- }
- }
- }
- index = 0;
- for (short ii=0 ; ii< COLS/bin_size; ii++ )
- {
- for(short jj=0; jj<ROWS/bin_size; jj++ )
- {
- int gVal = good_values.count(fFill[jj][ii]);
- if( gVal )
- {
- int item_index = good_values[ fFill[jj][ii] ];
- if (myChar == 'b')
- {
- Point p1( ii * bin_size,jj * bin_size);
- Point p2( (ii+1) * bin_size, (jj+1) * bin_size);
- cv::rectangle(detected.getImage(),p1,p2, this->colors[ item_index ], -1);
- }
- if (ii > c_max[item_index])
- { c_max[item_index] = ii; }
- if (jj > r_max[item_index])
- { r_max[item_index] = jj; }
- if (ii < c_min[item_index])
- { c_min[item_index] = ii; }
- if (jj < r_min[item_index])
- { r_min[item_index] = jj; }
- }
- index++;
- }
- }
- for ( int ii=0 ; ii < MAX_ITEMS ; ii++)
- {
- if ( c_min[ii] != COLS/bin_size+1 &&
- r_min[ii] != ROWS/bin_size+1 &&
- c_max[ii] != -1 &&
- r_max[ii] != -1
- )
- {
- Point p1( c_min[ii] * bin_size, r_min[ii] * bin_size);
- Point p2( c_max[ii] * bin_size, r_max[ii] * bin_size);
- cv::rectangle(detected.getImage(),p1,p2, this->colors[ ii ], 3);
- }
- }
- }
- // Fill
- int floodFill(short rr, short cc, short index, int * sum)
- {
- // If out of bounds, return
- if ( rr >= ROWS/bin_size || cc >= COLS/bin_size || rr < 0 || cc < 0 )
- {
- return index;
- }
- // If I am not a zero value in the bin, return
- else if ( bin[rr][cc] == false )
- {
- return index;
- }
- // If I am zero, continue
- else if ( fFill[rr][cc] == 0 )
- {
- fFill[rr][cc] = index+1;
- // Increment the mass count
- (*sum)++;
- floodFill(rr+1,cc,index,sum);
- floodFill(rr-1,cc,index,sum);
- floodFill(rr,cc+1,index,sum);
- floodFill(rr,cc-1,index,sum);
- return index+1;
- }
- else
- {
- return index;
- }
- }
- //double getFilter()
- //{
- // if (myChar == ']')
- // {
- // filter += filter >= 1 ? 0 : 0.1 ;
- // std::cout << filter;
- // }
- // if (myChar == '[')
- // {
- // filter -= filter <= 0 ? 0 : 0.1 ;
- // std::cout << filter;
- // }
- // return filter;
- //}
- bool doWork(Mat& frame)
- {
- // Preprocessed Blurring step
- Mat blurred ,blurred2, blurred3;
- // cv::GaussianBlur(frame , blurred , cv::Size(7,7),1.5);
- int erosion_elem = 0;
- int erosion_size = 0;
- int dilation_elem = 0;
- int dilation_size = 0;
- int const max_elem = 2;
- int const max_kernel_size = 21;
- int erosion_type;
- if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
- else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
- else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
- Mat element = getStructuringElement( erosion_type,
- Size( 2*erosion_size + 1, 2*erosion_size+1 ),
- Point( erosion_size, erosion_size ) );
- /// Apply the erosion operation
- erode( frame, blurred2, element );
- dilate(blurred2, blurred3, element);
- cv::blur(blurred3 , blurred , cv::Size(9,9)) ;
- processed(blurred);
- detected(blurred);
- // Calculate Projections
- projections();
- // Calculate the bins and bounds
- int xmax = binning( this->xbins , bin_size, this->COLS/bin_size, this->cp );
- int ymax = binning( this->ybins , bin_size, this->ROWS/bin_size, this->rp );
- bound ( this->xbins , COLS/bin_size, xmax * filter, this->xbool );
- bound ( this->ybins , ROWS/bin_size, ymax * filter , this->ybool );
- box();
- cluster();
- imshow("detected", detected.getImage());
- cvWaitKey(40);
- return true;
- }
- void project(bool xdirection, Image* image, int rows, int cols, int* toReturn)
- {
- int total = 0;
- double average;
- if(!xdirection)
- {
- for (int ii = 0; ii<rows; ii++)
- {
- toReturn[ii] = 0;
- for(int jj=0; jj<cols; jj++)
- {
- toReturn[ii] += ((image->getR(jj,ii))/255);
- total += toReturn[ii];
- }
- }
- }
- else
- {
- for (int ii = 0; ii<cols; ii++)
- {
- toReturn[ii] = 0;
- for(int jj=0; jj<rows; jj++)
- {
- toReturn[ii] += ((image->getR(ii,jj))/255);
- int current = toReturn[ii];
- total += toReturn[ii];
- }
- }
- }
- average = total/(rows*cols);
- int length = cols;
- if(!xdirection){length = rows;}
- for (int ii=0;ii<length; ii++)
- {
- toReturn[ii] -= average;
- if (toReturn[ii] < 0)
- {
- toReturn[ii] = 0;
- }
- }
- }
- void setKey(char c)
- {
- myChar = c;
- }
- Image processed;
- Image detected;
- // X and Y Projection vectors
- int * rp;
- int * cp;
- // Bins
- unsigned int * ybins;
- unsigned int * xbins;
- // Binary image
- public: bool** bimage;
- bool** bin;
- char myChar;
- short** fFill;
- // Row and column sizes
- int ROWS;
- int COLS;
- bool * xbool;
- bool * ybool;
- // Members for the threshold and maxValue
- int threshold;
- int maxValue;
- int bin_size ;
- int MAX_ITEMS;
- int MIN_MASS;
- // A vector to keep track of the area of each mass
- int * areas;
- // Color Array
- vector<cv::Scalar> colors;
- double filter;
- // Arrays for bounds
- short *c_max;
- short *r_max;
- short *c_min;
- short *r_min;
- };
- #endif
Add Comment
Please, Sign In to add comment