Using tesseract to read numbers

479 views
Skip to first unread message

Bernardo Meurer

unread,
May 26, 2014, 6:58:22 PM5/26/14
to tesser...@googlegroups.com
Hello,
I'm in need of some help, I was wondering if it would be possible to use tesseract to read number plates as the one in the image below. If that is doable, if anyone could give me some directions of where to start it would also help a lot.

Thanks



Nick White

unread,
May 27, 2014, 10:32:51 AM5/27/14
to tesser...@googlegroups.com
Hi Bernardo,

On Mon, May 26, 2014 at 03:58:22PM -0700, Bernardo Meurer wrote:
> I'm in need of some help, I was wondering if it would be possible to use
> tesseract to read number plates as the one in the image below. If that is
> doable, if anyone could give me some directions of where to start it would also
> help a lot.

Variations of this question have been asked quite a few times on
this mailing list. Have you searched the archives?

The short answer is "if you can preprocess to isolate some not too
messed up text, you can pass that to Tesseract and it will work."

Search the archives for more clues. But yes, it's the image
processing that will be challenging.

Nick

Bernardo Meurer

unread,
May 27, 2014, 4:36:58 PM5/27/14
to tesser...@googlegroups.com
Hey Nick, thanks for the answer.
You are right, I hadn't done much research, sorry.
Now, I found this sample code which I am trying to test on my plates to see if its successful. I am getting compiling bugs when i try to run it, but i'm not sure this is the place to ask for help in such way. If its oks, the bugs are :
main.cc:66:37: error: CV_RETR_EXTERNAL was not declared in this scope
main
.cc:66:55: error: CV_CHAIN_APPROX_NONE was not declared in this scope
main
.cc:81:28: error: CV_BGR2GRAY was not declared in this scope
If this is not the right way to go, i believe i could at least use his image processing code, but use OpenCV to maybe try to detect the plate, then process it and read it in Tesseract, what do you think?

Nick White

unread,
May 27, 2014, 4:50:11 PM5/27/14
to tesser...@googlegroups.com
Hi Bernardo,

On Tue, May 27, 2014 at 01:36:58PM -0700, Bernardo Meurer wrote:
> Now, I found this sample code which I am trying to test on my plates to see if
> its successful. I am getting compiling bugs when i try to run it, but i'm not
> sure this is the place to ask for help in such way. If its oks, the bugs are :
> main.cc:66:37: error: ‘CV_RETR_EXTERNAL’ was not declared in this
> scope
> main.cc:66:55: error: ‘CV_CHAIN_APPROX_NONE’ was not declared in this scope
> main.cc:81:28: error: ‘CV_BGR2GRAY’ was not declared in this scope

This is a fine place to ask for such help, don't worry. However, if
you don't post some example code and the command you used to compile
it we can't really help you. From the errors I'd guess OpenCV isn't
being included appropriately.

> If this is not the right way to go, i believe i could at least use
> his image processing code, but use OpenCV to maybe try to detect
> the plate, then process it and read it in Tesseract, what do you
> think?

Sure, using OpenCV to detect the plate, ideally deskew it if
necessary, then sending it to Tesseract, sounds reasonable.
It sounds like that's what the example code you found does too,
probably.

Nick

Bernardo Meurer

unread,
May 27, 2014, 6:28:58 PM5/27/14
to tesser...@googlegroups.com
I didn't want to spam the source code here not knowing it wasn't allowed, but here is the code I'm attempting to compile:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <tesseract/baseapi.h>
#include <iostream>
void rgb2cmyk(cv::Mat& src, std::vector<cv::Mat>& cmyk)
{
    CV_Assert(src.type() == CV_8UC3);

    cmyk.clear();
    for (int i = 0; i < 4; ++i)
        cmyk.push_back(cv::Mat(src.size(), CV_32F));

    for (int i = 0; i < src.rows; ++i)
    {
        for (int j = 0; j < src.cols; ++j)
        {
            cv::Vec3b p = src.at<cv::Vec3b>(i,j);

            float r = p[2] / 255.;
            float g = p[1] / 255.;
            float b = p[0] / 255.;
            float k = (1 - std::max(std::max(r,g),b));

            cmyk[0].at<float>(i,j) = (1 - r - k) / (1 - k); 
            cmyk[1].at<float>(i,j) = (1 - g - k) / (1 - k);
            cmyk[2].at<float>(i,j) = (1 - b - k) / (1 - k);
            cmyk[3].at<float>(i,j) = k;
        }
    }
}

int main()
{
cv::Mat im0 = cv::imread("scratchcard.png");
    if (!im0.data)
        return -1;

    std::vector<cv::Mat> cmyk;
    rgb2cmyk(im0, cmyk);

    cv::Mat im1;
    im1 = cmyk[3].mul(1 - cmyk[1]) > 0.25;

    cv::Mat im2;
    im1.convertTo(im2, CV_8U);

    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(im2, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    double max_area = 0;
    int max_idx = 0;
    for (int i = 0; i < contours.size(); i++)
    {
        double area = cv::contourArea(contours[i]);
        max_idx  = area > max_area ? i : max_idx;
        max_area = area > max_area ? area : max_area;
    }

    im2.setTo(cv::Scalar(0));
    cv::drawContours(im2, contours, max_idx, cv::Scalar(255), -1);

    cv::Mat im3;
    cv::cvtColor(im0, im3, CV_BGR2GRAY);
    im3 = ((255 - im3) & im2) > 200;

    cv::Mat dst = im3.clone();
    cv::findContours(dst.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    for (int i = 0; i < contours.size(); i++)
    {
        if (cv::contourArea(contours[i]) < 100)
            cv::drawContours(dst, contours, i, cv::Scalar(0), -1);
    }

    tesseract::TessBaseAPI tess;
    tess.Init(NULL, "eng", tesseract::OEM_DEFAULT);
    tess.SetVariable("tessedit_char_whitelist", "0123456789");
    tess.SetPageSegMode(tesseract::PSM_SINGLE_BLOCK);
    tess.SetImage((uchar*)dst.data, dst.cols, dst.rows, 1, dst.cols);

    char* out = tess.GetUTF8Text();
    std::cout << out << std::endl;

    cv::imshow("src", im0);
    cv::imshow("dst", dst);
    cv::waitKey();
    return 0;
}

I included OpenCV and Tesseract as the example code instructed, but maybe I'm missing one #include.

zdenko podobny

unread,
May 28, 2014, 3:41:27 PM5/28/14
to tesser...@googlegroups.com
You did not provided a lot of information ;-)
  1. If you afraid to post code to forum, you can use pastebin.com or similar service. Sending links to code/files is IMHO good behaviour (for images too) :-)
  2. I tested it on openSUSE 13.1 64bit with opencv-devel-2.4.9-32.1. And this command compiles your code (saved as tess-opencv.cpp):
    gcc -o tess-opencv tess-opencv.cpp -ltesseract -lstdc++ -lopencv_core \
           -lopencv_highgui -lopencv_imgproc
    some version of opencv could have different names of libraries. In such case you need to use e.g. -lhighgui instead of -lopencv_highgui.

Zdenko


--
You received this message because you are subscribed to the Google Groups "tesseract-ocr" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tesseract-oc...@googlegroups.com.
To post to this group, send email to tesser...@googlegroups.com.
Visit this group at http://groups.google.com/group/tesseract-ocr.
To view this discussion on the web visit https://groups.google.com/d/msgid/tesseract-ocr/7efe2d12-791d-4511-928e-57d50908e1e8%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages