Click here to Skip to main content
15,868,141 members
Articles / Desktop Programming / Win32

OCR using C++

Rate me:
Please Sign up or sign in to vote.
4.90/5 (8 votes)
30 Jan 2021CPOL3 min read 14K   391   6   2
How to use an OCR SDK using C++ and libCurl
The purpose of this article is to teach you how to perform OCR using C++ by interfacing with an OCR SDK.

Image 1

Introduction

During our day to day development, we needed to perform OCR (Optical Character Recognition) on scanned images, screenshots and other forms or files. We looked for an SDK which will allow that and examined ABBYY Cloud OCR SDK. They didn't have any C / C++ code samples, so I had to develop them...

Creating an ABBYY Cloud OCR App

Image 2

Here are the steps that need to be taken once a trial account was created and verified.

  1. Create a new App.
  2. Check your email for the Application's password. You will need both Application ID and Application Password to start.

You should see these two placeholder lines in our code:

C++
#define APP_ID            "<Your Application ID>"
#define PASSWORD        "<Your Application Password"

Replace these strings with your allocated Application ID and Application Password.

Initiating libCurl

First, we initiate the Curl object:

C++
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();

Handling the Input File

Our input file can be any image or even a PDF file. We need to convert it to a mime and to do so, we call:

C++
<a href="https://curl.se/libcurl/c/curl_mime_init.html">curl_mime_init()</a>

Next, we generate the upload part in our request:

C++
field = curl_mime_addpart(form);
curl_mime_name(field, "upload");

and generate the file data using curl_mine_filedata() which is used to set our mime part's body data from out input file's contents.

C++
curl_mime_filedata(field, file_to_upload.c_str());

Now, we set the options by calling curl_easy_setopt(), which, as its name implies, prepare the set the options for our request.

We need the following attributes:

  • PROCESSING_URL is the URL given by Abbyy SDK.
  • headerlist was set earlier.
  • form is the upload part.
  • APP_ID is an application specific identifying provided by Abbyy SDK per each software we develop.
  • PASSWORD is the application's password, which needs to be generated.
  • CURLOPT_WRITEFUNCTION is a callback function for writing the result of the request. Data is written into readBuffer which will hold the results we receive from the API.
C++
curl_easy_setopt(curl, CURLOPT_URL, PROCESSING_URL);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
curl_easy_setopt(curl, CURLOPT_USERNAME, APP_ID);
curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

Then, we are ready to execute our request. We call curl_easy_perform().

C++
res = curl_easy_perform(curl);

Right after we check the results.

Checking the Results

Next, we obtain the Task_ID which is given to each OCR task. You can initiate several tasks and then wait for each of them to be completed. We use the Task_ID we have obtained to check the status of the task and wait until it is completed.

C++
while (1)
{
    res = curl_easy_perform(status_curl);
    if (res != CURLE_OK)
    {
        WriteLogFile(L"Error: %S", curl_easy_strerror(res));
    }
    else
    {
        WriteLogFile(L"Read Buffer:\n%S", readBuffer.c_str());
        task_status = ObtainStatus(readBuffer);
        WriteLogFile(L"task_status: %S", task_status.c_str());
    }
    if (task_status != "Completed")
    {
        //wait 5s before next check
        Sleep(2000);
    }
    else
    {
        setcolor(LOG_COLOR_DARKGREEN, 0);
        SetConsoleTitle(L"OCR completed");
        setcolor(LOG_COLOR_WHITE, 0);

        result_url = ObtainURL(readBuffer);
        //replace all &amp; to &
        result_url = ReplaceAll(result_url, "&amp;", "&");
        //downloading text file of response
        WriteLogFile(L"Downloading File from URL: %S", result_url.c_str());
        op_curl = curl_easy_init();
        if (op_curl)
        {
            headerlist = curl_slist_append(headerlist, buf);
            curl_easy_setopt(op_curl, CURLOPT_URL, result_url.c_str());
            curl_easy_setopt(op_curl, CURLOPT_HTTPHEADER, headerlist);
            curl_easy_setopt(op_curl, CURLOPT_HTTPGET, 1L);
            FILE* wfd = fopen(json_result_file.c_str(), "ab");
            fprintf(wfd, "\n");
            curl_easy_setopt(op_curl, CURLOPT_WRITEDATA, wfd);
            curl_easy_perform(op_curl);
            curl_easy_cleanup(op_curl);
            fclose(wfd);
            WriteLogFile(L"FILE saved");
        }
        break;
    }
    readBuffer = "";
}    // While

Now once we have the results, we just clean up everything.

Here is a video demo of how the program works:

Building Blocks

One of the key building blocks to such project, would be libCurl. I used it as a static library. The .lib file is included in the article's source code, however you can read about using libCurl as a static library here.

Note: WriteLogFile() is one of my old logging functions described in this article.

Using the Code

You can use a different export format. See this link for the options.

You can define which languages you are expecting. Read this link for the options.

You can use many languages, most of them can be also as hand written text (ICR). You set the list of expected languages in the PROCESSING_URL string.

In this example, we expect English and Hebrew:

C++
#define PROCESSING_URL    
"https://cloud-westus.ocrsdk.com/processImage?exportFormat=txt&language=English,Hebrew"

History

  • 30th January, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Secured Globe, Inc.
United States United States
Michael Haephrati is a music composer, an inventor and an expert specializes in software development and information security, who has built a unique perspective which combines technology and the end user experience. He is the author of a the book Learning C++ , which teaches C++ 20, and was published in August 2022.

He is the CEO of Secured Globe, Inc., and also active at Stack Overflow.

Read our Corporate blog or read my Personal blog.





Comments and Discussions

 
Questionis there a way to save in different format as csv? Pin
The Gridlock8-Mar-22 17:40
The Gridlock8-Mar-22 17:40 
AnswerRe: is there a way to save in different format as csv? Pin
Michael Haephrati8-Mar-22 17:54
professionalMichael Haephrati8-Mar-22 17:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.