diff --git a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp index 4d6db66f28..8c1f29298b 100644 --- a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp @@ -556,9 +556,11 @@ public: // Param image is a frame on which detector will be applied. // Param rois is a vector of regions of interest. Only the objects that fall into one of the regions will be returned. // Param objects is an output array of Detections - virtual void detect(const Mat& image, const std::vector& rois, std::vector& objects) const; + virtual void detect(InputArray image, InputArray rois, std::vector& objects) const; private: + void detectNoRoi(const Mat& image, std::vector& objects) const; + struct Filds; Filds* filds; diff --git a/modules/objdetect/perf/perf_cascadeclassifier.cpp b/modules/objdetect/perf/perf_cascadeclassifier.cpp index cc068e8ea3..f52bd59af1 100644 --- a/modules/objdetect/perf/perf_cascadeclassifier.cpp +++ b/modules/objdetect/perf/perf_cascadeclassifier.cpp @@ -81,13 +81,12 @@ PERF_TEST_P(detect, SCascade, ASSERT_TRUE(fs.isOpened()); ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); - std::vector rois; std::vector objectBoxes; - cascade.detect(colored, rois, objectBoxes); + cascade.detect(colored, cv::noArray(), objectBoxes); TEST_CYCLE() { - cascade.detect(colored, rois, objectBoxes); + cascade.detect(colored, cv::noArray(), objectBoxes); } vector rects; diff --git a/modules/objdetect/src/softcascade.cpp b/modules/objdetect/src/softcascade.cpp index 37ab091666..2f7e697135 100644 --- a/modules/objdetect/src/softcascade.cpp +++ b/modules/objdetect/src/softcascade.cpp @@ -510,16 +510,9 @@ bool cv::SCascade::load(const FileNode& fn) return filds->fill(fn, minScale, maxScale); } -void cv::SCascade::detect(const Mat& image, const std::vector& /*rois*/, std::vector& objects) const +void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector& objects) const { - // only color images are supperted - CV_Assert(image.type() == CV_8UC3); - Filds& fld = *filds; - fld.calcLevels(image.size(), scales); - - objects.clear(); - // create integrals ChannelStorage storage(image, fld.shrinkage); @@ -537,4 +530,49 @@ void cv::SCascade::detect(const Mat& image, const std::vector& /*rois* } } } +} + +void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector& objects) const +{ + // only color images are supperted + cv::Mat image = _image.getMat(); + CV_Assert(image.type() == CV_8UC3); + + Filds& fld = *filds; + fld.calcLevels(image.size(), scales); + + objects.clear(); + + if (_rois.kind() == cv::_InputArray::NONE) + return detectNoRoi(image, objects); + + cv::Mat roi = _rois.getMat(); + cv::Mat mask(image.rows / fld.shrinkage, image.cols / fld.shrinkage, CV_8UC1); + + mask.setTo(cv::Scalar::all(0)); + cv::Rect* r = roi.ptr(0); + for (int i = 0; i < (int)roi.cols; ++i) + cv::Mat(mask, cv::Rect(r[i].x / fld.shrinkage, r[i].y / fld.shrinkage, r[i].width / fld.shrinkage , r[i].height / fld.shrinkage)).setTo(cv::Scalar::all(1)); + + // create integrals + ChannelStorage storage(image, fld.shrinkage); + + typedef std::vector::const_iterator lIt; + for (lIt it = fld.levels.begin(); it != fld.levels.end(); ++it) + { + const Level& level = *it; + + for (int dy = 0; dy < level.workRect.height; ++dy) + { + uchar* m = mask.ptr(dy); + for (int dx = 0; dx < level.workRect.width; ++dx) + { + if (m[dx]) + { + storage.offset = dy * storage.step + dx; + fld.detectAt(dx, dy, level, storage, objects); + } + } + } + } } \ No newline at end of file diff --git a/modules/objdetect/test/test_softcascade.cpp b/modules/objdetect/test/test_softcascade.cpp index f8dec6b45a..d33d5892bf 100644 --- a/modules/objdetect/test/test_softcascade.cpp +++ b/modules/objdetect/test/test_softcascade.cpp @@ -63,36 +63,96 @@ TEST(SCascade, detect) cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/bahnhof/image_00000000_0.png"); ASSERT_FALSE(colored.empty()); + std::vector objects; + + cascade.detect(colored, cv::noArray(), objects); + + // cv::Mat out = colored.clone(); + // int level = 0, total = 0; + // int levelWidth = objects[0].bb.width; + + // for(int i = 0 ; i < (int)objects.size(); ++i) + // { + // if (objects[i].bb.width != levelWidth) + // { + // std::cout << "Level: " << level << " total " << total << std::endl; + // cv::imshow("out", out); + // cv::waitKey(0); + // out = colored.clone(); + // levelWidth = objects[i].bb.width; + // total = 0; + // level++; + // } + // cv::rectangle(out, objects[i].bb, cv::Scalar(255, 0, 0, 255), 1); + // std::cout << "detection: " << objects[i].bb.x + // << " " << objects[i].bb.y + // << " " << objects[i].bb.width + // << " " << objects[i].bb.height << std::endl; + // total++; + // } + // std::cout << "detected: " << (int)objects.size() << std::endl; + ASSERT_EQ((int)objects.size(), 3498); +} + +TEST(SCascade, detectRoi) +{ + typedef cv::SCascade::Detection Detection; + std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/sc_cvpr_2012_to_opencv.xml"; + cv::SCascade cascade; + cv::FileStorage fs(xml, cv::FileStorage::READ); + ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); + + cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/bahnhof/image_00000000_0.png"); + ASSERT_FALSE(colored.empty()); + std::vector objects; std::vector rois; rois.push_back(cv::Rect(0, 0, 640, 480)); cascade.detect(colored, rois, objects); + // cv::Mat out = colored.clone(); + // int level = 0, total = 0; + // int levelWidth = objects[0].bb.width; - cv::Mat out = colored.clone(); - int level = 0, total = 0; - int levelWidth = objects[0].bb.width; - - for(int i = 0 ; i < (int)objects.size(); ++i) - { - if (objects[i].bb.width != levelWidth) - { - std::cout << "Level: " << level << " total " << total << std::endl; - cv::imshow("out", out); - cv::waitKey(0); - out = colored.clone(); - levelWidth = objects[i].bb.width; - total = 0; - level++; - } - cv::rectangle(out, objects[i].bb, cv::Scalar(255, 0, 0, 255), 1); - std::cout << "detection: " << objects[i].bb.x - << " " << objects[i].bb.y - << " " << objects[i].bb.width - << " " << objects[i].bb.height << std::endl; - total++; - } - std::cout << "detected: " << (int)objects.size() << std::endl; + // for(int i = 0 ; i < (int)objects.size(); ++i) + // { + // if (objects[i].bb.width != levelWidth) + // { + // std::cout << "Level: " << level << " total " << total << std::endl; + // cv::imshow("out", out); + // cv::waitKey(0); + // out = colored.clone(); + // levelWidth = objects[i].bb.width; + // total = 0; + // level++; + // } + // cv::rectangle(out, objects[i].bb, cv::Scalar(255, 0, 0, 255), 1); + // std::cout << "detection: " << objects[i].bb.x + // << " " << objects[i].bb.y + // << " " << objects[i].bb.width + // << " " << objects[i].bb.height << std::endl; + // total++; + // } + // std::cout << "detected: " << (int)objects.size() << std::endl; ASSERT_EQ((int)objects.size(), 3498); +} + +TEST(SCascade, detectNoRoi) +{ + typedef cv::SCascade::Detection Detection; + std::string xml = cvtest::TS::ptr()->get_data_path() + "cascadeandhog/sc_cvpr_2012_to_opencv.xml"; + cv::SCascade cascade; + cv::FileStorage fs(xml, cv::FileStorage::READ); + ASSERT_TRUE(cascade.load(fs.getFirstTopLevelNode())); + + cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/bahnhof/image_00000000_0.png"); + ASSERT_FALSE(colored.empty()); + + std::vector objects; + std::vector rois; + + cascade.detect(colored, rois, objects); + + ASSERT_EQ((int)objects.size(), 0); } \ No newline at end of file