From 3da94d12ffaa223ddd347fd1ea56050ed4b6f12c Mon Sep 17 00:00:00 2001 From: "ly.pechvattana" Date: Fri, 24 Feb 2023 11:17:03 +0100 Subject: [PATCH 1/2] buffer part --- ppg.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ppg.cpp b/ppg.cpp index 9752e6a..198839c 100644 --- a/ppg.cpp +++ b/ppg.cpp @@ -9,6 +9,7 @@ const int FPS = 30; bool isDiscardData = true; int countDiscard = 0; const int DISCARD_DURATION = 10; +const int BUFFER_DURATION = 60; int main() { cv::VideoCapture cap; @@ -42,6 +43,20 @@ int main() { faceDetector.detectMultiScale(frame, faceRectangles, 1.1, 3, 0,cv::Size(20, 20)); foreheadROI = faceRectangles[0]; foreheadROI.height *= 0.3; + cv::Mat frame_forehead = frame(foreheadROI); + cv::Scalar avg_forehead = mean(frame_forehead); + bool isBufferFull = false; + int sampleIdBuffer = 0; + cv::Mat greenSignal(1, FPS*BUFFER_DURATION, CV_64F); + if (!isBufferFull) + { + greenSignal.at(0, sampleIdBuffer) = avg_forehead[1] ; + sampleIdBuffer++; + if (sampleIdBuffer == FPS*BUFFER_DURATION) + { + isBufferFull = true; + } + } cv::rectangle(frame, faceRectangles[0], cv::Scalar(0, 0, 255), 1, 1, 0); cv::rectangle(frame, foreheadROI, cv::Scalar(0, 255, 0), 1, 1, 0); cv::imshow("Color", frame); From c4e8ca8013de8f75ed5b35c28be928e84c07c9ac Mon Sep 17 00:00:00 2001 From: "ly.pechvattana" Date: Fri, 24 Feb 2023 12:10:54 +0100 Subject: [PATCH 2/2] last version --- ppg.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/ppg.cpp b/ppg.cpp index 198839c..0ba5961 100644 --- a/ppg.cpp +++ b/ppg.cpp @@ -3,14 +3,33 @@ #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" -const int FPS = 30; +const int FPS = 5; bool isDiscardData = true; int countDiscard = 0; const int DISCARD_DURATION = 10; -const int BUFFER_DURATION = 60; +const int BUFFER_DURATION = 10; +const int I = 1; + +template + cv::Mat plotGraph(std::vector& vals, const double* YRange) + { + auto it = minmax_element(vals.begin(), vals.end()); + float scale = 1./ceil(*it.second - *it.first); + float bias = *it.first; + int rows = YRange[1] - YRange[0] + 1; + cv::Mat image = 255*cv::Mat::ones( rows, vals.size(), CV_8UC3 ); + image.setTo(255); + for (int i = 0; i < (int)vals.size()-1; i++) + { + cv::line(image, cv::Point(i, rows - 1 - (vals[i] -bias)*scale*YRange[1]), cv::Point(i+1, rows - 1 - (vals[i+1] - + bias)*scale*YRange[1]), cv::Scalar(255, 0, 0), 1); + } + return image; + } + int main() { cv::VideoCapture cap; cap.open(0); @@ -41,25 +60,67 @@ int main() { } std::vector faceRectangles; faceDetector.detectMultiScale(frame, faceRectangles, 1.1, 3, 0,cv::Size(20, 20)); - foreheadROI = faceRectangles[0]; - foreheadROI.height *= 0.3; - cv::Mat frame_forehead = frame(foreheadROI); - cv::Scalar avg_forehead = mean(frame_forehead); - bool isBufferFull = false; - int sampleIdBuffer = 0; - cv::Mat greenSignal(1, FPS*BUFFER_DURATION, CV_64F); - if (!isBufferFull) - { - greenSignal.at(0, sampleIdBuffer) = avg_forehead[1] ; - sampleIdBuffer++; - if (sampleIdBuffer == FPS*BUFFER_DURATION) + + if (faceRectangles.size() > 0) + { + foreheadROI = faceRectangles[0]; + foreheadROI.height *= 0.3; + + cv::rectangle(frame, faceRectangles[0], cv::Scalar(0, 0, 255), 1, 1, 0); + cv::rectangle(frame, foreheadROI, cv::Scalar(0, 255, 0), 1, 1, 0); + + cv::Mat frame_forehead = frame(foreheadROI); + cv::Scalar avg_forehead = mean(frame_forehead); + bool isBufferFull = false; + int sampleIdBuffer = 0; + cv::Mat greenSignal(1, FPS*BUFFER_DURATION, CV_64F); + + if (!isBufferFull) { - isBufferFull = true; + greenSignal.at(0, sampleIdBuffer) = avg_forehead[1] ; + sampleIdBuffer++; + if (sampleIdBuffer == FPS*BUFFER_DURATION) + { + isBufferFull = true; + } } + else + { + std::vector greenSignalNormalized; + cv::Scalar mean, stddev; + cv::meanStdDev(greenSignal, mean, stddev); + for (int l_sample=0; l_sample < FPS*BUFFER_DURATION; l_sample++) + { + greenSignalNormalized.push_back((greenSignal.at(0, l_sample) - + mean[0])/stddev[0]); + } + cv::Mat greenFFT; + std::vector greenFFTModule; + cv::dft(greenSignalNormalized,greenFFT,cv::DFT_ROWS|cv::DFT_COMPLEX_OUTPUT); + cv::Mat planes[] = {cv::Mat::zeros(greenSignalNormalized.size(),1, CV_64F), + cv::Mat::zeros(greenSignalNormalized.size(),1, CV_64F)}; + cv::split(greenFFT, planes); // planes[0] = Re(DFT(I), + // planes[1] = Im(DFT(I)) + greenFFTModule.clear(); + for (int l=0; l < planes[1].cols; l++) + { + double moduleFFT = pow(planes[1].at(0,l),2) + + pow(planes[0].at(0,l),2); + greenFFTModule.push_back(sqrt(moduleFFT)); + } + // display green FFT + const double range[2] = {0.0, 150.0}; + cv::imshow("FFT module green", plotGraph(greenFFTModule, range)); + } - cv::rectangle(frame, faceRectangles[0], cv::Scalar(0, 0, 255), 1, 1, 0); - cv::rectangle(frame, foreheadROI, cv::Scalar(0, 255, 0), 1, 1, 0); + + + } + + cv::imshow("Color", frame); + // int range[2] = {0, (int)(FPS*BUFFER_DURATION)}; + // cv::imshow("green", plotGraph(greenSignalNormalized, range)); if (cv::waitKey(1000.0 / FPS) >= 0) break; }