diff --git a/include/detection.hpp b/include/detection.hpp index 46930d3..cf66efe 100644 --- a/include/detection.hpp +++ b/include/detection.hpp @@ -1,14 +1,32 @@ #pragma once - +#include #include #include -#include "opencv2/core/core.hpp" +#include +#include +#include +#include + +using namespace std; +using namespace cv; class Detector { public: static std::shared_ptr CreateDetector(const std::string& name); + virtual bool Init(const std::string& model_file_path) = 0; virtual void Detect(const cv::Mat& frame, std::vector& objects, std::vector& scores) = 0; }; + +class CascadeDetector : public Detector { +public: + virtual bool Init(const std::string& model_file_path); + virtual void Detect(const cv::Mat& frame, std::vector& objects, + std::vector& scores); + +protected: + cv::CascadeClassifier detector; +}; + diff --git a/include/image_processing.hpp b/include/image_processing.hpp index ca1f116..690c2c5 100644 --- a/include/image_processing.hpp +++ b/include/image_processing.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "opencv2/core/core.hpp" @@ -15,4 +16,69 @@ class ImageProcessor { const int kernelSize) = 0; virtual cv::Mat Pixelize(const cv::Mat &src, const cv::Rect &roi, const int kDivs) = 0; -}; \ No newline at end of file +}; + +class ImageProcessorImpl : public ImageProcessor { +public: + cv::Mat CvtColor(const cv::Mat &src, const cv::Rect &roi) override { + + cv::Mat src_copy; + src.copyTo(src_copy); + cv::Mat src_copy_roi = src_copy(roi); + cv::Mat dst_gray_roi; + cv::cvtColor(src_copy_roi, dst_gray_roi, CV_BGR2GRAY); + std::vector channels(3); + + std::fill(channels.begin(), channels.end(), dst_gray_roi); + cv::Mat dst_roi; + cv::merge(channels, dst_roi); + dst_roi.copyTo(src_copy_roi); + return src_copy; + } + + cv::Mat Filter(const cv::Mat &src, const cv::Rect &roi, const int kSize) override { + cv::Mat src_copy; + src.copyTo(src_copy); + cv::Mat src_copy_roi = src_copy(roi); + cv::medianBlur(src_copy_roi, src_copy_roi, kSize); + return src_copy; + } + + cv::Mat + DetectEdges(const cv::Mat &src, const cv::Rect &roi, const int filterSize, const int lowThreshold, const int ratio, + const int kernelSize) override { + cv::Mat src_copy; + src.copyTo(src_copy); + cv::Mat src_roi = src_copy(roi); + cv::Mat src_gray_roi; + cv::cvtColor(src_roi, src_gray_roi, CV_BGR2GRAY); + cv::Mat detected_edges; + cv::blur(src_gray_roi, src_gray_roi, cv::Size(filterSize, filterSize)); + cv::Canny(src_gray_roi, detected_edges, lowThreshold, lowThreshold + ratio, kernelSize); + cv::Mat dst; + src.copyTo(dst); + cv::Mat dst_roi = dst(roi); + dst_roi = cv::Scalar::all(0); + src_roi.copyTo(dst_roi, detected_edges); + return dst; + } + + cv::Mat Pixelize(const cv::Mat &src, const cv::Rect &roi, const int kDivs) override { + cv::Mat src_copy; + src.copyTo(src_copy); + cv::Mat src_copy_roi = src_copy(roi); + int block_size_x = roi.width / kDivs; + int block_size_y = roi.height / kDivs; + for (int i = 0; i < src_copy_roi.rows; i += block_size_y) + for (int j = 0; j < src_copy_roi.cols; j += block_size_x) { + cv::Mat src_roi_block = src_copy_roi(cv::Rect(j, i, + j + block_size_x <= src_copy_roi.cols ? + block_size_x : src_copy_roi.cols - j, + i + block_size_y <= src_copy_roi.rows ? + block_size_y : src_copy_roi.rows - i)); + + cv::blur(src_roi_block, src_roi_block, cv::Size(block_size_x, block_size_y)); + } + return src_copy; + } +}; diff --git a/samples/detection_demo.cpp b/samples/detection_demo.cpp new file mode 100644 index 0000000..c538291 --- /dev/null +++ b/samples/detection_demo.cpp @@ -0,0 +1,96 @@ +#include +#include "detection.hpp" + + +using namespace std; +using namespace cv; + +const char* kOptions = + "{ i image | | image to process }" + "{ v video | | video to process }" + "{ c camera | | camera to get video from }" + "{ m model | | path to detector file }" + "{ h ? help usage | | print help message }"; + +int main(int argc, const char** argv) { + // Parse command line arguments. + CommandLineParser parser(argc, argv, kOptions); + + // If help option is given, print help message and exit. + if (parser.get("help")) { + parser.printMessage(); + return 0; + } + + CascadeDetector detector; + //("../test/test_data/detection/cascades/intel_logo_cascade.xml"); + detector.Init("/home/luba/github/itseez-ss-2016-practice/test/test_data/detection/cascades/unn_old_logo_cascade.xml"); + + cv::Mat frame1; + std::vector objects; + std::vector scores; + + /*if(parser.has("v")){ + std::string filePath; + filePath = parser.get("v"); + cv::VideoCapture video(filePath); + + while(true){ + video >> frame1; + detector.Detect(frame1, objects, scores); + } + } + else if(parser.has("i")){ + std::string filePath; + filePath = parser.get("i"); + cv::Mat input = cv::imread(filePath); + detector.Detect(input, objects, scores); + } + else if(parser.has("c")){ + + CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY); + assert( capture ); + IplImage* frame=0; + cvNamedWindow("capture", CV_WINDOW_AUTOSIZE); + printf("[i] press Esc for quit!\n\n"); + while(true) {// получаем кадр + frame = cvQueryFrame(capture); + detector.Detect(frame1, objects, scores); + cvShowImage("capture", frame); + char c = cvWaitKey(33); + if (c == 27) { // нажата ESC + break; + } + } + cvReleaseCapture( &capture ); + cvDestroyWindow("capture"); + } + else if(parser.has("m")){ + std::string filePathDetector; + filePathDetector = parser.has("m"); + detector.Init( filePathDetector); + }*/ + + CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY); + assert( capture ); + IplImage* frame=0; + cvNamedWindow("capture", CV_WINDOW_AUTOSIZE); + printf("[i] press Esc for quit!\n\n"); + while(true) {// получаем кадр + frame = cvQueryFrame(capture); + detector.Detect(frame1, objects, scores); + cvShowImage("capture", frame); + char c = cvWaitKey(33); + if (c == 27) { // нажата ESC + break; + } + } + cvReleaseCapture( &capture ); + cvDestroyWindow("capture"); + + + + return 0; +} + + diff --git a/samples/imgproc_demo.cpp b/samples/imgproc_demo.cpp new file mode 100644 index 0000000..855ee5d --- /dev/null +++ b/samples/imgproc_demo.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +const char* kOptions = + "{ @image | | image to process }" + "{ gray | | convert ROI to gray scale }" + "{ median | | apply median filter for ROI }" + "{ edges | | detect edges in ROI }" + "{ pix | | pixelize ROI }" + "{ h ? help usage | | print help message }"; +struct MouseCallbackState { + bool is_selection_started; + bool is_selection_finished; + Point point_first; + Point point_second; +} mouseCallbackState; +void onMouse(int event, int x, int y, int flag, void* param) +{ + if(event == cv::EVENT_LBUTTONDOWN) + { + mouseCallbackState.is_selection_started = true; + mouseCallbackState.is_selection_finished = false; + mouseCallbackState.point_first = cv::Point(x, y); + } + if(event == cv::EVENT_LBUTTONUP) + { + mouseCallbackState.is_selection_started = false; + mouseCallbackState.is_selection_finished = true; + mouseCallbackState.point_second = cv::Point(x, y); + } + if(event == cv::EVENT_MOUSEMOVE && !mouseCallbackState.is_selection_finished) + { + mouseCallbackState.point_second = cv::Point(x, y); + } +} + +int main(int argc, const char** argv) { + // Parse command line arguments. + CommandLineParser parser(argc, argv, kOptions); + + // If help option is given, print help message and exit. + if (parser.get("help")) { + parser.printMessage(); + return 0; + } + + + // Do something cool. + cv::namedWindow("input"); + cv::setMouseCallback("input", onMouse); + std::string filePath; + if (parser.has("@image")){ + filePath = parser.get("@image"); + } + cv::Mat input = cv::imread(filePath); + cv::Mat input_copy; + cv::Rect rect; + while(true) + { + input.copyTo(input_copy); + + if(mouseCallbackState.is_selection_started && !mouseCallbackState.is_selection_finished) { + rect = cv::Rect(mouseCallbackState.point_first.x, mouseCallbackState.point_first.y, + mouseCallbackState.point_second.x - mouseCallbackState.point_first.x, + mouseCallbackState.point_second.y - mouseCallbackState.point_first.y); + } + cv::rectangle(input_copy, rect, cv::Scalar(255, 0, 100)); + cv::imshow("input", input_copy); + char c = cv::waitKey(33); + if (c == 27) + break; + } + ImageProcessorImpl processor; + + if(parser.has("gray")){ + input = processor.CvtColor(input, rect); + } + else if(parser.has("pix")) { + input = processor.Pixelize(input, rect, 5); + } + else if(parser.has("edges")) { + input = processor.DetectEdges(input, rect, 5, 2, 3, 5); + } + else if(parser.has("median")) { + input = processor.Filter(input, rect, 5); + } + else{ + cerr << "no flag" << endl; + } + cv::imshow("input", input); + cv::waitKey(0); + + return 0; +} diff --git a/src/detection.cpp b/src/detection.cpp index 15e7fd1..bd2e2da 100644 --- a/src/detection.cpp +++ b/src/detection.cpp @@ -1,13 +1,30 @@ -#include "detection.hpp" - #include +#include "detection.hpp" using std::string; using std::shared_ptr; using namespace cv; shared_ptr Detector::CreateDetector(const string& name) { - std::cerr << "Failed to create detector with name '" << name << "'" - << std::endl; - return nullptr; + if (name == "cascade") { + return std::make_shared(); + } +} + + +bool CascadeDetector::Init(const std::string &model_file_path) { + detector.load(model_file_path); + return detector.empty(); +} + +void CascadeDetector::Detect(const cv::Mat &frame, std::vector &objects, std::vector &scores) { + if (!detector.empty() ) { + std::vector sc; + detector.detectMultiScale(frame, objects, sc); + std::copy(sc.begin(), sc.end(), scores.begin()); + } + else { + std::cerr << "Error"; + exit(-1); + } }