MichaelYoung

Part 2: Classifying characters

Jan 12th, 2013
3,855
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. ayoungprogrammer.blogspot.com
  3.  
  4. Part 2: Training: Classifying characters
  5. */
  6.  
  7. #include <iostream>
  8.  #include <Windows.h>
  9.  
  10. #ifdef _CH_
  11. #pragma package <opencv>
  12. #endif
  13.  
  14. #ifndef _EiC
  15. #include "cv.h"
  16. #include "highgui.h"
  17. #include "ml.h"
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21. #endif
  22.  
  23. using namespace std;
  24. using namespace cv;
  25.  
  26.  
  27. bool createDir(const std::string& dirName_in)
  28. {
  29.   if (CreateDirectory(dirName_in.c_str(), NULL)){
  30.     return true;
  31.   }else return false;
  32. }
  33.  
  34. int numOfFiles(char* searchPath)
  35. {
  36.     WIN32_FIND_DATA FindData;
  37.     HANDLE      hFiles;
  38.     LPTSTR      lptszFiles[100];
  39.     UINT        nFileCount = 0;
  40.  
  41.     hFiles = FindFirstFile(searchPath, &FindData);
  42.    
  43.     if (hFiles == INVALID_HANDLE_VALUE)
  44.         return 0;
  45.  
  46.     bool bFinished = false;
  47.     while(!bFinished){
  48.         if(!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
  49.             nFileCount++;
  50.         }
  51.  
  52.         if(!FindNextFile(hFiles, &FindData)){
  53.             bFinished = true;
  54.         }
  55.     }
  56.     FindClose(hFiles);
  57.     return nFileCount;
  58. }
  59.  
  60.  
  61.  
  62. class comparator{
  63. public:
  64.     bool operator()(vector<Point> c1,vector<Point>c2){
  65.        
  66.         return boundingRect( Mat(c1)).x<boundingRect( Mat(c2)).x;
  67.  
  68.     }
  69.  
  70. };
  71.  
  72.  
  73. void extractContours(Mat& image,vector< vector<Point> > contours_poly){
  74.  
  75.     vector<Mat> extracted;
  76.  
  77.     sort(contours_poly.begin(),contours_poly.end(),comparator());
  78.  
  79.  
  80.     char curDir[256];
  81.     GetCurrentDirectory(256,curDir);
  82.  
  83.     stringstream fileOutput;
  84.     fileOutput<<curDir<<"\\output\\";
  85.  
  86.     createDir("output");
  87.  
  88.  
  89.  
  90.    
  91.  
  92.     //Loop through all contours to extract
  93.          for( int i = 0; i< contours_poly.size(); i++ ){
  94.  
  95.             Rect r = boundingRect( Mat(contours_poly[i]) );
  96.            
  97.            
  98.             Mat mask = Mat::zeros(image.size(), CV_8UC1);
  99.             //Draw mask
  100.             drawContours(mask, contours_poly, i, Scalar(255), CV_FILLED);
  101.  
  102.             //Check for equal sign (2 dashes on top of each other) and merge
  103.             if(i+1<contours_poly.size()){
  104.                 Rect r2 = boundingRect( Mat(contours_poly[i+1]) );
  105.                 //Shape on top of another shape
  106.                 if(abs(r2.x-r.x)<20){
  107.                     drawContours(mask, contours_poly, i+1, Scalar(255), CV_FILLED);
  108.                     i++;
  109.                     int minX = min(r.x,r2.x);
  110.                     int minY = min(r.y,r2.y);
  111.                     int maxX =  max(r.x+r.width,r2.x+r2.width);
  112.                     int maxY = max(r.y+r.height,r2.y+r2.height);
  113.                     r = Rect(minX,minY,maxX - minX,maxY-minY);
  114.  
  115.                     //Ignore equal signs
  116.                     if((double)r.width/r.height>3.0){
  117.                         continue;
  118.                     }
  119.  
  120.                 }
  121.             }
  122.            
  123.             //Ignore dashes
  124.             if((double)r.width/r.height>3.0){
  125.                
  126.                
  127.                 continue;
  128.  
  129.             }
  130.            
  131.  
  132.             //Extract shape from mask
  133.              Mat extractPic;
  134.              image.copyTo(extractPic,mask);
  135.              Mat resizedPic = extractPic(r);//extractPic(cv::Range(r.x, r.y), cv::Range(r.x+r.width, r.y+r.height));
  136.    
  137.             cv::Mat image=resizedPic.clone();
  138.             imshow("image",image);
  139.             char ch  = waitKey(0);
  140.  
  141.             stringstream outputFile;
  142.             outputFile<<fileOutput.str()<<ch;
  143.            
  144.             createDir(outputFile.str());
  145.            
  146.             //Search for jpgs
  147.             stringstream searchMask;
  148.             searchMask<<outputFile.str()<<"\\*.jpg";
  149.  
  150.             //Write to file
  151.             int n = numOfFiles((char*)searchMask.str().c_str());
  152.             outputFile<<"\\"<<n<<".jpg";
  153.             imwrite(outputFile.str(),resizedPic);
  154.  
  155.  
  156.          }
  157.  
  158.  
  159.  
  160. }
  161.  
  162. void getContours(const char* filename)
  163. {
  164.   cv::Mat img = cv::imread(filename, 0);
  165.  
  166.  
  167.   //Apply blur to smooth edges and use adapative thresholding
  168.    cv::Size size(3,3);
  169.   cv::GaussianBlur(img,img,size,0);
  170.    adaptiveThreshold(img, img,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,75,10);
  171.   cv::bitwise_not(img, img);
  172.  
  173.  
  174.   cv::Mat img2 = img.clone();
  175.  
  176.   //Rotate the points from calculated angle
  177.   std::vector<cv::Point> points;
  178.   cv::Mat_<uchar>::iterator it = img.begin<uchar>();
  179.   cv::Mat_<uchar>::iterator end = img.end<uchar>();
  180.   for (; it != end; ++it)
  181.     if (*it)
  182.       points.push_back(it.pos());
  183.  
  184.  
  185.   cv::Point2f vertices[4];
  186.  
  187.   cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));
  188.    double angle = box.angle;
  189.   if (angle < -45.)
  190.     angle += 90.;
  191.  
  192.    box.points(vertices);
  193.   for(int i = 0; i < 4; ++i)
  194.     cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(255, 0, 0), 1, CV_AA);
  195.  
  196.  
  197.  
  198.    cv::Mat rot_mat = cv::getRotationMatrix2D(box.center, angle, 1);
  199.  
  200.    cv::Mat rotated;
  201.   cv::warpAffine(img2, rotated, rot_mat, img.size(), cv::INTER_CUBIC);
  202.  
  203.    
  204.  
  205.   cv::Size box_size = box.size;
  206.   if (box.angle < -45.)
  207.     std::swap(box_size.width, box_size.height);
  208.   cv::Mat cropped;
  209.  
  210.   cv::getRectSubPix(rotated, box_size, box.center, cropped);
  211.   cv::imshow("Cropped", cropped);
  212.    
  213.     Mat cropped2=cropped.clone();
  214. cvtColor(cropped2,cropped2,CV_GRAY2RGB);
  215.  
  216. Mat cropped3 = cropped.clone();
  217. cvtColor(cropped3,cropped3,CV_GRAY2RGB);
  218.  
  219.  vector<vector<Point> > contours;
  220.   vector<Vec4i> hierarchy;
  221.  
  222.   /// Find contours
  223.   cv:: findContours( cropped, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS, Point(0, 0) );
  224.  
  225.  
  226.  
  227.   /// Approximate contours to polygons + get bounding rects and circles
  228.   vector<vector<Point> > contours_poly( contours.size() );
  229.   vector<Rect> boundRect( contours.size() );
  230.   vector<Point2f>center( contours.size() );
  231.   vector<float>radius( contours.size() );
  232.  
  233.  
  234.   //Get poly contours
  235.     for( int i = 0; i < contours.size(); i++ ) {
  236.          approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
  237.      }
  238.  
  239.  
  240.   //Get only important contours, merge contours that are within another
  241.  
  242.   vector<vector<Point> > validContours;
  243.     for (int i=0;i<contours_poly.size();i++){
  244.        
  245.         Rect r = boundingRect(Mat(contours_poly[i]));
  246.         if(r.area()<100)continue;
  247.         bool inside = false;
  248.         for(int j=0;j<contours_poly.size();j++){
  249.             if(j==i)continue;
  250.            
  251.             Rect r2 = boundingRect(Mat(contours_poly[j]));
  252.             if(r2.area()<100||r2.area()<r.area())continue;
  253.             if(r.x>r2.x&&r.x+r.width<r2.x+r2.width&&
  254.                 r.y>r2.y&&r.y+r.height<r2.y+r2.height){
  255.  
  256.                 inside = true;
  257.             }
  258.         }
  259.         if(inside)continue;
  260.         validContours.push_back(contours_poly[i]);
  261.     }
  262.  
  263.  
  264. //Get bounding rects
  265.     for(int i=0;i<validContours.size();i++){
  266.         boundRect[i] = boundingRect( Mat(validContours[i]) );
  267.     }
  268.  
  269.  
  270. //Display
  271.   Scalar color = Scalar(0,255,0);
  272.   for( int i = 0; i< validContours.size(); i++ )
  273.      {
  274.         if(boundRect[i].area()<100)continue;
  275.       drawContours( cropped2, validContours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
  276.        rectangle( cropped2, boundRect[i].tl(), boundRect[i].br(),color, 2, 8, 0 );
  277.      }
  278.   extractContours(cropped3,validContours);
  279.  
  280. cv::waitKey(0);
  281.  
  282. }
  283.  
  284.  
  285.  
  286.  
  287. int main(void){
  288.  
  289. char fileName[256];
  290. cin>>fileName;
  291. getContours(fileName);
  292.  
  293. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×