Resource Base
Table of contents

Document Normalizer in C++ - User Guide

In this guide, you will learn step by step on how to build a document normalization application with Dynamsoft Document Normalizer SDK using C++ language.

Read more on Dynamsoft Document Normalizer Features

Installation

If you haven’t downloaded the SDK yet, download the C++ Package now and unpack the package into a directory of your choice.

For this tutorial, we unpack it to a pseudo directory [INSTALLATION FOLDER], change it to your unpacking path for the following content.

To find out whether your environment is supported, read the System Requirements.

Build Your First Application

Let’s start by creating a console application which demonstrates how to use the minimum code to detect and normalize a document from an picture of it.

You can download the entire source code from here.

Create a New Project

  • For Windows
  1. Open Visual Studio. Go to “File > New > Project…” or click “Create a new project” on the starting page, choose “Console App”, create a new Empty Project and set the Project name as NormalizeAnImage.

  2. Add a new source file named NormalizeAnImage.cpp into the project.

  • For Linux
  1. Create a new source file named NormalizeAnImage.cpp and place it into the folder [INSTALLATION FOLDER]/Dynamsoft/Resources/DocumentNormalizer/Samples/HelloWorld/NormalizeAnImage.

Include the Library

  1. Add headers and libs in NormalizeAnImage.cpp.

     #include <iostream>
     #include <string>
     #include "[INSTALLATION FOLDER]/Dynamsoft/Include/DynamsoftCaptureVisionRouter.h"
    
     using namespace std;
     using namespace dynamsoft::license;
     using namespace dynamsoft::cvr;
     using namespace dynamsoft::ddn;
    
     #if defined(_WIN64) || defined(_WIN32)
         #ifdef _WIN64
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x64/DynamsoftCaptureVisionRouterx64.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x64/DynamsoftCorex64.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x64/DynamsoftLicensex64.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x64/DynamsoftUtilityx64.lib")
         #else
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x86/DynamsoftCaptureVisionRouterx86.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x86/DynamsoftCorex86.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x86/DynamsoftLicensex86.lib")
             #pragma comment(lib, "[INSTALLATION FOLDER]/Dynamsoft/Distributables/Lib/Windows/x86/DynamsoftUtilityx86.lib")
         #endif
     #endif
    

Initialize a Capture Vision Router Instance

  1. Initialize the license key.

     char errorMsg[256] = {0};
     CLicenseManager::InitLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", errorMsg, 256);
    

    The string “DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9” here is a free public trial license. Note that network connection is required for this license to work. When it expires, you can request a 30-day free trial license from the Customer Portal.

  2. Create an instance of Capture Vision Router.

     CCaptureVisionRouter *router = new CCaptureVisionRouter;
    

Detect and Save the Normalized Document

  1. Apply normalization for an image file.

     string imageFile = "../../../Images/sample-image.png";
     CCapturedResult* result = router->Capture(imageFile.c_str(), CPresetTemplate::PT_DETECT_AND_NORMALIZE_DOCUMENT);
    
  2. Save the normalized result as an image file.

     cout << "File: " << imageFile << endl;
    
     /*
     * results is an Array of CCapturedResult objects, each object is the result of an image.
     */
    
     if (result->GetErrorCode() != 0) {
         cout << "Error: " << result->GetErrorCode() << "," << result->GetErrorString() << endl;
     }
     /*
     * There can be multiple types of result items per image.
     * We check each of these items until we find the normalized image.
     */
     int count = result->GetItemsCount();
     cout << "Normalized " << count << " documents" << endl;
     for (int i = 0; i < count; i++) {
         const CCapturedResultItem* item = result->GetItem(i);
         CapturedResultItemType type = item->GetType();
         if (type == CapturedResultItemType::CRIT_NORMALIZED_IMAGE) {
             const CNormalizedImageResultItem* normalizedImage = dynamic_cast<const CNormalizedImageResultItem*>(item);
             string outPath = "normalizedResult_";
             outPath += to_string(i) + ".png";
             CImageManager manager;
             // Save normalized image to file.
             errorcode = manager.SaveToFile(normalizedImage->GetImageData(), outPath.c_str());
             if (errorcode == 0) {
                 cout << "Document " << i << " file: " << outPath << endl;
             }
         }
     }
    
  3. Release the allocated memory.

     result->Release();
     delete router, router = NULL;
    

Build and Run the Project

  • For Windows
  1. In Visual Studio, set the solution to build as Release|x64.

  2. Build the project to generate program NormalizeAnImage.exe.

  3. Copy ALL *.dll files under [INSTALLATION FOLDER]/Dynamsoft/Lib/Windows/x64 to the same folder as the NormalizeAnImage.exe

  4. Copy [INSTALLATION FOLDER]/Dynamsoft/Distributables/DDN-PresetTemplates.json to the same folder as the NormalizeAnImage.exe.

  5. Run the program NormalizeAnImage.exe.

The SDK supports both x86 and x64, please set the platform based on your needs.

  • For Linux
  1. Open a terminal and change to the target directory where NormalizeAnImage.cpp is located. Build the sample:

     g++ -o NormalizeAnImage NormalizeAnImage.cpp -lDynamsoftCore -lDynamsoftLicense -lDynamsoftUtility -lDynamsoftCaptureVisionRouter -L ../../../Lib/Linux/x64 -Wl,-rpath=../../../Lib/Linux/x64 -std=c++11
     cp ../Distributables/DDN-PresetTemplates.json ../Distributables/Lib/Linux/x64
    
  2. Run the program NormalizeAnImage.

     ./NormalizeAnImage
    

Process Multiple Images

If you need to process multiple images at once instead of one image, you can follow these steps:

Preparation Steps

  1. Create a new project named NormalizeMultipleImages.
  2. Initialize a Capture Vision Router Instance.
  3. Include the Library.

You can download the complete source code from here.

Add an Image Source as the Input

The class CDirectoryFetcher is capable of converting a local directory to an image source. We will use it to connect multiple images to the image-processing engine.

  1. Setting up a directory fetcher to retrieve image data sources from a directory.

     CDirectoryFetcher *dirFetcher = new CDirectoryFetcher;
     dirFetcher->SetDirectory("[Your Image Path]");
    
     router->SetInput(dirFetcher);
    
  2. Create a class MyImageSourceStateListener to implement the CImageSourceStateListenter interface, and call StopCapturing in the callback function.

     class MyImageSourceStateListener : public CImageSourceStateListener
     {
     private:
         CCaptureVisionRouter* m_router;
    
     public:
         MyImageSourceStateListener(CCaptureVisionRouter* router) {
             m_router = router;
         }
    
         virtual void OnImageSourceStateReceived(ImageSourceState state)
         {
             if (state == ISS_EXHAUSTED)
                 m_router->StopCapturing();
         }
     };
    
  3. Register the MyImageSourceStateListener object to monitor the status of the image source.

     CImageSourceStateListener *listener = new MyImageSourceStateListener(router);
     router->AddImageSourceStateListener(listener);
    

Add a Result Receiver as the Output

  1. Define the receiver class.

     class MyResultReceiver : public CCapturedResultReceiver
     {
         void OnNormalizedImagesReceived(CNormalizedImagesResult* pResult)
         {
             const CFileImageTag *tag = dynamic_cast<const CFileImageTag*>(pResult->GetOriginalImageTag());
    
             cout << "File: " << tag->GetFilePath() << endl;
    
             if (pResult->GetErrorCode() != EC_OK)
             {
                 cout << "Error: " << pResult->GetErrorString() << endl;
             }
             else
             {
                 CImageManager manager;
                 int lCount = pResult->GetItemsCount();
                 cout << "Normalized " << lCount << " documents" << endl;
                 for (int li = 0; li < lCount; ++li)
                 {
                     const CNormalizedImageResultItem* item = pResult->GetItem(li);
                        
                     string outPath = "normalizeImage_";
                     outPath += to_string(li) + ".png";
    
                     manager.SaveToFile(item->GetImageData(), outPath.c_str());
    
                     cout << "Document " << li << " file: " << outPath << endl;
                 }
             }
    
             cout << endl;
         }
     };
    

    For the error handling mechanism, the SDK returns Error Code in the CNormalizedImagesResult object. You can add error handling code as needed. See Error Code for a full list of supported error codes.

  2. Create a receiver object and set it as the output.

     CCapturedResultReceiver *recv = new MyResultReceiver;
     router->AddResultReceiver(recv);
    

Start the Process

  1. Call the method StartCapturing() to start processing all the images in the specified folder.

     router->StartCapturing(CPresetTemplate::PT_DETECT_AND_NORMALIZE_DOCUMENT, true);        
    

    During the process, the callback function OnNormalizedImagesReceived() is triggered each time an image finishes processing. After all images are processed, the listener function OnImageSourceStateReceived() will return the image source state as ISS_EXHAUSTED and the process is stopped with the method StopCapturing().

Release Allocated Memory

delete router, router = NULL;
delete dirFetcher, dirFetcher = NULL;
delete listener, listener = NULL;
delete recv, recv = NULL;

Build and Run the Project Again

Please refer to Build and Run the Project.

This page is compatible for:

Version 1.0

Is this page helpful?

YesYes NoNo

In this article:

latest version

  • Latest version(2.2.10)
  • Version 2.x
    • Version 2.2.0
    • Version 2.0.20
    • Version 2.0.10
    • Version 2.0.0
  • Version 1.x
    • Version 1.0.20
    • Version 1.0.10
    • Version 1.0.0
Change +
© 2003–2024 Dynamsoft. All rights reserved.
Privacy Statement / Site Map / Home / Purchase / Support