From ee2886891d56946972a3f358754b572e3a0198e2 Mon Sep 17 00:00:00 2001 From: VishwanathB45 <130537881+VishwanathB45@users.noreply.github.com> Date: Thu, 1 Aug 2024 01:05:54 +0530 Subject: [PATCH] Qrreader changes (#371) * 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 --- README.md | 2 +- base/CMakeLists.txt | 8 ++-- base/include/QRReader.h | 18 +++++++- base/src/QRReader.cpp | 79 +++++++++++++++++++++++++++++------- base/test/QRReader_tests.cpp | 59 +++++++++++++++++++++++++++ thirdparty/zxing-cpp | 2 +- 6 files changed, 147 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 744934e73..2792f9c86 100755 --- a/README.md +++ b/README.md @@ -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 diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 14b1cf0ad..bbc5dd179 100755 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -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) @@ -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) @@ -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 diff --git a/base/include/QRReader.h b/base/include/QRReader.h index 481bfabdc..43e79fee7 100644 --- a/base/include/QRReader.h +++ b/base/include/QRReader.h @@ -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 diff --git a/base/src/QRReader.cpp b/base/src/QRReader.cpp index c341daa78..6d5fa7aba 100644 --- a/base/src/QRReader.cpp +++ b/base/src/QRReader.cpp @@ -3,16 +3,28 @@ #include "FrameMetadataFactory.h" #include "Frame.h" #include "Logger.h" -#include "ReadBarcode.h" -#include "TextUtfEncoding.h" +#include "RawImageMetadata.h" +#include +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() {} @@ -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); } @@ -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; } @@ -124,10 +145,40 @@ bool QRReader::process(frame_container &frames) { auto frame = frames.begin()->second; - const auto &result = ZXing::ReadBarcode({static_cast(frame->data()), mDetail->mWidth, mDetail->mHeight, mDetail->mImageFormat}, mDetail->mHints); - - auto text = ZXing::TextUtfEncoding::ToUtf8(result.text()); - + const auto &result = ZXing::ReadBarcode({static_cast(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(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)); diff --git a/base/test/QRReader_tests.cpp b/base/test/QRReader_tests.cpp index cd3b73234..ed8e7b580 100644 --- a/base/test/QRReader_tests.cpp +++ b/base/test/QRReader_tests.cpp @@ -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) @@ -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(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(new QRReader(qrReaderProps)); + fileReader->setNext(QRData); + + auto sink = boost::shared_ptr(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( static_cast(outputFrame->data()) ), outputFrame->size() ); +} + BOOST_AUTO_TEST_CASE(yuv420) { Logger::setLogLevel(boost::log::trivial::severity_level::trace); @@ -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(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(new RotateCV(RotateCVProps(90))); + fileReader->setNext(m1); + + QRReaderProps qrReaderProps(true, true, "./data", 10); + auto QRData = boost::shared_ptr(new QRReader(qrReaderProps)); + m1->setNext(QRData); + + + auto p = boost::shared_ptr(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() diff --git a/thirdparty/zxing-cpp b/thirdparty/zxing-cpp index a3e1d3115..ce8e3770e 160000 --- a/thirdparty/zxing-cpp +++ b/thirdparty/zxing-cpp @@ -1 +1 @@ -Subproject commit a3e1d3115147cc72970574f30f635a13bbe75782 +Subproject commit ce8e3770ea9aaf5809b11ebfc258d433df86eac2