Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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