Skip to content

Commit

Permalink
Qrreader changes (#371)
Browse files Browse the repository at this point in the history
* 1. upgraded the zxing library
2. Added 4 props in QR Reader module
 - tryHarder
 - saveQRImages
 - qrImagesPath
 - frameRotationCounter
3. Added loop test for QR module

* checked out to v2.2.1 for zxing submodule and some minor changes in Readme file.

* added some warning logs and trycatch block to handle some exception

* changed submodule zxing-cpp to Apra-Labs/zxing-cpp
  • Loading branch information
VishwanathB45 authored Jul 31, 2024
1 parent b84edfc commit ee28868
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ git clone --recursive https://github.com/Apra-Labs/ApraPipes.git

## Prerequisites
* Run ```sudo apt-get update && sudo apt-get install build-essential``` to get latest build tools
* CMake minimum version 3.14 - Follow [this article](https://anglehit.com/how-to-install-the-latest-version-of-cmake-via-command-line/) to update cmake
* CMake minimum version 3.17 - Follow [this article](https://anglehit.com/how-to-install-the-latest-version-of-cmake-via-command-line/) to update cmake
* ffmpeg
```
sudo apt install yasm -y
Expand Down
8 changes: 4 additions & 4 deletions base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ IF(ENABLE_ARM64)
ENDIF(ENABLE_ARM64)

project(APRAPIPES)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)

hunter_add_package(Boost COMPONENTS system thread filesystem serialization log chrono)
find_package(Boost CONFIG REQUIRED system thread filesystem serialization log chrono)
Expand Down Expand Up @@ -60,13 +60,13 @@ find_library(LIB_AVFORMAT libavformat.a PATHS ${FFMPEG_ROOT}/libavformat NO_DEFA
find_library(LIB_AVCODEC libavcodec.a PATHS ${FFMPEG_ROOT}/libavcodec NO_DEFAULT_PATH)
find_library(LIB_AVUTIL libavutil.a PATHS ${FFMPEG_ROOT}/libavutil NO_DEFAULT_PATH)
find_library(LIB_FFSWR libswresample.a PATHS ${FFMPEG_ROOT}/libswresample NO_DEFAULT_PATH)
find_library(LIB_ZXING libZXing.a PATHS ../thirdparty/zxing-cpp/_install/lib NO_DEFAULT_PATH)
find_library(LIB_ZXING libZXing.a PATHS ../thirdparty/zxing-cpp/_build/zxing-cpp.release/core NO_DEFAULT_PATH)


IF(ENABLE_CUDA)
IF(ENABLE_ARM64)
SET(NVCODEC_LIB)
SET ( JETSON_MULTIMEDIA_LIB_INCLUDE "/usr/src/jetson_multimedia_api/include" )
SET ( JETSON_MULTIMEDIA_LIB_INCLUDE "/usr/src/jetson_multimedia_api/include" )

list(APPEND CMAKE_PREFIX_PATH /usr/lib/aarch64-linux-gnu/tegra)
list(APPEND CMAKE_PREFIX_PATH /usr/lib/aarch64-linux-gnu/tegra-egl)
Expand Down Expand Up @@ -117,7 +117,7 @@ include_directories(AFTER SYSTEM include
../thirdparty/Video_Codec_SDK_10.0.26/Interface
../thirdparty/ffmpeg/include
${CURSES_INCLUDE_DIR}
../thirdparty/zxing-cpp/_install/include/ZXing
../thirdparty/zxing-cpp/core/src
)

# ApraPipes library
Expand Down
18 changes: 17 additions & 1 deletion base/include/QRReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@

#include "Module.h"
#include "ReadBarcode.h"
#include "TextUtfEncoding.h"

class QRReaderProps : public ModuleProps
{
public:
QRReaderProps() : ModuleProps() {}
QRReaderProps(bool _tryHarder = false, bool _saveQRImages = false, string _qrImagesPath = "", int _frameRotationCounter = 10) : ModuleProps()
{
tryHarder = _tryHarder;
saveQRImages = _saveQRImages;
qrImagesPath = _qrImagesPath;
frameRotationCounter = _frameRotationCounter;
}

size_t getSerializeSize()
{
return ModuleProps::getSerializeSize();
}
bool tryHarder;
bool saveQRImages;
string qrImagesPath;
int frameRotationCounter;
};

class QRReader : public Module
Expand Down
79 changes: 65 additions & 14 deletions base/src/QRReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,28 @@
#include "FrameMetadataFactory.h"
#include "Frame.h"
#include "Logger.h"
#include "ReadBarcode.h"
#include "TextUtfEncoding.h"
#include "RawImageMetadata.h"
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

class QRReader::Detail
{

public:
Detail() : mWidth(0), mHeight(0)
Detail(QRReaderProps _props) : mWidth(0), mHeight(0)
{
mHints.setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);
mReaderOptions.setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);
LOG_INFO << "Setting tryHarder as " << _props.tryHarder;
mReaderOptions.setTryHarder(_props.tryHarder);
mSaveQRImages = _props.saveQRImages;
mQRImagesFolderName = _props.qrImagesPath;
mFrameRotationCounter = _props.frameRotationCounter;
if (mFrameRotationCounter <= 0)
{
LOG_WARNING << "You are setting frameRotationCounter less than 1";
mFrameRotationCounter = 1;
}
mFrameCounter = 0;
}

~Detail() {}
Expand Down Expand Up @@ -50,17 +62,18 @@ class QRReader::Detail

int mWidth;
int mHeight;
ZXing::DecodeHints mHints;
ZXing::ReaderOptions mReaderOptions;
std::string mOutputPinId;
ZXing::ImageFormat mImageFormat;

private:
framemetadata_sp mMetadata;
bool mSaveQRImages;
fs::path mQRImagesFolderName;
int mFrameCounter;
int mFrameRotationCounter;
};

QRReader::QRReader(QRReaderProps _props) : Module(TRANSFORM, "QRReader", _props)
{
mDetail.reset(new Detail());
mDetail.reset(new Detail(_props));
auto metadata = framemetadata_sp(new FrameMetadata(FrameMetadata::GENERAL));
mDetail->mOutputPinId = addOutputPin(metadata);
}
Expand Down Expand Up @@ -111,7 +124,15 @@ bool QRReader::init()
{
return false;
}

boost::system::error_code ec;
if (mDetail->mSaveQRImages && (!fs::create_directories(mDetail->mQRImagesFolderName, ec)))
{
if (ec)
{
LOG_ERROR << "Failed to create directory: " << mDetail->mQRImagesFolderName << ". Error: " << ec.message();
mDetail->mQRImagesFolderName = "";
}
}
return true;
}

Expand All @@ -124,10 +145,40 @@ bool QRReader::process(frame_container &frames)
{
auto frame = frames.begin()->second;

const auto &result = ZXing::ReadBarcode({static_cast<uint8_t *>(frame->data()), mDetail->mWidth, mDetail->mHeight, mDetail->mImageFormat}, mDetail->mHints);

auto text = ZXing::TextUtfEncoding::ToUtf8(result.text());

const auto &result = ZXing::ReadBarcode({static_cast<uint8_t *>(frame->data()), mDetail->mWidth, mDetail->mHeight, mDetail->mImageFormat}, mDetail->mReaderOptions);

auto text = result.text();
if (text.length())
{
LOG_INFO << "ZXING decoded QR: " << text;
}

if (mDetail->mSaveQRImages && (mDetail->mQRImagesFolderName != ""))
{
fs::path savePath = mDetail->mQRImagesFolderName / (std::to_string(mDetail->mFrameCounter) + ".raw");
try
{
std::ofstream outFile(savePath.string(), std::ios::binary);
if (outFile)
{
outFile.write(static_cast<char *>(frame->data()), frame->size());
outFile.close();
}
else
{
LOG_ERROR << "Failed to save frame to " << savePath.string();
}
}
catch (const std::exception &e)
{
LOG_ERROR << "Exception caught while saving frame to " << savePath.string() << ": " << e.what() << std::endl;
}
mDetail->mFrameCounter++;
if ((mDetail->mFrameCounter % mDetail->mFrameRotationCounter) == 0)
{
mDetail->mFrameCounter = 0;
}
}
auto outFrame = makeFrame(text.length(), mDetail->mOutputPinId);
memcpy(outFrame->data(), text.c_str(), outFrame->size());
frames.insert(make_pair(mDetail->mOutputPinId, outFrame));
Expand Down
59 changes: 59 additions & 0 deletions base/test/QRReader_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include "Logger.h"
#include "AIPExceptions.h"
#include "QRReader.h"
#include "PipeLine.h"
#include "RotateCV.h"
#include "VirtualCameraSink.h"

#define VIDEO_DEV "/dev/video99"

BOOST_AUTO_TEST_SUITE(QRReader_tests)

Expand Down Expand Up @@ -39,6 +44,34 @@ BOOST_AUTO_TEST_CASE(rgb)
BOOST_TEST(expectedOutput == actualOutput);
}

BOOST_AUTO_TEST_CASE(test)
{
FileReaderModuleProps fileReaderProps("./data/qrData/h.raw");
fileReaderProps.readLoop = true;
auto fileReader = boost::shared_ptr<FileReaderModule>(new FileReaderModule(fileReaderProps));
auto metadata = framemetadata_sp(new RawImageMetadata(720, 1280, ImageMetadata::ImageType::RGB, CV_8UC3, 0, CV_8U, FrameMetadata::HOST, true));
fileReader->addOutputPin(metadata);

QRReaderProps qrReaderProps(true,true,"./data",10);
auto QRData = boost::shared_ptr<QRReader>(new QRReader(qrReaderProps));
fileReader->setNext(QRData);

auto sink = boost::shared_ptr<ExternalSinkModule>(new ExternalSinkModule());
QRData->setNext(sink);

BOOST_TEST(fileReader->init());
BOOST_TEST(QRData->init());
BOOST_TEST(sink->init());

fileReader->step();
QRData->step();
auto frames = sink->pop();
BOOST_TEST(frames.size() == 1);
auto outputFrame = frames.cbegin()->second;
std::string expectedOutput = "0005100788";
auto actualOutput = std::string(const_cast<const char*>( static_cast<char*>(outputFrame->data()) ), outputFrame->size() );
}

BOOST_AUTO_TEST_CASE(yuv420)
{
Logger::setLogLevel(boost::log::trivial::severity_level::trace);
Expand Down Expand Up @@ -66,5 +99,31 @@ BOOST_AUTO_TEST_CASE(yuv420)
BOOST_TEST(expectedOutput == actualOutput);
}

BOOST_AUTO_TEST_CASE(readLoop)
{
Logger::setLogLevel(boost::log::trivial::severity_level::trace);
FileReaderModuleProps fileReaderProps("./data/qrData/h.raw");
fileReaderProps.readLoop = true;
auto fileReader = boost::shared_ptr<FileReaderModule>(new FileReaderModule(fileReaderProps));
auto metadata = framemetadata_sp(new RawImageMetadata(720, 1280, ImageMetadata::ImageType::RGB, CV_8UC3, 0, CV_8U, FrameMetadata::HOST, true));
fileReader->addOutputPin(metadata);

auto m1 = boost::shared_ptr<RotateCV>(new RotateCV(RotateCVProps(90)));
fileReader->setNext(m1);

QRReaderProps qrReaderProps(true, true, "./data", 10);
auto QRData = boost::shared_ptr<QRReader>(new QRReader(qrReaderProps));
m1->setNext(QRData);


auto p = boost::shared_ptr<PipeLine>(new PipeLine("test"));
p->appendModule(fileReader);
p->init();
p->run_all_threaded();
boost::this_thread::sleep_for(boost::chrono::seconds(60));

p->wait_for_all(true);
}


BOOST_AUTO_TEST_SUITE_END()
2 changes: 1 addition & 1 deletion thirdparty/zxing-cpp
Submodule zxing-cpp updated 1124 files

0 comments on commit ee28868

Please sign in to comment.