Guest User

Untitled

a guest
Jun 13th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.33 KB | None | 0 0
  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
Add Comment
Please, Sign In to add comment