diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index ab213947e..f9ba91892 100755 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -626,6 +626,13 @@ SET(UT_FILES SET(SAMPLE_UT_FILES test/utmain.cpp test/test_utils.cpp + test/test_utils.h + ../samples/face_detection_cpu/test_face_detection_cpu.cpp +) + +SET(SAMPLE_CORE_FILES + ../samples/face_detection_cpu/face_detection_cpu.h + ../samples/face_detection_cpu/face_detection_cpu.cpp test/test_utils.h ../samples/create_thumbnail_from_mp4_video/test_generate_thumbnail_from_mp4_video.cpp ../samples/play_mp4_from_beginning/test_play_mp4_video_from_beginning.cpp @@ -645,6 +652,7 @@ SET(SAMPLE_SOURCE ${SAMPLE_CORE_FILES} ${SAMPLE_UT_FILES} ) + IF(ENABLE_LINUX) list(APPEND UT_FILES test/gtkglrenderer_tests.cpp @@ -660,6 +668,17 @@ ENDIF(ENABLE_LINUX) add_executable(aprapipesut ${UT_FILES}) add_executable(aprapipessampleut ${SAMPLE_SOURCE}) +target_include_directories ( aprapipessampleut PRIVATE + ${JETSON_MULTIMEDIA_LIB_INCLUDE} + ${FFMPEG_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${LIBMP4_INC_DIR} + ${BARESIP_INC_DIR} + ${LIBRE_INC_DIR} + ${NVCODEC_INCLUDE_DIR} + test + IF(ENABLE_ARM64) target_include_directories ( aprapipesut PRIVATE ${JETSON_MULTIMEDIA_LIB_INCLUDE} ${FFMPEG_ROOT} ${JPEG_INCLUDE_DIR}) ENDIF(ENABLE_ARM64) @@ -695,13 +714,36 @@ ENDIF (ENABLE_CUDA) find_library(OPENH264_LIB NAMES openh264.lib libopenh264.a REQUIRED) find_library(LIBMP4_LIB NAMES mp4lib.lib libmp4lib.a REQUIRED) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../samples ${CMAKE_CURRENT_BINARY_DIR}/samples) + target_link_libraries(aprapipessampleut aprapipes + ${JPEG_LIBRARIES} + +target_link_libraries(aprapipessampleut + aprapipes ${LIBMP4_LIB} ${OPENH264_LIB} ${Boost_LIBRARIES} ${FFMPEG_LIBRARIES} ${OpenCV_LIBRARIES} + ${JETSON_LIBS} + ${NVCUDAToolkit_LIBS} + ${NVCODEC_LIB} + ${NVJPEGLIB_L4T} + ${CURSES_LIBRARIES} + ZXing::Core + ZXing::ZXing + BZip2::BZip2 + ZLIB::ZLIB + liblzma::liblzma + bigint::bigint + sfml-audio + whisper::whisper + ) + + target_link_libraries(aprapipesut ${NVCUDAToolkit_LIBS} ${NVCODEC_LIB} ) @@ -718,7 +760,7 @@ IF(ENABLE_LINUX) ) ENDIF(ENABLE_LINUX) -target_link_libraries(aprapipesut +target_link_libraries(aprapipesut aprapipes ${GLEW_LIBRARIES} ${JPEG_LIBRARIES} @@ -748,6 +790,7 @@ IF(ENABLE_WINDOWS) IF(GHA) file(COPY ${RUNTIME_DLLS} DESTINATION RelWithDebInfo/) ENDIF(GHA) + ENDIF(ENABLE_WINDOWS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../samples ${CMAKE_CURRENT_BINARY_DIR}/samples) @@ -785,4 +828,4 @@ install( DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/aprapipes) install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aprapipes) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aprapipes) \ No newline at end of file diff --git a/base/include/FaceDetectorXform.h b/base/include/FaceDetectorXform.h index bbbca3ebc..9ccf07e46 100644 --- a/base/include/FaceDetectorXform.h +++ b/base/include/FaceDetectorXform.h @@ -6,11 +6,14 @@ class FaceDetectorXformProps : public ModuleProps { public: - FaceDetectorXformProps(double _scaleFactor = 1.0, float _confidenceThreshold = 0.5) : scaleFactor(_scaleFactor), confidenceThreshold(_confidenceThreshold) + FaceDetectorXformProps(double _scaleFactor = 1.0, float _confidenceThreshold = 0.5, std::string _Face_Detection_Configuration= "./data/assets/deploy.prototxt", std::string _Face_Detection_Weights= "./data/assets/res10_300x300_ssd_iter_140000_fp16.caffemodel") + : scaleFactor(_scaleFactor), confidenceThreshold(_confidenceThreshold), FACE_DETECTION_CONFIGURATION(_Face_Detection_Configuration), FACE_DETECTION_WEIGHTS(_Face_Detection_Weights) { } double scaleFactor; float confidenceThreshold; + std::string FACE_DETECTION_CONFIGURATION; + std::string FACE_DETECTION_WEIGHTS; size_t getSerializeSize() { diff --git a/base/include/FacialLandmarksCV.h b/base/include/FacialLandmarksCV.h index ef52acbaa..3f94b1a0c 100644 --- a/base/include/FacialLandmarksCV.h +++ b/base/include/FacialLandmarksCV.h @@ -81,4 +81,5 @@ class FacialLandmarkCV : public Module FacialLandmarkCVProps mProp; bool handlePropsChange(frame_sp& frame); std::string mOutputPinId1; + std::string rawFramePinId; }; \ No newline at end of file diff --git a/base/src/FaceDetectorXform.cpp b/base/src/FaceDetectorXform.cpp index 9fc912cfb..84f2836b2 100644 --- a/base/src/FaceDetectorXform.cpp +++ b/base/src/FaceDetectorXform.cpp @@ -11,6 +11,7 @@ #include "AIPExceptions.h" #include "ApraFaceInfo.h" #include "FaceDetectsInfo.h" +#include "Overlay.h" class FaceDetectorXform::Detail { @@ -34,13 +35,12 @@ class FaceDetectorXform::Detail framemetadata_sp mOutputMetadata; FaceDetectorXformProps mProps; std::string mOutputPinId; + std::string rawFramePinId; cv::Mat mInputImg; int mFrameType; cv::dnn::Net network; cv::Mat inputBlob; cv::Mat detection; - const std::string FACE_DETECTION_CONFIGURATION = "./data/assets/deploy.prototxt"; - const std::string FACE_DETECTION_WEIGHTS = "./data/assets/res10_300x300_ssd_iter_140000_fp16.caffemodel"; // scalar with mean values which are subtracted from channels. // Values are intended to be in (mean-R, mean-G, mean-B) order if image has BGR ordering and swapRB is true. const cv::Scalar meanValuesRGB = cv::Scalar({104., 177.0, 123.0}); @@ -75,7 +75,7 @@ bool FaceDetectorXform::validateInputPins() bool FaceDetectorXform::validateOutputPins() { - if (getNumberOfOutputPins() != 1) + if (getNumberOfOutputPins() > 2) { LOG_ERROR << "<" << getId() << ">::validateOutputPins size is expected to be 1. Actual<" << getNumberOfOutputPins() << ">"; return false; @@ -88,11 +88,12 @@ void FaceDetectorXform::addInputPin(framemetadata_sp &metadata, string &pinId) Module::addInputPin(metadata, pinId); mDetail->mOutputMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::FACEDETECTS_INFO)); mDetail->mOutputPinId = addOutputPin(mDetail->mOutputMetadata); + mDetail->rawFramePinId = addOutputPin(metadata); } bool FaceDetectorXform::init() { - mDetail->network = cv::dnn::readNetFromCaffe(mDetail->FACE_DETECTION_CONFIGURATION, mDetail->FACE_DETECTION_WEIGHTS); + mDetail->network = cv::dnn::readNetFromCaffe(mDetail->mProps.FACE_DETECTION_CONFIGURATION, mDetail->mProps.FACE_DETECTION_WEIGHTS); if (mDetail->network.empty()) { LOG_ERROR << "Failed to load network with the given settings. Please check the loaded parameters."; @@ -121,11 +122,14 @@ bool FaceDetectorXform::process(frame_container &frames) mDetail->inputBlob = cv::dnn::blobFromImage(mDetail->mInputImg, mDetail->mProps.scaleFactor, cv::Size(mDetail->mInputImg.cols, mDetail->mInputImg.rows), mDetail->meanValuesRGB, false, false); mDetail->network.setInput(mDetail->inputBlob, "data"); - + mDetail->detection = mDetail->network.forward("detection_out"); cv::Mat detectionMatrix(mDetail->detection.size[2], mDetail->detection.size[3], CV_32F, mDetail->detection.ptr()); + std::vector rectangleOverlays; + CompositeOverlay compositeOverlay; + for (int i = 0; i < detectionMatrix.rows; i++) { float confidence = detectionMatrix.at(i, 2); @@ -136,20 +140,42 @@ bool FaceDetectorXform::process(frame_container &frames) } mDetail->faceInfo.x1 = detectionMatrix.at(i, 3) * mDetail->mInputImg.cols; - mDetail->faceInfo.y2 = detectionMatrix.at(i, 4) * mDetail->mInputImg.rows; + mDetail->faceInfo.y1 = detectionMatrix.at(i, 4) * mDetail->mInputImg.rows; mDetail->faceInfo.x2 = detectionMatrix.at(i, 5) * mDetail->mInputImg.cols; - mDetail->faceInfo.y1 = detectionMatrix.at(i, 6) * mDetail->mInputImg.rows; + mDetail->faceInfo.y2 = detectionMatrix.at(i, 6) * mDetail->mInputImg.rows; mDetail->faceInfo.score = confidence; mDetail->faces.emplace_back(mDetail->faceInfo); + + RectangleOverlay rectangleOverlay; + rectangleOverlay.x1 = mDetail->faceInfo.x1; + rectangleOverlay.y1 = mDetail->faceInfo.y1; + rectangleOverlay.x2 = mDetail->faceInfo.x2; + rectangleOverlay.y2 = mDetail->faceInfo.y2; + rectangleOverlays.push_back(rectangleOverlay); } + for (auto &rectangleOverlay : rectangleOverlays) { + compositeOverlay.add(&rectangleOverlay); + } + + auto rawFrame = frames.cbegin()->second; + frames.insert(make_pair(mDetail->rawFramePinId, rawFrame)); + mDetail->faceDetectsInfo.faces = mDetail->faces; - auto outFrame = makeFrame(mDetail->faceDetectsInfo.getSerializeSize()); - mDetail->faceDetectsInfo.serialize(outFrame->data(), mDetail->faceDetectsInfo.getSerializeSize()); - frames.insert(make_pair(mDetail->mOutputPinId, outFrame)); + + if (rectangleOverlays.size() > 0) { + DrawingOverlay drawingOverlay; + drawingOverlay.add(&compositeOverlay); + auto mvSize = drawingOverlay.mGetSerializeSize(); + auto outFrame = makeFrame(mvSize, mDetail->mOutputPinId); + drawingOverlay.serialize(outFrame); + frames.insert(make_pair(mDetail->mOutputPinId, outFrame)); + } + mDetail->faces.clear(); mDetail->faceDetectsInfo.faces.clear(); + send(frames); return true; } diff --git a/base/src/FacialLandmarksCV.cpp b/base/src/FacialLandmarksCV.cpp index a9ef0ce5a..02b55b1cd 100644 --- a/base/src/FacialLandmarksCV.cpp +++ b/base/src/FacialLandmarksCV.cpp @@ -12,6 +12,7 @@ #include "Logger.h" #include "Utils.h" #include "AIPExceptions.h" +#include "Overlay.h" class Detail { @@ -87,6 +88,7 @@ class Detail FacialLandmarkCVProps props; cv::Mat iImg; vector>landmarks; + vector faces; protected: framemetadata_sp mInputMetadata; @@ -113,6 +115,7 @@ class DetailSSD : public Detail { //input must be 3 channel image(RGB) // Create a 4-dimensional blob from the image. Optionally resizes and crops image from center, subtract mean values, scales values by scalefactor, swap Blue and Red channels. + iImg.data = static_cast(buffer->data()); cv::Mat inputBlob = cv::dnn::blobFromImage(iImg, 1.0, cv::Size(300, 300), cv::Scalar(104, 177, 123), false, false); // Set the input blob as input to the face detector network @@ -123,8 +126,6 @@ class DetailSSD : public Detail cv::Mat detectionMatrix(detection.size[2], detection.size[3], CV_32F, detection.ptr()); - vector faces; - for (int i = 0; i < detectionMatrix.rows; i++) { float confidence = detectionMatrix.at(i, 2); @@ -139,13 +140,16 @@ class DetailSSD : public Detail cv::Rect faceRect(x1, y1, x2 - x1, y2 - y1); faces.push_back(faceRect); - cv::rectangle(iImg, faceRect, cv::Scalar(0, 255, 0), 2); } } + if (faces.size() == 0) { + return false; + } + bool success = facemark->fit(iImg, faces, landmarks); - return true; + return success; } private: @@ -164,17 +168,15 @@ class DetailHCASCADE : public Detail bool compute(frame_sp buffer) { - vector faces; faceDetector.detectMultiScale(iImg, faces); - for (int i = 0; i < faces.size(); i++) - { - rectangle(iImg, faces[i], cv::Scalar(0, 255, 0), 2); + if (faces.size() == 0) { + return false; } - bool success = facemark->fit(iImg, faces, landmarks); - - return true; + bool success = facemark->fit(iImg, faces, landmarks); + + return success; } private: @@ -243,6 +245,7 @@ void FacialLandmarkCV::addInputPin(framemetadata_sp &metadata, string &pinId) Module::addInputPin(metadata, pinId); auto landmarksOutputMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::FACE_LANDMARKS_INFO)); mOutputPinId1 = addOutputPin(landmarksOutputMetadata); + rawFramePinId = addOutputPin(metadata); } bool FacialLandmarkCV::init() @@ -278,8 +281,26 @@ bool FacialLandmarkCV::term() bool FacialLandmarkCV::process(frame_container& frames) { auto frame = frames.cbegin()->second; + bool computeValue = mDetail->compute(frame); + + if (computeValue == false) { + send(frames); + return true; + } + + std::vector rectangleOverlays; + + for (const auto& face :mDetail->faces) { + RectangleOverlay rectangleOverlay; + rectangleOverlay.x1 = face.x; + rectangleOverlay.y1 = face.y; + rectangleOverlay.x2 = face.x + face.width; + rectangleOverlay.y2 = face.y + face.height; - mDetail->compute(frame); + rectangleOverlays.push_back(rectangleOverlay); + } + + std::vector circleOverlays; // Convert the landmarks from cv::Point2f to ApraPoint2f vector> apralandmarks; @@ -287,6 +308,13 @@ bool FacialLandmarkCV::process(frame_container& frames) vector apralandmark; for (const auto& point : landmark) { apralandmark.emplace_back(ApraPoint2f(point)); + + CircleOverlay circleOverlay; + circleOverlay.x1 = point.x; + circleOverlay.y1 = point.y; + circleOverlay.radius = 1; + + circleOverlays.push_back(circleOverlay); } apralandmarks.emplace_back(std::move(apralandmark)); } @@ -297,11 +325,31 @@ bool FacialLandmarkCV::process(frame_container& frames) bufferSize += sizeof(apralandmarks[i]) + (sizeof(ApraPoint2f) + 2 * sizeof(int)) * apralandmarks[i].size(); } - auto landmarksFrame = makeFrame(bufferSize); + CompositeOverlay compositeOverlay; - Utils::serialize>>(apralandmarks, landmarksFrame->data(), bufferSize); + for (auto &rectangleOverlay : rectangleOverlays) { + compositeOverlay.add(&rectangleOverlay); + } + + for (auto &circleOverlay : circleOverlays) { + compositeOverlay.add(&circleOverlay); + } + + auto rawFrame = frames.cbegin()->second; + + frames.insert(make_pair(rawFramePinId, rawFrame)); + + if (rectangleOverlays.size() > 0 || circleOverlays.size() > 0) { + DrawingOverlay drawingOverlay; + drawingOverlay.add(&compositeOverlay); + auto mvSize = drawingOverlay.mGetSerializeSize(); + auto landmarksFrame = makeFrame(mvSize, mOutputPinId1); + drawingOverlay.serialize(landmarksFrame); + frames.insert(make_pair(mOutputPinId1, landmarksFrame)); + } - frames.insert(make_pair(mOutputPinId1, landmarksFrame)); + mDetail->faces.clear(); + mDetail->landmarks.clear(); send(frames); diff --git a/base/src/OverlayModule.cpp b/base/src/OverlayModule.cpp index c0ea6a0fa..a76ba4776 100644 --- a/base/src/OverlayModule.cpp +++ b/base/src/OverlayModule.cpp @@ -32,7 +32,7 @@ bool OverlayModule::validateInputPins() BOOST_FOREACH(me, inputMetadataByPin) { FrameMetadata::FrameType frameType = me.second->getFrameType(); - if (frameType != FrameMetadata::RAW_IMAGE && frameType != FrameMetadata::OVERLAY_INFO_IMAGE) + if (frameType != FrameMetadata::RAW_IMAGE && frameType != FrameMetadata::OVERLAY_INFO_IMAGE && frameType != FrameMetadata::FACE_LANDMARKS_INFO && frameType != FrameMetadata::FACEDETECTS_INFO) { LOG_ERROR << "<" << getId() << ">::validateInputPins input frameType is expected to be RAW_IMAGE OR OVERLAY_INFO_IMAGE. Actual<" << frameType << ">"; return false; @@ -70,8 +70,13 @@ bool OverlayModule::process(frame_container& frames) if (frameType == FrameMetadata::OVERLAY_INFO_IMAGE) { drawOverlay.deserialize(frame); + } + else if (frameType == FrameMetadata::FACE_LANDMARKS_INFO) { + drawOverlay.deserialize(frame); + } + else if (frameType == FrameMetadata::FACEDETECTS_INFO) { + drawOverlay.deserialize(frame); } - else if (frameType == FrameMetadata::RAW_IMAGE) { drawOverlay.draw(frame); diff --git a/base/test/facedetectorXform_tests.cpp b/base/test/facedetectorXform_tests.cpp index 3b3ae4528..cc04c2903 100644 --- a/base/test/facedetectorXform_tests.cpp +++ b/base/test/facedetectorXform_tests.cpp @@ -13,6 +13,8 @@ #include "ApraFaceInfo.h" #include "FaceDetectsInfo.h" #include "ImageDecoderCV.h" +#include "OverlayModule.h" +#include "ImageViewerModule.h" BOOST_AUTO_TEST_SUITE(facedetector_tests) #ifdef ARM64 @@ -59,6 +61,40 @@ BOOST_AUTO_TEST_CASE(basic) Test_Utils::saveOrCompare("./data/testOutput/facesResult.raw", const_cast(static_cast(frame.data)), frame.step[0] * frame.rows, 0); } +BOOST_AUTO_TEST_CASE(basic_faces) +{ + auto fileReader = boost::shared_ptr(new FileReaderModule(FileReaderModuleProps("./data/faces.jpg"))); + auto metadata = framemetadata_sp(new FrameMetadata(FrameMetadata::ENCODED_IMAGE)); + fileReader->addOutputPin(metadata); + + auto decoder = boost::shared_ptr(new ImageDecoderCV(ImageDecoderCVProps())); + auto metadata2 = framemetadata_sp(new RawImageMetadata()); + decoder->addOutputPin(metadata2); + fileReader->setNext(decoder); + + FaceDetectorXformProps faceDetectorProps; + auto faceDetector = boost::shared_ptr(new FaceDetectorXform(faceDetectorProps)); + decoder->setNext(faceDetector); + + auto overlay = boost::shared_ptr(new OverlayModule(OverlayModuleProps())); + faceDetector->setNext(overlay); + + auto sink = boost::shared_ptr(new ImageViewerModule(ImageViewerModuleProps("imageview"))); + overlay->setNext(sink); + + PipeLine p("test"); + p.appendModule(fileReader); + p.init(); + + p.run_all_threaded(); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + + LOG_INFO << "profiling done - stopping the pipeline"; + p.stop(); + p.term(); + p.wait_for_all(); +} + BOOST_AUTO_TEST_CASE(serialization_test) { diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index a9ff6823f..c2f9918a3 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) +add_subdirectory(face_detection_cpu) add_subdirectory(create_thumbnail_from_mp4_video) add_subdirectory(play_mp4_from_beginning) -add_subdirectory(timelapse-sample) +add_subdirectory(timelapse-sample) \ No newline at end of file diff --git a/samples/face_detection_cpu/CMakeLists.txt b/samples/face_detection_cpu/CMakeLists.txt new file mode 100644 index 000000000..97cdd62de --- /dev/null +++ b/samples/face_detection_cpu/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.22) +set(TARGET face_detection_cpu) +SET(SAMPLE_FILES + face_detection_cpu.cpp + pipelineMain.cpp +) +SET(SAMPLE_FILES_H + face_detection_cpu.h +) +SET(SOURCE + ${SAMPLE_FILES} + ${SAMPLE_FILES_H} +) + +add_executable(${TARGET} ${SOURCE}) + +target_include_directories ( ${TARGET} PRIVATE + ${OpenCV_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} +) + +target_link_libraries( + ${TARGET} + aprapipes + ${JPEG_LIBRARIES} + ${Boost_LIBRARIES} + ${OpenCV_LIBRARIES} + ) \ No newline at end of file diff --git a/samples/face_detection_cpu/face_detection_cpu.cpp b/samples/face_detection_cpu/face_detection_cpu.cpp new file mode 100644 index 000000000..a24f5a2ba --- /dev/null +++ b/samples/face_detection_cpu/face_detection_cpu.cpp @@ -0,0 +1,44 @@ +#include "WebCamSource.h" +#include "ImageViewerModule.h" +#include "face_detection_cpu.h" +#include "OverlayModule.h" +#include "ImageDecoderCV.h" +#include "FaceDetectorXform.h" +#include "ColorConversionXForm.h" +#include + +FaceDetectionCPU::FaceDetectionCPU() : faceDetectionCPUSamplePipeline("faceDetectionCPUSamplePipeline") {} + +bool FaceDetectionCPU::setupPipeline(const int &cameraId, const double &scaleFactor, const double &threshold, const std::string &faceDetectionConfiguration, const std::string &faceDetectionWeight) { + WebCamSourceProps webCamSourceprops(cameraId); + mSource = boost::shared_ptr(new WebCamSource(webCamSourceprops)); + + FaceDetectorXformProps faceDetectorProps(scaleFactor, threshold, faceDetectionConfiguration, faceDetectionWeight); + mFaceDetector = boost::shared_ptr(new FaceDetectorXform(faceDetectorProps)); + mSource->setNext(mFaceDetector); + + mOverlay = boost::shared_ptr(new OverlayModule(OverlayModuleProps())); + mFaceDetector->setNext(mOverlay); + + mColorConversion = boost::shared_ptr(new ColorConversion(ColorConversionProps(ColorConversionProps::RGB_TO_BGR))); + mOverlay->setNext(mColorConversion); + + mImageViewerSink = boost::shared_ptr(new ImageViewerModule(ImageViewerModuleProps("imageview"))); + mColorConversion->setNext(mImageViewerSink); + + return true; +} + +bool FaceDetectionCPU::startPipeline() { + faceDetectionCPUSamplePipeline.appendModule(mSource); + faceDetectionCPUSamplePipeline.init(); + faceDetectionCPUSamplePipeline.run_all_threaded(); + return true; +} + +bool FaceDetectionCPU::stopPipeline() { + faceDetectionCPUSamplePipeline.stop(); + faceDetectionCPUSamplePipeline.term(); + faceDetectionCPUSamplePipeline.wait_for_all(); + return true; +} \ No newline at end of file diff --git a/samples/face_detection_cpu/face_detection_cpu.h b/samples/face_detection_cpu/face_detection_cpu.h new file mode 100644 index 000000000..3d6360962 --- /dev/null +++ b/samples/face_detection_cpu/face_detection_cpu.h @@ -0,0 +1,23 @@ +#include +#include "WebCamSource.h" +#include "ImageViewerModule.h" +#include "OverlayModule.h" +#include "FacialLandmarksCV.h" +#include "ImageDecoderCV.h" +#include "FaceDetectorXform.h" +#include "ColorConversionXForm.h" + +class FaceDetectionCPU { +public: + FaceDetectionCPU(); + bool setupPipeline(const int &cameraId, const double &scaleFactor, const double &threshold, const std::string &faceDetectionConfiguration, const std::string &faceDetectionWeight); + bool startPipeline(); + bool stopPipeline(); +private: + PipeLine faceDetectionCPUSamplePipeline; + boost::shared_ptr mSource; + boost::shared_ptr mFaceDetector; + boost::shared_ptr mOverlay; + boost::shared_ptr mColorConversion; + boost::shared_ptr mImageViewerSink; +}; \ No newline at end of file diff --git a/samples/face_detection_cpu/pipelineMain.cpp b/samples/face_detection_cpu/pipelineMain.cpp new file mode 100644 index 000000000..3f35b8687 --- /dev/null +++ b/samples/face_detection_cpu/pipelineMain.cpp @@ -0,0 +1,22 @@ +#include "face_detection_cpu.h" +#include +#include + +void main() { + FaceDetectionCPU faceDetectionCPUSamplePipeline; + if (!faceDetectionCPUSamplePipeline.setupPipeline(0, 1.0, 0.7, "../../data/assets/deploy.prototxt", "../../data/assets/res10_300x300_ssd_iter_140000_fp16.caffemodel")) { + std::cerr << "Failed to setup pipeline." << std::endl; + } + + if (!faceDetectionCPUSamplePipeline.startPipeline()) { + std::cerr << "Failed to start pipeline." << std::endl; + } + + // Wait for the pipeline to run for 10 seconds + boost::this_thread::sleep_for(boost::chrono::seconds(50)); + + // Stop the pipeline + if (!faceDetectionCPUSamplePipeline.stopPipeline()) { + std::cerr << "Failed to stop pipeline." << std::endl; + } +} \ No newline at end of file diff --git a/samples/face_detection_cpu/test_face_detection_cpu.cpp b/samples/face_detection_cpu/test_face_detection_cpu.cpp new file mode 100644 index 000000000..6440070d2 --- /dev/null +++ b/samples/face_detection_cpu/test_face_detection_cpu.cpp @@ -0,0 +1,18 @@ +#include + +#include "face_detection_cpu.h" + +BOOST_AUTO_TEST_SUITE(test_face_detection_cpu) + +BOOST_AUTO_TEST_CASE(face_detection_cpu) +{ + auto faceDetectionCPUPipeline = boost::shared_ptr(new FaceDetectionCPU()); + faceDetectionCPUPipeline->setupPipeline(0, 1.0, 0.7, "./data/assets/deploy.prototxt", "./data/assets/res10_300x300_ssd_iter_140000_fp16.caffemodel"); + faceDetectionCPUPipeline->startPipeline(); + + boost::this_thread::sleep_for(boost::chrono::seconds(25)); + + faceDetectionCPUPipeline->stopPipeline(); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file