Compare commits

..

No commits in common. "b5811dbbcb44d7c914e54342c371e48c9cf696d7" and "aad6de3687aa3fc3d00b557fbf5756dd2e825662" have entirely different histories.

4 changed files with 64 additions and 160 deletions

View File

@ -1,8 +1,6 @@
cmake_minimum_required(VERSION 3.1.0) cmake_minimum_required(VERSION 3.1.0)
project(lfr_image_processing VERSION 0.1.0) project(lfr_image_processing VERSION 0.1.0)
set (CMAKE_CXX_STANDARD 20)
include(CTest) include(CTest)
enable_testing() enable_testing()

View File

@ -4,52 +4,19 @@
int main(void) int main(void)
{ {
//Disable opencv logging messages //Disable opencv logging messages
//cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_WARNING); cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_WARNING);
const int thresholdBinary = 140; const int thresholdBinary = 140;
const int videoHeight = 720; const int videoHeight = 720;
const int videoWidth = 1280; const int videoWidth = 1280;
const int gaussKernelSize = 11; const int gaussKernelSize = 11;
std::mutex mutex; LFR lfr(videoHeight, videoWidth, thresholdBinary, gaussKernelSize);
lfr.saveOutputFlag = false;
LFR lfr(videoHeight, videoWidth, thresholdBinary, gaussKernelSize, [&](std::exception const &ex) lfr.videoFlag = true;
{
std::unique_lock<std::mutex> lock(mutex);
std::cerr<<"camera exception:"<<ex.what()<<std::endl;
return true;
});
//To calculate the frame rate
std::chrono::milliseconds last = duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
std::chrono::milliseconds now = duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
cv::Mat img;
lfr.addListener([&](LFR_Result result)
{
std::unique_lock<std::mutex> lock(mutex);
if (!result.rawImage.empty())
{
cv::resize(result.rawImage, img, cv::Size(128, 64+32));
//Calculate frame rate
now = duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
unsigned int deltaMs = (now-last).count();
float delta = static_cast<float>(deltaMs) / 1000.0;
float frameRate = 1.0 / static_cast<float>(delta);
//std::cout << "Frame rate: " << frameRate << std::endl;
last = now;
}
}, &mutex);
lfr.startLoop(); lfr.startLoop();
//To end the video stream, write any char in the console.
for(int finished = false; finished != 'q';){ char a;
finished = std::tolower(cv::waitKey(66)); std::cin >> a;
std::unique_lock<std::mutex> lock(mutex); lfr.endLoop();
if(!img.empty()){
cv::imshow("frame", img);
}
}
} }

View File

@ -3,114 +3,63 @@
#define right false #define right false
#define left true #define left true
LFR::LFR(int videoHeight, int videoWidth, int thresholdBinary, int gaussKernelSize, ExceptionCallback cb): LFR::LFR(int videoHeight, int videoWidth, int thresholdBinary, int gaussKernelSize)
stop(false), : iAmLooping(false), input(videoHeight, videoWidth), processing(), controlModule(), interpreter(), intersectionHandler()
input(videoHeight, videoWidth),
processing(),
controlModule(),
interpreter(),
intersectionHandler(),
cb(cb)
{ {
this->iAmLooping = false;
this->thresholdBinary = thresholdBinary; this->thresholdBinary = thresholdBinary;
this->gaussKernelSize = gaussKernelSize; this->gaussKernelSize = gaussKernelSize;
this->videoFlag = false;
this->saveOutputFlag = false;
this->outputFileName = "";
} }
LFR::~LFR() LFR::~LFR()
{ {
endLoop(); if(iAmLooping)
thread->join();
}
void LFR::removeListener(LFR::ListenerKey key)
{
std::lock_guard<std::mutex> lock(mutex);
auto it = std::find_if(std::begin(listeners), std::end(listeners), [&](auto const &val){
return val.first == key;
});
if(it != std::end(listeners))
{ {
listeners.erase(it); this->endLoop();
} }
} }
void LFR::addListener(LFR::ListenerCallback cb, LFR::ListenerKey key) void LFR::loop()
{ {
std::lock_guard<std::mutex> lock(mutex); if(this->videoFlag) {namedWindow("Display window");}
listeners.emplace_back(key, std::move(cb)); while(iAmLooping)
}
void LFR::setStop(bool val)
{
std::lock_guard<std::mutex> lock(mutex);
stop = val;
}
void LFR::createThread()
{
thread = std::make_unique<std::thread>([this](){
while(true)
{ {
LFR_Result result;
if(!stop && !listeners.empty())
{
try
{
std::lock_guard<std::mutex> lock(mutex);
Mat originalImage = input.readWebcam(); Mat originalImage = input.readWebcam();
Point roiOrigin(0, int(originalImage.rows*(3.25/6.0))); Point roiOrigin(0, int(originalImage.rows*(3.25/6.0)));
Rect roi(roiOrigin.x, roiOrigin.y, originalImage.cols, originalImage.rows/6); Rect roi(roiOrigin.x, roiOrigin.y, originalImage.cols, originalImage.rows/6);
//Mat processedImage = originalImage(roi);
Mat processedImage = originalImage; Mat processedImage = originalImage;
processing.processImage(processedImage, this->thresholdBinary, this->gaussKernelSize); processing.processImage(processedImage, this->thresholdBinary, this->gaussKernelSize);
//processedImage = processedImage(roi);
FrameData data = processing.calculateLineSegments(processedImage, roi); FrameData data = processing.calculateLineSegments(processedImage, roi);
processing.filterReflections(data); processing.filterReflections(data);
processing.calcAngles(data, originalImage.cols, originalImage.rows, left); processing.calcAngles(data, originalImage.cols, originalImage.rows, left);
this->provideOutput(originalImage, processedImage, data, roi);
processedImage = provideOutput(originalImage, processedImage, data, roi);
result.rawImage = originalImage;
result.processedImage = processedImage;
result.data = data;
} }
catch(std::exception const &ex) if(this->videoFlag) {destroyWindow("Display window");}
{ input.freeWebcam();
cb(ex);
}
//Invoke the callback method (ListenerPair second -> ListenerCallback)
for(auto &val : listeners)
{
val.second(result);
}
}
else
{
break;
}
}
});
} }
void LFR::startLoop() void LFR::startLoop()
{ {
if(thread) iAmLooping = true;
{ this->loopThread=thread(&LFR::loop, this);
//Restart thread if it is running
setStop(true);
thread->join();
setStop(false);
}
createThread();
} }
void LFR::endLoop() void LFR::endLoop()
{ {
setStop(true); iAmLooping = false;
this->loopThread.join();
return;
} }
cv::Mat LFR::provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi) void LFR::provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi)
{ {
for(int i = 0; i < frameData.contours.size(); i++) for(int i = 0; i < frameData.contours.size(); i++)
{ {
@ -134,5 +83,14 @@ cv::Mat LFR::provideOutput(Mat originalImage, Mat processedImage, const FrameDat
P2.y = (int)round(P1.y + length * sin(frameData.angle * CV_PI / 180.0)); P2.y = (int)round(P1.y + length * sin(frameData.angle * CV_PI / 180.0));
cv::arrowedLine(originalImage, P1, P2, Scalar(0,0,255), 2, 8); cv::arrowedLine(originalImage, P1, P2, Scalar(0,0,255), 2, 8);
} }
return originalImage; if(this->videoFlag)
{
imshow("Display window", originalImage);
imshow("processed:", processedImage);
char c = (char)waitKey(25);
}
if (this->saveOutputFlag && !(this->outputFileName.empty()))
{
imwrite(this->outputFileName, originalImage);
}
} }

View File

@ -3,7 +3,6 @@
#include <iostream> #include <iostream>
#include <future> #include <future>
#include <thread> #include <thread>
#include <functional>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
@ -16,52 +15,34 @@
using namespace cv; using namespace cv;
struct LFR_Result
{
cv::Mat rawImage;
cv::Mat processedImage;
FrameData data;
};
class LFR class LFR
{ {
public:
using ListenerKey = void const*;
using ExceptionCallback = std::function<bool(std::exception const &ex)>;
using ListenerCallback = std::function<void(LFR_Result)>;
private:
using ListenerPair = std::pair<ListenerKey, ListenerCallback>;
using ListenerVector = std::vector<ListenerPair>;
Input input; Input input;
Processing processing; Processing processing;
ControlModule controlModule; ControlModule controlModule;
Interpreter interpreter; Interpreter interpreter;
IntersectionHandler intersectionHandler; IntersectionHandler intersectionHandler;
volatile bool iAmLooping;
void loop();
thread loopThread;
int thresholdBinary; int thresholdBinary;
int gaussKernelSize; int gaussKernelSize;
ListenerVector listeners; void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi);
ExceptionCallback cb;
bool stop;
std::unique_ptr<std::thread> thread;
mutable std::mutex mutex;
//void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi);
void createThread();
void setStop(bool val);
public: public:
LFR() = delete; LFR() = delete;
LFR(int videoHeight, int videoWidth, int thresholdBinary, int gaussKernelSize, ExceptionCallback cb); LFR(int videoHeight, int videoWidth, int thresholdBinary, int gaussKernelSize);
~LFR(); ~LFR();
void startLoop(); void startLoop();
void endLoop(); void endLoop();
void addListener(ListenerCallback cv, ListenerKey key);
void removeListener(ListenerKey key);
void isStopped() const noexcept; bool videoFlag;
Mat provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi); bool saveOutputFlag;
std::string outputFileName;
}; };