2013-02-22 43 views
2

我寫了一個數字OCR爲IOS。 我有兩個數字5和4 我找到輪廓測試圖像PNG文件。如何在tesseract上傳輸輪廓?的iOS +正方體OCR + OpenCV的

初始化的Tesseract:

tess = new tesseract::TessBaseAPI(); 
    tess->Init([dataPath cStringUsingEncoding:NSUTF8StringEncoding], "eng"); 
    tess->SetPageSegMode(tesseract::PSM_SINGLE_CHAR); //<-- !!!! 
    tess->tesseract::TessBaseAPI::SetVariable("tessedit_char_whitelist", ""); 

功能用於檢測輪廓:

- (std::vector<std::vector<cv::Point> >)findSquaresInImage:(cv::Mat)_image { 
std::vector<std::vector<cv::Point> > squares; 
cv::Mat pyr, timg, gray0(_image.size(), CV_8U), gray; 
int thresh = 50, N = 11; 
cv::pyrDown(_image, pyr, cv::Size(_image.cols/2, _image.rows/2)); 
cv::pyrUp(pyr, timg, _image.size()); 
std::vector<std::vector<cv::Point> > contours; 
    int ch[] = {0, 0}; 
    mixChannels(&timg, 1, &gray0, 1, ch, 1); 
    for(int l = 0; l < N; l++) { 
     if(l == 0) { 
      cv::Canny(gray0, gray, 0, thresh, 5); 
      cv::dilate(gray, gray, cv::Mat(), cv::Point(-1,-1)); 
     } 
     else { 
      gray = gray0 >= (l+1)*255/N; 
     } 
     cv::findContours(gray, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 
     std::vector<cv::Point> approx; 

     CvRect rec1; 
     std::string str; 
     std::map<int,IplImage*> pic_list; 

     for(size_t i = 0; i < contours.size(); i++) 
     { 

      rec1 = cv::boundingRect(contours[i]); 

      if (rec1.height > 0.5*gray.rows && rec1.width < 0.756*gray.cols) { 
       NSLog(@"%d %d %d %d", rec1.width, rec1.height, rec1.x, rec1.y); 
       cv::approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true); 
       squares.push_back(approx); 
      } 
     } 
    } 

return squares; } 

對於平局輪廓功能:

- (IBAction)onMath:(id)sender { 
    UIImage *image = [UIImage imageNamed:@"test1.png"]; 

    cv::Mat iMat = [self cvMatFromUIImage:image]; 
    std::vector<std::vector<cv::Point> > sq = [self findSquaresInImage:iMat]; 
    cv::Mat hui = debugSquares(sq, iMat); 

    image = [self UIImageFromCVMat:hui]; 
    self.imView.image = image; 
} 
012:

cv::Mat debugSquares(std::vector<std::vector<cv::Point> > squares, cv::Mat image) { 
for (int i = 0; i< squares.size(); i++) { 
    // draw contour 
    cv::drawContours(image, squares, i, cv::Scalar(255,0,0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point()); 

    // draw bounding rect 
    cv::Rect rect = boundingRect(cv::Mat(squares[i])); 
    cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0,255,0), 2, 8, 0); 

    // draw rotated rect 
    cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i])); 
    cv::Point2f rect_points[4]; 
    minRect.points(rect_points); 
    for (int j = 0; j < 4; j++) { 
     cv::line(image, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,0,255), 1, 8); // blue 
    } 
} 

return image; 
} 

的BTN Click方法

圖像後:

鏈接到項目在GitHub上:https://github.com/MaxPatsy/iORC

+0

您可以使用SetImage,然後使用SetRectangle和輪廓邊界框;你知道如何給tesseract一個它可以讀取的圖像嗎? – 2013-05-18 01:01:21

+0

你能更新你的問題嗎?在Internet Archive上,github用戶/項目被刪除,沒有任何痕跡。我能找到的最佳相關鏈接是http://www.cyberforum.ru/ios-dev/thread788840.html – 2017-06-15 05:31:22

回答

0

你可以檢查這個答案here

我描述了一些技巧,這裏準備圖像爲正方體:使用超正方體識別車牌

在你的榜樣,有幾件事情怎麼回事...

你需要獲取文本是黑色和白色圖像(而不是相反)的其餘部分。這就是字符識別所關注的。灰度是好的,只要背景大部分是全白的,文本大部分是全黑的;文本的邊緣可能是灰色的(反鋸齒),這可能有助於識別(但不一定 - 您必須嘗試)

您看到的一個問題是,在圖像的某些部分,文字是真正的「薄」(在字母的差距顯示閾值處理後),而在其他地方真的很「厚」(和字母開始合併)。正方體不會喜歡:)這是因爲輸入圖像不均勻的光線,所以單一的門檻不工作無處不在。解決方案是做「局部自適應閾值」,其中爲圖像的每個鄰域計算不同的閾值。有這樣做的方法很多,但檢查出來,例如:

自適應高斯閾值在OpenCV中與cv2.adaptiveThreshold(...,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,...) 局部大津算法 本地自適應直方圖均衡 你有另一個問題是線條不直。根據我的經驗,Tesseract可以處理非直線的非常有限的程度(透視失真,傾斜或傾斜的幾個百分比),但它不適用于波浪線。如果可以的話,確保源圖像有直線:)不幸的是,現在沒有簡單的現成答案。您必須查看研究文獻並自行實施最先進的算法之一(如果可能的話,開放源代碼 - 真正需要開源解決方案)。一個谷歌學術搜索「曲線OCR提取」將讓你開始,例如:彎曲的文檔圖像 最後的

文本行分割:我想你會做的更好使用Python生態系統的工作(ndimage,skimage )比在C++中的OpenCV。OpenCV python包裝對於簡單的東西是可以的,但是對於你想要做的事情他們不會做這項工作,你需要抓住很多不在OpenCV中的東西(當然你可以混合搭配)。在C++中執行類似曲線檢測的操作將比Python中的要長一個數量級(*即使您不知道python,也是如此)。

祝你好運!