User Guide - C++
In this guide, you will learn step by step on how to build a barcode reader, label recognizer and document normalizer application with Dynamsoft Capture Vision SDK using C++ language.
Read more on Dynamsoft Capture Vision Features
Table of Contents
Requirements
- Windows:
- Supported Versions: Windows 7 and higher, or Windows Server 2003 and higher
- Architecture: x64 and x86
- Development Environment: Visual Studio 2012 or higher.
- Linux:
- Supported Distributions: Ubuntu 14.04.4+ LTS, Debian 8+, CentOS 6+
- Architectures: x64 (arm 32-bit and arm 64-bit coming soon)
- Minimum GLIBC Version: GLIBC_2.18 or higher
- Compiler: G++ 5.4 or higher
Installation
If you haven’t downloaded the SDK yet, download the C/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.
Build Your First Application
Let’s start by creating a console application which demonstrates the minimum code needed to capture content from an image file.
You can download the complete source code from here.
Create A New Project
For Windows
-
Open Visual Studio. Go to File > New > Project, select Empty App and enter
CaptureFromAnImage
in thename
text box. -
Add a new source file named
CaptureFromAnImage.cpp
into the project.
For Linux
-
Create a new source file named
CaptureFromAnImage.cpp
and place it into the folder[INSTALLATION FOLDER]\Resources\CaptureVision\Samples\HelloWorld\CaptureFromAnImage
. -
Create a file named
Makefile
and put it in the same directory as the fileCaptureFromAnImage.cpp
. The content ofMakefile
is as follows:CC=gcc CCFLAGS=-c -std=c++11 DLRMODEL_PATH=../../../CharacterModel DS_LIB_PATH=../../../Lib/Linux/x64 LDFLAGS=-L $(DS_LIB_PATH) -Wl,-rpath=$(DS_LIB_PATH) -Wl,-rpath=./ DS_LIB=-lDynamsoftCaptureVisionRouter -lDynamsoftCore -lDynamsoftLicense -lDynamsoftUtility STDLIB=-lstdc++ TARGET=CaptureFromAnImage OBJECT=CaptureFromAnImage.o SOURCE=CaptureFromAnImage.cpp # build rule for target. $(TARGET): $(OBJECT) $(CC) -o $(TARGET) $(OBJECT) $(STDLIB) $(DS_LIB) $(LDFLAGS) cp -r $(DLRMODEL_PATH) $(DS_LIB_PATH) # target to build an object file $(OBJECT): $(SOURCE) $(CC) $(CCFLAGS) $(SOURCE) # the clean target .PHONY : clean clean: rm -f $(OBJECT) $(TARGET) -r $(DS_LIB_PATH)/CharacterModel
Note: The
DS_LIB_PATH
variable should be set to the correct directory where the DLR library files are located. The files and character models directory can be found in[INSTALLATION FOLDER]/Lib/Linux/x64
.
Include the Library
-
Add headers and libs in
CaptureFromAnImage.cpp
.#include <iostream> #include <string> #include "[INSTALLATION FOLDER]/Include/DynamsoftCaptureVisionRouter.h" using namespace std; using namespace dynamsoft::cvr; using namespace dynamsoft::dlr; using namespace dynamsoft::dbr; using namespace dynamsoft::ddn; using namespace dynamsoft::license; using namespace dynamsoft::utility; // The following code only applies to Windows. #if defined(_WIN64) || defined(_WIN32) #ifdef _WIN64 #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x64/DynamsoftCaptureVisionRouterx64.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x64/DynamsoftCorex64.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x64/DynamsoftLicensex64.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x64/DynamsoftUtilityx64.lib") #else #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x86/DynamsoftCaptureVisionRouterx86.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x86/DynamsoftCorex86.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x86/DynamsoftLicensex86.lib") #pragma comment(lib, "[INSTALLATION FOLDER]/Lib/Windows/x86/DynamsoftUtilityx86.lib") #endif #endif
Initialize a Capture Vision Router Instance
-
Initialize the license key
char error[512]; CLicenseManager::InitLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", error, 512); cout << "License initialization: " << error << endl;
Note:
- An internet connection is required for the license to work.
- “DLS2***” is a default free public trial license used in the sample.
- If the license has expired, please request an extension through the customer portal.
-
Create an instance of Dynamsoft Capture Vision Router
CCaptureVisionRouter* router = new CCaptureVisionRouter();
Capture and Output Captured Results
-
Capture content from an image file
string imageFile = "[INSTALLATION FOLDER]/Resources/CaptureVision/Images/dcv-sample-image.png"; CCapturedResult* result = router->Capture(imageFile.c_str(), CPresetTemplate::PT_DEFAULT);
Note:
Please change all
[INSTALLATION FOLDER]
in above code snippet to your unpacking path. -
Output the captured results
cout << "File: " << imageFile << endl; // 4.Outputs the result. if (result->GetErrorCode() != 0) { cout << "Error: " << result->GetErrorCode() << "," << result->GetErrorString() << endl; } /* * There can be multiple types of result items per image. */ int count = result->GetCount(); cout << "Captured " << count << " items" << endl; for (int i = 0; i < count; i++) { const CCapturedResultItem* item = result->GetItem(i); CapturedResultItemType type = item->GetType(); if (type == CapturedResultItemType::CRIT_BARCODE) { const CBarcodeResultItem* barcode = dynamic_cast<const CBarcodeResultItem*>(item); // Output the decoded barcode text. cout << ">>Item " << i << ": " << "Barcode," << barcode->GetText() << endl; } else if (type == CapturedResultItemType::CRIT_TEXT_LINE) { const CTextLineResultItem* textLine = dynamic_cast<const CTextLineResultItem*>(item); // Output the recognized text line. cout << ">>Item " << i << ": " << "TextLine," << textLine->GetText() << endl; } else 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 iamge to file. errorcode = manager.SaveToFile(normalizedImage->GetImageData(), outPath.c_str()); if (errorcode == 0) { cout << ">>Item " << i << ": " << "NormalizedImage," << outPath << endl; } } }
Release the Allocated Memory
delete router, router = NULL;
delete result, result = NULL;
Build and Run the Project
On windows
-
Build the application through Visual Studio.
- Copy the related DLL files to the same folder as the EXE file. The DLL files can be found in
[INSTALLATION FOLDER]\Lib\Windows\[platforms]
Note: Select the corresponding folder (x86 or x64) based on your project’s platform setting.
-
Copy the
[INSTALLATION FOLDER]\Resources\LabelRecognizer\CharacterModel
directory to the same folder as the EXE file. - Run the program
CaptureFromAnImage.exe
.
On Linux
-
Open a terminal and change to the target directory where
Makefile
located in. Build the sample:>make
-
Run the program
CaptureFromAnImage
.>./CaptureFromAnImage
Process Multiple Images
If you need to process multiple images at once instead of one image, you can follow these steps:
Preparation Steps
- Create a new project named
CaptureFromMultipleImages
. - Initialize a Capture Vision Router Instance.
- 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.
-
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);
-
Create a class
MyImageSourceStateListener
to implement theCImageSourceStateListenter
interface, and callStopCapturing
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(); } };
-
Register the
MyImageSourceStateListener
object to monitor the status of the image source.CImageSourceStateListener *listener = new MyImageSourceStateListener(router); router->AddImageSourceStateListener(listener);
Add Captured Result Receiver
-
Create a class
MyResultReceiver
to implement theCCapturedResultReceiver
interface, and get the captured results inOnCapturedResultReceived
callback function.class MyResultReceiver : public CCapturedResultReceiver { public: virtual void OnCapturedResultReceived(const CCapturedResult* pResult) { const CFileImageTag *tag = dynamic_cast<const CFileImageTag*>(pResult->GetSourceImageTag()); cout << "File: " << tag->GetFilePath() << endl; cout << "Page: " << tag->GetPageNumber() << endl; if (pResult->GetErrorCode() != EC_OK) { cout << "Error: " << pResult->GetErrorString() << endl; } else { int lCount = pResult->GetCount(); cout << "Captured " << lCount << " items" << endl; for (int i = 0; i < lCount; i++) { const CCapturedResultItem* item = pResult->GetItem(i); CapturedResultItemType type = item->GetType(); if (type == CapturedResultItemType::CRIT_BARCODE) { const CBarcodeResultItem* barcode = dynamic_cast<const CBarcodeResultItem*>(item); // Output the decoded barcode text. cout << ">>Item " << i << ": " << "Barcode," << barcode->GetText() << endl; } else if (type == CapturedResultItemType::CRIT_TEXT_LINE) { const CTextLineResultItem* textLine = dynamic_cast<const CTextLineResultItem*>(item); // Output the recognized text line. cout << ">>Item " << i << ": " << "TextLine," << textLine->GetText() << endl; } else 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 iamge to file. int errorcode = manager.SaveToFile(normalizedImage->GetImageData(), outPath.c_str()); if (errorcode == 0) { cout << ">>Item " << i << ": " << "NormalizedImage," << outPath << endl; } } } } cout << endl; } };
For the error handling mechanism, the SDK returns Error Code in the
CCapturedResult
object. You can add error handling code as needed. See Error Code for a full list of supported error codes. -
Register the
MyResultReceiver
object to monitor the captured results of the router.CCapturedResultReceiver* recv = new MyResultReceiver(); router->AddResultReceiver(recv);
Start Capturing
-
Start Capturing with the default Capture Vision Template.
router->StartCapturing(CPresetTemplate::PT_DEFAULT, true);
Note:
- During the process, the callback function
OnCapturedResultReceived()
is triggered each time an image finishes processing. After all images are processed, the listener functionOnImageSourceStateReceived()
will return the image source state asISS_EXHAUSTED
and the process is stopped with the methodStopCapturing()
.
- During the process, the callback function
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.