2

iOS用のデジタルOCRを書きました。5と4の2桁のテスト画像pngがあります。輪郭を見つけます。tesseractで輪郭を転送するにはどうすればよいですか?

初期テッセラクト:

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

輪郭を検出する関数:

- (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;  }

輪郭を描く関数:

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;
}

ボタンクリックの方法:

- (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;
}

後の画像:

github のプロジェクトへのリンク: https://github.com/MaxPatsy/iORC

4

1 に答える 1

0

ここでこの回答を確認できますか

ここで、Tesseract 用の画像を準備するためのヒントをいくつか説明しました。Tesseract を使用してナンバー プレートを認識する

あなたの例では、いくつかのことが起こっています...

テキストを黒く、画像の残りの部分を白くする必要があります (逆ではありません)。それが、文字認識がオンになっているものです。背景がほとんど完全に白で、テキストがほとんど完全に黒である限り、グレースケールは問題ありません。テキストの端が灰色 (アンチエイリアス処理) になっている場合があり、それが認識に役立つ場合があります (必ずしもそうとは限りません - 実験する必要があります)。

表示されている問題の 1 つは、画像の一部のテキストが非常に「薄い」(しきい値処理後に文字のギャップが表示される) のに対し、他の部分では実際に「厚い」(文字が開始されている) ことです。合併)。Tesseract はそれを好まないでしょう :) これは、入力画像が均一に照らされていないために発生するため、単一のしきい値がどこでも機能するわけではありません。解決策は、画像の各近傍に対して異なるしきい値が計算される「局所適応しきい値処理」を行うことです。やり方はいろいろありますが、例えば以下を参考にしてください。

cv2.adaptiveThreshold(...,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,...) を使用した OpenCV での適応ガウスしきい値処理 ローカル Otsu の方法 ローカル適応ヒストグラム均等化 もう 1 つの問題は、線がまっすぐでないことです。私の経験では、Tesseract は非常に限られた程度の非直線 (遠近法の歪み、傾き、ゆがみの数パーセント) を処理できますが、波線では実際には機能しません。可能であれば、ソース画像に直線があることを確認してください:) 残念ながら、これに対する簡単な既成の答えはありません。研究文献を調べて、最先端のアルゴリズムの 1 つを自分で実装する必要があります (そして、可能であればオープンソース化します。これに対するオープンソース ソリューションが本当に必要です)。「曲線 OCR 抽出」を Google Scholar で検索すると、

湾曲したドキュメント画像のテキスト行分割 OpenCV pythonラッパーは単純なものには問題ありませんが、あなたがやろうとしていることにはうまくいきません.OpenCVにない多くの部分をつかむ必要があります(もちろん、組み合わせて一致させることができます). C++ で曲線検出のようなものを実装すると、Python よりも桁違いに時間がかかります (* これは、Python を知らなくても当てはまります)。

幸運を!

于 2015-12-24T08:59:29.527 に答える