From 7892a5bd4c9f54ff5ae73afb209d0bc5bb183e21 Mon Sep 17 00:00:00 2001 From: Ajit Pant <43715439+AjitPant@users.noreply.github.com> Date: Wed, 19 Aug 2020 20:39:57 +0530 Subject: [PATCH 1/5] Exposed some of the internal variables of the CChecker class --- .../mcc/include/opencv2/mcc/checker_model.hpp | 36 ++++- modules/mcc/samples/chart_detection.cpp | 1 + .../samples/chart_detection_with_network.cpp | 1 + modules/mcc/src/checker_detector.cpp | 80 +++++----- modules/mcc/src/checker_detector.hpp | 18 +-- modules/mcc/src/checker_model.cpp | 142 +++++++++++++----- modules/mcc/src/checker_model.hpp | 25 ++- modules/mcc/src/common.cpp | 32 ++++ modules/mcc/src/common.hpp | 15 +- 9 files changed, 251 insertions(+), 99 deletions(-) diff --git a/modules/mcc/include/opencv2/mcc/checker_model.hpp b/modules/mcc/include/opencv2/mcc/checker_model.hpp index c13d5afc585..6e310b3e428 100644 --- a/modules/mcc/include/opencv2/mcc/checker_model.hpp +++ b/modules/mcc/include/opencv2/mcc/checker_model.hpp @@ -82,17 +82,29 @@ class CV_EXPORTS_W CChecker CV_WRAP virtual void setTarget(TYPECHART _target) = 0; CV_WRAP virtual void setBox(std::vector _box) = 0; + CV_WRAP virtual void setPerPatchCosts(std::vector _patchCosts) = 0; + + // Detected directly by the detector or found using geometry, useful to determine if a patch is occluded + CV_WRAP virtual void setBoxDetectionType(std::vector> detectionType) = 0; CV_WRAP virtual void setChartsRGB(Mat _chartsRGB) = 0; CV_WRAP virtual void setChartsYCbCr(Mat _chartsYCbCr) = 0; CV_WRAP virtual void setCost(float _cost) = 0; CV_WRAP virtual void setCenter(Point2f _center) = 0; + CV_WRAP virtual void setPatchCenters(std::vector _patchCenters) = 0; + CV_WRAP virtual void setPatchBoundingBoxes(std::vector _patchBoundingBoxes) = 0; CV_WRAP virtual TYPECHART getTarget() = 0; CV_WRAP virtual std::vector getBox() = 0; + CV_WRAP virtual std::vector getPerPatchCosts() = 0; + CV_WRAP virtual std::vector> getBoxDetectionType() = 0; CV_WRAP virtual Mat getChartsRGB() = 0; CV_WRAP virtual Mat getChartsYCbCr() = 0; CV_WRAP virtual float getCost() = 0; CV_WRAP virtual Point2f getCenter() = 0; + CV_WRAP virtual std::vector getPatchCenters() = 0; + CV_WRAP virtual std::vector getPatchBoundingBoxes(float sideRatio=0.5) =0; + + CV_WRAP virtual bool calculate() = 0; ///< Return false if some error occured, true otherwise }; /** \brief checker draw @@ -115,10 +127,16 @@ class CV_EXPORTS_W CCheckerDraw public: virtual ~CCheckerDraw() {} /** \brief Draws the checker to the given image. - * \param img image in color space BGR + * \param img image in color space BGR, original image gets modified + * \param sideRatio ratio between the side length of drawed boxes, and the actual side of squares + * keeping sideRatio = 1.0 is not recommended as the border can be a bit inaccurate + * in detection, for best output keep it at less than 1.0 + * \param drawActualDetection draw the actually detected patch,i.e,, the non occuled ones, + * useful for debugging, default (false) * \return void */ - CV_WRAP virtual void draw(InputOutputArray img) = 0; + CV_WRAP virtual void draw(InputOutputArray img, float sideRatio = 0.5, + bool drawActualDetection = false) = 0; /** \brief Create a new CCheckerDraw object. * \param pChecker The checker which will be drawn by this object. * \param color The color by with which the squares of the checker @@ -132,6 +150,20 @@ class CV_EXPORTS_W CCheckerDraw int thickness = 2); }; + +/** @brief draws a single mcc::ColorChecker on the given image + * This is a functional version of the CCheckerDraw class, provided for convenience + * \param img image in color space BGR, it gets changed by this call + * \param pChecker pointer to the CChecker, which contains the detection + * \param color color used for drawing + * \param thickness thickness of the boxes drawed + * \param sideRatio ratio between the side length of drawed boxes, and the actual side of squares + * keeping sideRatio = 1.0 is not recommended as the border can be a bit inaccurate + * in detection, for best output keep it at less than 1.0 + */ +CV_EXPORTS_W void drawColorChecker(InputOutputArray img, Ptr pChecker, + cv::Scalar color = CV_RGB(0, 255, 0), int thickness = 2, float sideRatio = 0.5, + bool drawActualDetection = false); //! @} mcc } // namespace mcc } // namespace cv diff --git a/modules/mcc/samples/chart_detection.cpp b/modules/mcc/samples/chart_detection.cpp index 792c54a3514..f86f22f914d 100644 --- a/modules/mcc/samples/chart_detection.cpp +++ b/modules/mcc/samples/chart_detection.cpp @@ -40,6 +40,7 @@ int main(int argc, char *argv[]) if (!parser.check()) { parser.printErrors(); + parser.printMessage(); return 0; } diff --git a/modules/mcc/samples/chart_detection_with_network.cpp b/modules/mcc/samples/chart_detection_with_network.cpp index aab197cddb6..5a7076ca824 100644 --- a/modules/mcc/samples/chart_detection_with_network.cpp +++ b/modules/mcc/samples/chart_detection_with_network.cpp @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) if (!parser.check()) { parser.printErrors(); + parser.printMessage(); return 0; } diff --git a/modules/mcc/src/checker_detector.cpp b/modules/mcc/src/checker_detector.cpp index f5ce44ed569..462f0ebac9f 100644 --- a/modules/mcc/src/checker_detector.cpp +++ b/modules/mcc/src/checker_detector.cpp @@ -193,7 +193,8 @@ bool CCheckerDetectorImpl:: //------------------------------------------------------------------- std::vector> colorCharts; - checkerRecognize(img_bgr, detectedCharts, G, chartType, colorCharts, params); + std::vector> groupedCharts; + checkerRecognize(img_bgr, detectedCharts, G, chartType, colorCharts,groupedCharts, params); if (colorCharts.empty()) continue; @@ -219,7 +220,7 @@ bool CCheckerDetectorImpl:: // checker color analysis //------------------------------------------------------------------- std::vector> checkers; - checkerAnalysis(img_rgb_f, chartType, nc, colorCharts, checkers, asp, params, + checkerAnalysis(img_rgb_f, chartType, nc, colorCharts, groupedCharts, checkers, asp, params, img_rgb_org, img_ycbcr_org, rgb_planes, ycbcr_planes); #ifdef MCC_DEBUG @@ -237,6 +238,10 @@ bool CCheckerDetectorImpl:: for (cv::Point2f &corner : checker->getBox()) corner += static_cast(region.tl()); + for (std::vector &corners : checker->getBoxDetectionType()) + for (cv::Point2f & corner: corners) + corner += static_cast(region.tl()); + mtx.lock(); // push_back is not thread safe m_checkers.push_back(checker); mtx.unlock(); @@ -414,7 +419,8 @@ bool CCheckerDetectorImpl:: //------------------------------------------------------------------- std::vector> colorCharts; - checkerRecognize(img_bgr, detectedCharts, G, chartType, colorCharts, params); + std::vector> groupedCharts; + checkerRecognize(img_bgr, detectedCharts, G, chartType, colorCharts, groupedCharts, params); if (colorCharts.empty()) continue; @@ -440,7 +446,7 @@ bool CCheckerDetectorImpl:: // checker color analysis //------------------------------------------------------------------- std::vector> checkers; - checkerAnalysis(img_rgb_f, chartType, nc, colorCharts, checkers, asp, params, + checkerAnalysis(img_rgb_f, chartType, nc, colorCharts,groupedCharts, checkers, asp, params, img_rgb_org, img_ycbcr_org, rgb_planes, ycbcr_planes); #ifdef MCC_DEBUG cv::Mat image_checker; @@ -456,6 +462,10 @@ bool CCheckerDetectorImpl:: { for (cv::Point2f &corner : checker->getBox()) corner += static_cast(region.tl() + innerRegion.tl()); + for (std::vector &corners : checker->getBoxDetectionType()) + for (cv::Point2f & corner: corners) + corner += static_cast(region.tl() + innerRegion.tl()); + checker->calculate(); mtx.lock(); // push_back is not thread safe m_checkers.push_back(checker); mtx.unlock(); @@ -756,6 +766,7 @@ void CCheckerDetectorImpl:: const std::vector &G, const TYPECHART chartType, std::vector> &colorChartsOut, + std::vector> &groupedCharts, const Ptr ¶ms) { std::vector gU; @@ -775,7 +786,7 @@ void CCheckerDetectorImpl:: for (size_t i = 0; i < Ncc; i++) if (G[i] == (int)g) chartSub.push_back(detectedCharts[i]); - + std::vector chartSubCopy = chartSub; size_t Nsc = chartSub.size(); if (Nsc < params->minGroupSize) continue; @@ -958,6 +969,7 @@ void CCheckerDetectorImpl:: mcc::polyclockwise(ibox); // circshift(ibox, 4 - iTheta); colorCharts.push_back(ibox); + groupedCharts.push_back(chartSubCopy); } // return @@ -970,6 +982,7 @@ void CCheckerDetectorImpl:: const TYPECHART chartType, const unsigned int nc, const std::vector> &colorCharts, + const std::vector> &groupedCharts, std::vector> &checkers, float asp, const Ptr ¶ms, @@ -993,10 +1006,11 @@ void CCheckerDetectorImpl:: N = colorCharts.size(); std::vector J(N); + std::vector perPatchCost(N); for (size_t i = 0; i < N; i++) { ibox = colorCharts[i]; - J[i] = cost_function(img_f, mask, lab, ibox, chartType); + J[i] = cost_function(img_f, mask, lab, perPatchCost, ibox, chartType); } std::vector idx; @@ -1020,14 +1034,28 @@ void CCheckerDetectorImpl:: get_profile(ibox, chartType, charts_rgb, charts_ycbcr, img_rgb_org, img_ycbcr_org, rgb_planes, ycbcr_planes); + std::vector> directlyDetectedPatches; + for(auto chart : groupedCharts[idx[i]]) + { + for(auto &corners: chart.corners) + corners *= invAsp; + directlyDetectedPatches.push_back(chart.corners); + } + + + // result Ptr checker = CChecker::create(); checker->setBox(ibox); + checker->setBoxDetectionType(directlyDetectedPatches); + checker->setTarget(chartType); checker->setChartsRGB(charts_rgb); checker->setChartsYCbCr(charts_ycbcr); checker->setCenter(mace_center(ibox)); checker->setCost(J[i]); + checker->calculate(); //does some precomputation based on the inputs, + //mainly used to keep the code a bit clean checkers.push_back(checker); } @@ -1178,38 +1206,6 @@ void CCheckerDetectorImpl:: x_new.insert(x_new.begin() + idx + 1, (x_new[idx] + x_new[idx + 1]) / 2); } -void CCheckerDetectorImpl:: - transform_points_forward(InputArray T, const std::vector &X, std::vector &Xt) -{ - size_t N = X.size(); - if (N == 0) - return; - - Xt.clear(); - Xt.resize(N); - cv::Matx31f p, xt; - cv::Point2f pt; - - cv::Matx33f _T = T.getMat(); - for (int i = 0; i < (int)N; i++) - { - p(0, 0) = X[i].x; - p(1, 0) = X[i].y; - p(2, 0) = 1; - xt = _T * p; - pt.x = xt(0, 0) / xt(2, 0); - pt.y = xt(1, 0) / xt(2, 0); - Xt[i] = pt; - } -} - -void CCheckerDetectorImpl:: - transform_points_inverse(InputArray T, const std::vector &X, std::vector &Xt) -{ - cv::Matx33f _T = T.getMat(); - cv::Matx33f Tinv = _T.inv(); - transform_points_forward(Tinv, X, Xt); -} void CCheckerDetectorImpl:: get_profile( const std::vector &ibox, @@ -1330,6 +1326,7 @@ void CCheckerDetectorImpl:: float CCheckerDetectorImpl:: cost_function(InputArray im_rgb, InputOutputArray mask, InputArray lab, + std::vector &perPatchCost, const std::vector &ibox, const TYPECHART chartType) { CChartModel cccm(chartType); @@ -1342,6 +1339,8 @@ float CCheckerDetectorImpl:: int N = (int)(cellchart.size() / 4); + perPatchCost.assign(N, {-1, -1}); //-1 for patches outside the image + cv::Mat _lab = lab.getMat(); cv::Mat _im_rgb = im_rgb.getMat(); @@ -1376,10 +1375,11 @@ float CCheckerDetectorImpl:: // cos error float costh; costh = (float)(mu.dot(cv::Scalar(r)) / (norm(mu) * norm(r) + FLT_EPSILON)); - ec += (1 - (1 + costh) / 2); + perPatchCost[i] = {1 - (1 + costh)/2, (float)st.dot(st)}; + ec += perPatchCost[i].x; // standar desviation - es += (float)st.dot(st); + es += perPatchCost[i].y; } } diff --git a/modules/mcc/src/checker_detector.hpp b/modules/mcc/src/checker_detector.hpp index 83fc55ad767..129d6466bc0 100644 --- a/modules/mcc/src/checker_detector.hpp +++ b/modules/mcc/src/checker_detector.hpp @@ -130,8 +130,10 @@ class CCheckerDetectorImpl : public CCheckerDetector * \param[out] colorChartsOut */ virtual void - checkerRecognize(InputArray img, const std::vector &detectedCharts, const std::vector &G, - const TYPECHART chartType, std::vector> &colorChartsOut, + checkerRecognize(InputArray img, const std::vector &detectedCharts, + const std::vector &G, const TYPECHART chartType, + std::vector> &colorChartsOut, + std::vector> &groupedCharts, const Ptr ¶ms); /// checkerAnalysis @@ -146,6 +148,7 @@ class CCheckerDetectorImpl : public CCheckerDetector checkerAnalysis(InputArray img_rgb_f, const TYPECHART chartType, const unsigned int nc, const std::vector> &colorCharts, + const std::vector> &groupedCharts, std::vector> &checkers, float asp, const Ptr ¶ms, const cv::Mat &img_rgb_org, @@ -172,16 +175,6 @@ class CCheckerDetectorImpl : public CCheckerDetector std::vector &x_new, float tol); - void transform_points_forward( - InputArray T, - const std::vector &X, - std::vector &Xt); - - void transform_points_inverse( - InputArray T, - const std::vector &X, - std::vector &Xt); - void get_profile( const std::vector &ibox, const TYPECHART chartType, @@ -197,6 +190,7 @@ class CCheckerDetectorImpl : public CCheckerDetector * + \sum_k || \sigma_{k,p} ||^2 */ float cost_function(InputArray img, InputOutputArray mask, InputArray lab, + std::vector &perPatchCost, const std::vector &ibox, const TYPECHART chartType); }; diff --git a/modules/mcc/src/checker_model.cpp b/modules/mcc/src/checker_model.cpp index 2062e7705e5..210c0fd394d 100644 --- a/modules/mcc/src/checker_model.cpp +++ b/modules/mcc/src/checker_model.cpp @@ -31,6 +31,9 @@ #include "checker_model.hpp" #include "dictionary.hpp" +#include +using namespace std; + namespace cv { namespace mcc @@ -386,6 +389,14 @@ void CCheckerImpl::setBox(std::vector _box) { box = _box; } +void CCheckerImpl::setPerPatchCosts(std::vector _perPatchCost) +{ + perPatchCost = _perPatchCost; +} +void CCheckerImpl::setBoxDetectionType(std::vector> _boxDetectionType) +{ + boxDetectionType = _boxDetectionType; +} void CCheckerImpl::setChartsRGB(Mat _chartsRGB) { chartsRGB = _chartsRGB; @@ -402,6 +413,18 @@ void CCheckerImpl::setCenter(Point2f _center) { center = _center; } +void CCheckerImpl::setPatchCenters(std::vector _patchCenters) +{ + + patchCenters = _patchCenters; +} +void CCheckerImpl::setPatchBoundingBoxes(std::vector _patchBoundingBoxes) +{ + //Use of this function is not recommended as it can cause contradictory information in patBoundingBoxes and bo + patchBoundingBoxes = _patchBoundingBoxes; + +} + TYPECHART CCheckerImpl::getTarget() { @@ -411,6 +434,14 @@ std::vector CCheckerImpl::getBox() { return box; } +std::vector CCheckerImpl::getPerPatchCosts() +{ + return perPatchCost; +} +std::vector> CCheckerImpl::getBoxDetectionType() +{ + return boxDetectionType; +} Mat CCheckerImpl::getChartsRGB() { return chartsRGB; @@ -427,30 +458,51 @@ Point2f CCheckerImpl::getCenter() { return center; } +std::vector CCheckerImpl::getPatchCenters() +{ -////////////////////////////////////////////////////////////////////////////////////////////// -// CheckerDraw -Ptr CCheckerDraw::create(Ptr pChecker, cv::Scalar color /*= CV_RGB(0,250,0)*/, int thickness /*=2*/) + return patchCenters; +} + +std::vector CCheckerImpl::getPatchBoundingBoxes(float sideRatio) { - return makePtr(pChecker, color, thickness); + std::vector _patchBoundingBoxes; + + size_t N = patchBoundingBoxes.size() / 4; + + _patchBoundingBoxes.resize(4 * N); + + for (size_t i = 0; i < N; i++) + { + for (size_t j = 0; j < 4; j++) + _patchBoundingBoxes[4*i+j] = ((patchBoundingBoxes[4*i+j] - patchCenters[i] ) * sideRatio / defaultSideRatio) + patchCenters[i]; + + } + return _patchBoundingBoxes; } -void CCheckerDrawImpl:: - draw(InputOutputArray img) +bool CCheckerImpl::calculate() { + if(box.size() != 4) + return false; + //Currently it just calculates all the patch centers + + + + CChartModel cccm(this->getTarget()); - // color chart classic model - CChartModel cccm(m_pChecker->getTarget()); - cv::Mat lab; - size_t N; std::vector fbox = cccm.box; std::vector cellchart = cccm.cellchart; // tranformation - cv::Matx33f ccT = cv::getPerspectiveTransform(fbox, m_pChecker->getBox()); + cv::Matx33f ccT = cv::getPerspectiveTransform(fbox, this->getBox()); std::vector bch(4), bcht(4); - N = cellchart.size() / 4; + size_t N = cellchart.size() / 4; + + patchBoundingBoxes.resize(4 * N); + patchCenters.resize(N); + for (size_t i = 0, k; i < N; i++) { k = 4 * i; @@ -466,39 +518,61 @@ void CCheckerDrawImpl:: for (size_t j = 0; j < 4; j++) c += bcht[j]; c /= 4; + patchCenters[i] = c; for (size_t j = 0; j < 4; j++) - bcht[j] = ((bcht[j] - c) * 0.50) + c; + bcht[j] = ((bcht[j] - c) * defaultSideRatio) + c; - cv::line(img, bcht[0], bcht[1], m_color, m_thickness, LINE_AA); - cv::line(img, bcht[1], bcht[2], m_color, m_thickness, LINE_AA); - cv::line(img, bcht[2], bcht[3], m_color, m_thickness, LINE_AA); - cv::line(img, bcht[3], bcht[0], m_color, m_thickness, LINE_AA); + for (int j = 0; j < 4; j++) + patchBoundingBoxes[4 * i + j] = bcht[j]; } + return true; + + + +} +////////////////////////////////////////////////////////////////////////////////////////////// +// CheckerDraw +Ptr CCheckerDraw::create(Ptr pChecker, cv::Scalar color /*= CV_RGB(0,250,0)*/, int thickness /*=2*/) +{ + return makePtr(pChecker, color, thickness); } void CCheckerDrawImpl:: - transform_points_forward(InputArray T, const std::vector &X, std::vector &Xt) + draw(InputOutputArray img, float sideRatio, bool drawActualDetection) { - cv::Matx33f _T = T.getMat(); - size_t N = X.size(); - Xt.clear(); - Xt.resize(N); - if (N == 0) - return; - - cv::Matx31f p, xt; - cv::Point2f pt; + std::vector patchBoundingBoxes = m_pChecker->getPatchBoundingBoxes(sideRatio); + size_t N = patchBoundingBoxes.size()/4; for (size_t i = 0; i < N; i++) { - p(0, 0) = X[i].x; - p(1, 0) = X[i].y; - p(2, 0) = 1; - xt = _T * p; - pt.x = xt(0, 0) / xt(2, 0); - pt.y = xt(1, 0) / xt(2, 0); - Xt[i] = pt; + + cv::line(img, patchBoundingBoxes[4*i +0], patchBoundingBoxes[4*i+1], m_color, m_thickness, LINE_AA); + cv::line(img, patchBoundingBoxes[4*i+1], patchBoundingBoxes[4*i+2], m_color, m_thickness, LINE_AA); + cv::line(img, patchBoundingBoxes[4*i+2], patchBoundingBoxes[4*i+3], m_color, m_thickness, LINE_AA); + cv::line(img, patchBoundingBoxes[4*i+3], patchBoundingBoxes[4*i+0], m_color, m_thickness, LINE_AA); + } + + if(drawActualDetection) + { + + vector> f; + for (auto i : m_pChecker->getBoxDetectionType()) + { + vector x; + for (auto j : i) + x.push_back(j); + f.push_back(x); + } + drawContours(img, f, -1, CV_RGB(255, 255, 0), 2); } } + +void drawColorChecker(InputOutputArray img, Ptr pChecker, + cv::Scalar color, int thickness, float sideRatio, + bool drawActualDetection) +{ + CCheckerDrawImpl(pChecker, color, thickness).draw(img, sideRatio, drawActualDetection); +} + } // namespace mcc } // namespace cv diff --git a/modules/mcc/src/checker_model.hpp b/modules/mcc/src/checker_model.hpp index 31b85a5a144..87d13e6f6bf 100644 --- a/modules/mcc/src/checker_model.hpp +++ b/modules/mcc/src/checker_model.hpp @@ -130,25 +130,42 @@ class CCheckerImpl : public CChecker void setTarget(TYPECHART _target) CV_OVERRIDE; void setBox(std::vector _box) CV_OVERRIDE; + void setPerPatchCosts(std::vector cost) CV_OVERRIDE; + + // Detected directly by the detector or found using geometry, useful to determine if a patch is occluded + void setBoxDetectionType(std::vector> detectionType) CV_OVERRIDE; void setChartsRGB(Mat _chartsRGB) CV_OVERRIDE; void setChartsYCbCr(Mat _chartsYCbCr) CV_OVERRIDE; void setCost(float _cost) CV_OVERRIDE; void setCenter(Point2f _center) CV_OVERRIDE; + void setPatchCenters(std::vector _patchCenters) CV_OVERRIDE; + void setPatchBoundingBoxes(std::vector _patchBoundingBoxes) CV_OVERRIDE; TYPECHART getTarget() CV_OVERRIDE; std::vector getBox() CV_OVERRIDE; + std::vector getPerPatchCosts() CV_OVERRIDE; + std::vector> getBoxDetectionType() CV_OVERRIDE; Mat getChartsRGB() CV_OVERRIDE; Mat getChartsYCbCr() CV_OVERRIDE; float getCost() CV_OVERRIDE; Point2f getCenter() CV_OVERRIDE; + std::vector getPatchCenters() CV_OVERRIDE; + std::vector getPatchBoundingBoxes(float sideRatio=0.5) CV_OVERRIDE; + + bool calculate() CV_OVERRIDE;//basic precomp private: TYPECHART target; ///< type of checkercolor std::vector box; ///< positions of the corners + std::vector perPatchCost; ///< Cost of each patch in chart + std::vector patchBoundingBoxes; ///< Bounding box of the patches + std::vector patchCenters; ///< Centers of all the patches + std::vector> boxDetectionType; ///< contours of patches directly dectected, not using geometry cv::Mat chartsRGB; ///< charts profile in rgb color space cv::Mat chartsYCbCr; ///< charts profile in YCbCr color space float cost; ///< cost to aproximate cv::Point2f center; ///< center of the chart. + float defaultSideRatio = 0.5; ///< ratio of side of patchBoundingBox and actual patch size }; ////////////////////////////////////////////////////////////////////////////////////////////// @@ -167,19 +184,13 @@ class CCheckerDrawImpl : public CCheckerDraw CV_Assert(pChecker); } - void draw(InputOutputArray img) CV_OVERRIDE; + void draw(InputOutputArray img, float sideRatio =0.5,bool drawActualDetection=false) CV_OVERRIDE; private: Ptr m_pChecker; cv::Scalar m_color; int m_thickness; -private: - /** \brief transformation perspetive*/ - void transform_points_forward( - InputArray T, - const std::vector &X, - std::vector &Xt); }; // @} diff --git a/modules/mcc/src/common.cpp b/modules/mcc/src/common.cpp index 71cba1e8bc5..77c21d2f86a 100644 --- a/modules/mcc/src/common.cpp +++ b/modules/mcc/src/common.cpp @@ -86,5 +86,37 @@ mace_center(const std::vector &ps) return center; } +void transform_points_forward(InputArray T, const std::vector &X, + std::vector &Xt) +{ + size_t N = X.size(); + if (N == 0) + return; + + Xt.clear(); + Xt.resize(N); + cv::Matx31f p, xt; + cv::Point2f pt; + + cv::Matx33f _T = T.getMat(); + for (int i = 0; i < (int)N; i++) + { + p(0, 0) = X[i].x; + p(1, 0) = X[i].y; + p(2, 0) = 1; + xt = _T * p; + pt.x = xt(0, 0) / xt(2, 0); + pt.y = xt(1, 0) / xt(2, 0); + Xt[i] = pt; + } +} + +void transform_points_inverse(InputArray T, const std::vector &X, + std::vector &Xt) +{ + cv::Matx33f _T = T.getMat(); + cv::Matx33f Tinv = _T.inv(); + transform_points_forward(Tinv, X, Xt); +} } // namespace mcc } // namespace cv diff --git a/modules/mcc/src/common.hpp b/modules/mcc/src/common.hpp index aa4c383f556..0073364c516 100644 --- a/modules/mcc/src/common.hpp +++ b/modules/mcc/src/common.hpp @@ -36,6 +36,17 @@ namespace mcc Rect poly2mask(const std::vector &poly, Size size, InputOutputArray mask); + +float perimeter(const std::vector &ps); + +cv::Point2f mace_center(const std::vector &ps); + +void transform_points_forward(InputArray T, const std::vector &X, + std::vector &Xt); + +void transform_points_inverse(InputArray T, const std::vector &X, + std::vector &Xt); + template void circshift(std::vector &A, int shiff) { @@ -53,10 +64,6 @@ void circshift(std::vector &A, int shiff) A = Tmp; } -float perimeter(const std::vector &ps); - -cv::Point2f mace_center(const std::vector &ps); - template void unique(const std::vector &A, std::vector &U) { From 84e877aaf02fa482de3024febf22448914384a0a Mon Sep 17 00:00:00 2001 From: Ajit Pant <43715439+AjitPant@users.noreply.github.com> Date: Thu, 27 Aug 2020 22:08:39 +0530 Subject: [PATCH 2/5] Fixed a small bug --- modules/mcc/src/checker_model.cpp | 2 +- modules/mcc/test/test_mcc.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/mcc/src/checker_model.cpp b/modules/mcc/src/checker_model.cpp index 210c0fd394d..9ec4a40b52a 100644 --- a/modules/mcc/src/checker_model.cpp +++ b/modules/mcc/src/checker_model.cpp @@ -420,7 +420,7 @@ void CCheckerImpl::setPatchCenters(std::vector _patchCenters) } void CCheckerImpl::setPatchBoundingBoxes(std::vector _patchBoundingBoxes) { - //Use of this function is not recommended as it can cause contradictory information in patBoundingBoxes and bo + //Use of this function is not recommended as it can cause contradictory information in patBoundingBoxes and box patchBoundingBoxes = _patchBoundingBoxes; } diff --git a/modules/mcc/test/test_mcc.cpp b/modules/mcc/test/test_mcc.cpp index 4aa8ae31302..adb1857e59d 100644 --- a/modules/mcc/test/test_mcc.cpp +++ b/modules/mcc/test/test_mcc.cpp @@ -23,6 +23,8 @@ void runCCheckerDraw(Ptr pChecker, int rows, int cols, unsigned int nu Ptr cdraw = CCheckerDraw::create(pChecker); cdraw->draw(img); + imshow("a", img); + cv2.waitKey(0); //make sure this contains extacly as many rectangles as in the pChecker vector> contours; @@ -37,6 +39,8 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_MCC24) Ptr pChecker = CChecker::create(); pChecker->setTarget(MCC24); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); + ASSERT_EQ(pChecker->calculate() == true); + runCCheckerDraw(pChecker, 640, 480, 24); } TEST(CV_mccRunCCheckerDrawTest, accuracy_SG140) @@ -44,6 +48,7 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_SG140) Ptr pChecker = CChecker::create(); pChecker->setTarget(SG140); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); + pChecker->calculate(); runCCheckerDraw(pChecker, 640, 480, 140); } TEST(CV_mccRunCCheckerDrawTest, accuracy_VINYL18) @@ -51,6 +56,7 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_VINYL18) Ptr pChecker = CChecker::create(); pChecker->setTarget(VINYL18); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); + pChecker->calculate(); runCCheckerDraw(pChecker, 640, 480, 18); } From e9ccdc67c3081daf4403b9898ce5cd13c81af863 Mon Sep 17 00:00:00 2001 From: Ajit Pant <43715439+AjitPant@users.noreply.github.com> Date: Mon, 31 Aug 2020 06:45:05 +0530 Subject: [PATCH 3/5] Added some more interfaces and a sample for color calibration --- modules/mcc/CMakeLists.txt | 2 +- .../mcc/include/opencv2/mcc/checker_model.hpp | 13 +- .../mcc/samples/basic_color_calibration.cpp | 168 ++++++++++++++++++ modules/mcc/samples/chart_detection.cpp | 3 + .../samples/chart_detection_with_network.cpp | 4 + modules/mcc/src/checker_detector.cpp | 37 +++- modules/mcc/src/checker_model.cpp | 20 ++- modules/mcc/src/checker_model.hpp | 9 +- modules/mcc/src/common.cpp | 2 + modules/mcc/src/common.hpp | 17 ++ modules/mcc/src/mcc.cpp | 5 +- modules/mcc/test/test_mcc.cpp | 6 +- 12 files changed, 255 insertions(+), 31 deletions(-) create mode 100644 modules/mcc/samples/basic_color_calibration.cpp diff --git a/modules/mcc/CMakeLists.txt b/modules/mcc/CMakeLists.txt index 806303505f3..7bd55435a45 100644 --- a/modules/mcc/CMakeLists.txt +++ b/modules/mcc/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Macbeth Chart Detection") -ocv_define_module(mcc opencv_core opencv_imgproc opencv_calib3d opencv_photo opencv_dnn WRAP python) +ocv_define_module(mcc opencv_core opencv_imgproc opencv_calib3d opencv_photo opencv_dnn WRAP python) diff --git a/modules/mcc/include/opencv2/mcc/checker_model.hpp b/modules/mcc/include/opencv2/mcc/checker_model.hpp index 6e310b3e428..a5717ca0a2e 100644 --- a/modules/mcc/include/opencv2/mcc/checker_model.hpp +++ b/modules/mcc/include/opencv2/mcc/checker_model.hpp @@ -73,21 +73,16 @@ class CV_EXPORTS_W CChecker CV_WRAP static Ptr create(); public: - // CV_PROP_RW TYPECHART target; ///< type of checkercolor - // CV_PROP_RW std::vector box; ///< positions of the corners - // CV_PROP_RW cv::Mat charts_rgb; ///< charts profile in rgb color space - // CV_PROP_RW cv::Mat charts_ycbcr; ///< charts profile in YCbCr color space - // CV_PROP_RW float cost; ///< cost to aproximate - // CV_PROP_RW cv::Point2f center; ///< center of the chart. CV_WRAP virtual void setTarget(TYPECHART _target) = 0; CV_WRAP virtual void setBox(std::vector _box) = 0; CV_WRAP virtual void setPerPatchCosts(std::vector _patchCosts) = 0; // Detected directly by the detector or found using geometry, useful to determine if a patch is occluded - CV_WRAP virtual void setBoxDetectionType(std::vector> detectionType) = 0; + CV_WRAP virtual void setActualDetectedContours(std::vector> detectionType) = 0; CV_WRAP virtual void setChartsRGB(Mat _chartsRGB) = 0; CV_WRAP virtual void setChartsYCbCr(Mat _chartsYCbCr) = 0; + CV_WRAP virtual void setActualChartsColors(Mat _actualChartsColors) = 0; // the acutal color profile CV_WRAP virtual void setCost(float _cost) = 0; CV_WRAP virtual void setCenter(Point2f _center) = 0; CV_WRAP virtual void setPatchCenters(std::vector _patchCenters) = 0; @@ -96,14 +91,16 @@ class CV_EXPORTS_W CChecker CV_WRAP virtual TYPECHART getTarget() = 0; CV_WRAP virtual std::vector getBox() = 0; CV_WRAP virtual std::vector getPerPatchCosts() = 0; - CV_WRAP virtual std::vector> getBoxDetectionType() = 0; + CV_WRAP virtual std::vector> getActualDetectedContours() = 0; CV_WRAP virtual Mat getChartsRGB() = 0; CV_WRAP virtual Mat getChartsYCbCr() = 0; + CV_WRAP virtual Mat getActualChartsColors() = 0; // the acutal color profile CV_WRAP virtual float getCost() = 0; CV_WRAP virtual Point2f getCenter() = 0; CV_WRAP virtual std::vector getPatchCenters() = 0; CV_WRAP virtual std::vector getPatchBoundingBoxes(float sideRatio=0.5) =0; + CV_WRAP virtual bool calculate() = 0; ///< Return false if some error occured, true otherwise }; diff --git a/modules/mcc/samples/basic_color_calibration.cpp b/modules/mcc/samples/basic_color_calibration.cpp new file mode 100644 index 00000000000..699bae8f034 --- /dev/null +++ b/modules/mcc/samples/basic_color_calibration.cpp @@ -0,0 +1,168 @@ +#include + +#include +#include +#include + +using namespace std; +using namespace cv; +using namespace mcc; + +#include + +#include +#include +#include +#include + +using namespace std; +using namespace cv; +using namespace mcc; + +const char *about = "Basic color calibration using simple 3x3 linear color matrix"; +const char *keys = { + "{ help h usage ? | | show this message }" + "{t | 0 | chartType: 0-Standard, 1-DigitalSG, 2-Vinyl, default:0}" + "{m | | File path of model, if you don't have the model you can \ + find the link in the documentation}" + "{pb | | File path of pbtxt file, available along with with the model \ + file }" + "{v | | Input from video file, if ommited, input comes from camera }" + "{ci | 0 | Camera id if input doesnt come from video (-v) }" + "{nc | 1 | Maximum number of charts in the image }" + "{use_gpu | | Add this flag if you want to use gpu}"}; + +int main(int argc, char *argv[]) +{ + // ---------------------------------------------------------- + // Scroll down a bit (~50 lines) to find actual relevant code + // ---------------------------------------------------------- + + CommandLineParser parser(argc, argv, keys); + parser.about(about); + + if (parser.has("help")) + { + parser.printMessage(); + return -1; + } + + int t = parser.get("t"); + + CV_Assert(0 <= t && t <= 2); + TYPECHART chartType = TYPECHART(t); + + string model_path = parser.get("m"); + string pbtxt_path = parser.get("pb"); + + int camId = parser.get("ci"); + int nc = parser.get("nc"); + + String video; + + if (parser.has("v")) + video = parser.get("v"); + + bool use_gpu = parser.has("use_gpu"); + + if (!parser.check()) + { + parser.printErrors(); + parser.printMessage(); + return 0; + } + + VideoCapture inputVideo; + int waitTime; + if (!video.empty()) + { + inputVideo.open(video); + waitTime = 10; + } + else + { + inputVideo.open(camId); + waitTime = 10; + } + + //-------------------------------------------------------------------------- + //-------------------------Actual Relevant Code----------------------------- + //-------------------------------------------------------------------------- + + //load the network + + cv::dnn::Net net = cv::dnn::readNetFromTensorflow(model_path, pbtxt_path); + + if (use_gpu) + { + net.setPreferableBackend(dnn::DNN_BACKEND_CUDA); + net.setPreferableTarget(dnn::DNN_TARGET_CUDA); + } + + Ptr detector = CCheckerDetector::create(); + if (!detector->setNet(net)) + { + cout << "Loading Model failed: Aborting" << endl; + return 0; + } + namedWindow("original", WINDOW_NORMAL); + namedWindow("image result | q or esc to quit", WINDOW_NORMAL); + + while (inputVideo.grab()) + { + Mat image, imageCopy; + inputVideo.retrieve(image); + + imageCopy = image.clone(); + + // Marker type to detect + if (!detector->process(image, chartType, nc, true)) + { + printf("ChartColor not detected \n"); + } + else + { + + // get checker + std::vector> checkers = detector->getListColorChecker(); + for (Ptr checker : checkers) + { + // current checker + Ptr cdraw = CCheckerDraw::create(checker); + cdraw->draw(image); + Mat a = checker->getChartsRGB(); + Mat b = checker->getActualChartsColors(); + + a = a(Range::all(), Range(1, 2)).clone(); // second column contains the mean of each color + a = a.reshape(1, a.rows/3); + a.convertTo(a, CV_32F ); + + b = b(Range::all(), Range(0,3)).clone(); // The first 3 are rgb + + Mat x; + cv::solve(a, b, x,DECOMP_SVD); + + int originalRows= image.rows; + + cvtColor(image, image, COLOR_BGR2RGB); + image.convertTo(image, CV_32FC3); + image = image.reshape(1, image.rows*image.cols); + + image = image * x; + + image = image.reshape(3, originalRows); + image.convertTo(image, CV_8UC3); + cvtColor(image, image, COLOR_RGB2BGR); + + } + } + + imshow("image result | q or esc to quit", image); + imshow("original", imageCopy); + char key = (char)waitKey(waitTime); + if (key == 27) + break; + } + + return 0; +} diff --git a/modules/mcc/samples/chart_detection.cpp b/modules/mcc/samples/chart_detection.cpp index f86f22f914d..c47cdad7880 100644 --- a/modules/mcc/samples/chart_detection.cpp +++ b/modules/mcc/samples/chart_detection.cpp @@ -61,6 +61,9 @@ int main(int argc, char *argv[]) //-------------------------Actual Relevant Code----------------------------- //-------------------------------------------------------------------------- + namedWindow("original", WINDOW_NORMAL); + namedWindow("image result | q or esc to quit", WINDOW_NORMAL); + while (inputVideo.grab()) { diff --git a/modules/mcc/samples/chart_detection_with_network.cpp b/modules/mcc/samples/chart_detection_with_network.cpp index 5a7076ca824..1bbec1a0199 100644 --- a/modules/mcc/samples/chart_detection_with_network.cpp +++ b/modules/mcc/samples/chart_detection_with_network.cpp @@ -96,6 +96,9 @@ int main(int argc, char *argv[]) return 0; } + namedWindow("original", WINDOW_NORMAL); + namedWindow("image result | q or esc to quit", WINDOW_NORMAL); + while (inputVideo.grab()) { Mat image, imageCopy; @@ -127,6 +130,7 @@ int main(int argc, char *argv[]) char key = (char)waitKey(waitTime); if (key == 27) break; + } return 0; diff --git a/modules/mcc/src/checker_detector.cpp b/modules/mcc/src/checker_detector.cpp index 462f0ebac9f..c739f1895d5 100644 --- a/modules/mcc/src/checker_detector.cpp +++ b/modules/mcc/src/checker_detector.cpp @@ -35,6 +35,8 @@ #include "checker_model.hpp" #include "debug.hpp" + +#include namespace cv { namespace mcc @@ -220,9 +222,9 @@ bool CCheckerDetectorImpl:: // checker color analysis //------------------------------------------------------------------- std::vector> checkers; + checkerAnalysis(img_rgb_f, chartType, nc, colorCharts, groupedCharts, checkers, asp, params, img_rgb_org, img_ycbcr_org, rgb_planes, ycbcr_planes); - #ifdef MCC_DEBUG cv::Mat image_checker; croppedImage.copyTo(image_checker); @@ -235,13 +237,18 @@ bool CCheckerDetectorImpl:: #endif for (Ptr checker : checkers) { - for (cv::Point2f &corner : checker->getBox()) + auto box = checker->getBox(); + for (cv::Point2f &corner : box) corner += static_cast(region.tl()); - for (std::vector &corners : checker->getBoxDetectionType()) + auto actualDetectedContours = checker->getActualDetectedContours(); + for (std::vector &corners : actualDetectedContours) for (cv::Point2f & corner: corners) corner += static_cast(region.tl()); + checker->setBox(box); + checker->setActualDetectedContours(actualDetectedContours); + checker->calculate(); mtx.lock(); // push_back is not thread safe m_checkers.push_back(checker); mtx.unlock(); @@ -446,8 +453,14 @@ bool CCheckerDetectorImpl:: // checker color analysis //------------------------------------------------------------------- std::vector> checkers; + std::vector rgb_planes_inner(3), ycbcr_planes_inner(3); + for(int _i= 0;_i<3;_i++) + { + rgb_planes_inner[_i] = rgb_planes[_i](innerRegion); + ycbcr_planes_inner[_i] = ycbcr_planes[_i](innerRegion); + } checkerAnalysis(img_rgb_f, chartType, nc, colorCharts,groupedCharts, checkers, asp, params, - img_rgb_org, img_ycbcr_org, rgb_planes, ycbcr_planes); + img_rgb_org(innerRegion), img_ycbcr_org(innerRegion), rgb_planes_inner, ycbcr_planes_inner); #ifdef MCC_DEBUG cv::Mat image_checker; innerCroppedImage.copyTo(image_checker); @@ -460,11 +473,17 @@ bool CCheckerDetectorImpl:: #endif for (Ptr checker : checkers) { - for (cv::Point2f &corner : checker->getBox()) + auto box = checker->getBox(); + for (cv::Point2f &corner : box) corner += static_cast(region.tl() + innerRegion.tl()); - for (std::vector &corners : checker->getBoxDetectionType()) + + auto actualDetectedContours = checker->getActualDetectedContours(); + for (std::vector &corners : actualDetectedContours) for (cv::Point2f & corner: corners) corner += static_cast(region.tl() + innerRegion.tl()); + + checker->setBox(box); + checker->setActualDetectedContours(actualDetectedContours); checker->calculate(); mtx.lock(); // push_back is not thread safe m_checkers.push_back(checker); @@ -538,6 +557,8 @@ void CCheckerDetectorImpl:: cv::Mat strelbox = cv::getStructuringElement(cv::MORPH_RECT, Size(5, 5)); cv::morphologyEx(grayOut, grayOut, MORPH_OPEN, strelbox); + + } void CCheckerDetectorImpl:: @@ -994,7 +1015,6 @@ void CCheckerDetectorImpl:: size_t N; std::vector ibox; - // color chart classic model CChartModel cccm(chartType); cv::Mat lab; cccm.copyToColorMat(lab, 0); @@ -1047,11 +1067,12 @@ void CCheckerDetectorImpl:: // result Ptr checker = CChecker::create(); checker->setBox(ibox); - checker->setBoxDetectionType(directlyDetectedPatches); + checker->setActualDetectedContours(directlyDetectedPatches); checker->setTarget(chartType); checker->setChartsRGB(charts_rgb); checker->setChartsYCbCr(charts_ycbcr); + checker->setActualChartsColors(Vect2Mat(cccm.chart)); checker->setCenter(mace_center(ibox)); checker->setCost(J[i]); checker->calculate(); //does some precomputation based on the inputs, diff --git a/modules/mcc/src/checker_model.cpp b/modules/mcc/src/checker_model.cpp index 9ec4a40b52a..50ebaff2d76 100644 --- a/modules/mcc/src/checker_model.cpp +++ b/modules/mcc/src/checker_model.cpp @@ -393,9 +393,9 @@ void CCheckerImpl::setPerPatchCosts(std::vector _perPatchCost) { perPatchCost = _perPatchCost; } -void CCheckerImpl::setBoxDetectionType(std::vector> _boxDetectionType) +void CCheckerImpl::setActualDetectedContours(std::vector> _boxDetectionType) { - boxDetectionType = _boxDetectionType; + actualDetectedContours = _boxDetectionType; } void CCheckerImpl::setChartsRGB(Mat _chartsRGB) { @@ -405,6 +405,10 @@ void CCheckerImpl::setChartsYCbCr(Mat _chartsYCbCr) { chartsYCbCr = _chartsYCbCr; } +void CCheckerImpl::setActualChartsColors(Mat _actualChartsColors) +{ + actualChartsColors = _actualChartsColors; +} void CCheckerImpl::setCost(float _cost) { cost = _cost; @@ -438,9 +442,9 @@ std::vector CCheckerImpl::getPerPatchCosts() { return perPatchCost; } -std::vector> CCheckerImpl::getBoxDetectionType() +std::vector> CCheckerImpl::getActualDetectedContours() { - return boxDetectionType; + return actualDetectedContours; } Mat CCheckerImpl::getChartsRGB() { @@ -450,6 +454,10 @@ Mat CCheckerImpl::getChartsYCbCr() { return chartsYCbCr; } +Mat CCheckerImpl::getActualChartsColors() +{ + return actualChartsColors; +} float CCheckerImpl::getCost() { return cost; @@ -556,14 +564,14 @@ void CCheckerDrawImpl:: { vector> f; - for (auto i : m_pChecker->getBoxDetectionType()) + for (auto i : m_pChecker->getActualDetectedContours()) { vector x; for (auto j : i) x.push_back(j); f.push_back(x); } - drawContours(img, f, -1, CV_RGB(255, 255, 0), 2); + drawContours(img, f , -1, CV_RGB(255, 255, 0), 2); } } diff --git a/modules/mcc/src/checker_model.hpp b/modules/mcc/src/checker_model.hpp index 87d13e6f6bf..4343f7028a5 100644 --- a/modules/mcc/src/checker_model.hpp +++ b/modules/mcc/src/checker_model.hpp @@ -133,9 +133,10 @@ class CCheckerImpl : public CChecker void setPerPatchCosts(std::vector cost) CV_OVERRIDE; // Detected directly by the detector or found using geometry, useful to determine if a patch is occluded - void setBoxDetectionType(std::vector> detectionType) CV_OVERRIDE; + void setActualDetectedContours(std::vector> detectionType) CV_OVERRIDE; void setChartsRGB(Mat _chartsRGB) CV_OVERRIDE; void setChartsYCbCr(Mat _chartsYCbCr) CV_OVERRIDE; + void setActualChartsColors(Mat _actualChartsColors) CV_OVERRIDE; // the acutal color profile void setCost(float _cost) CV_OVERRIDE; void setCenter(Point2f _center) CV_OVERRIDE; void setPatchCenters(std::vector _patchCenters) CV_OVERRIDE; @@ -144,9 +145,10 @@ class CCheckerImpl : public CChecker TYPECHART getTarget() CV_OVERRIDE; std::vector getBox() CV_OVERRIDE; std::vector getPerPatchCosts() CV_OVERRIDE; - std::vector> getBoxDetectionType() CV_OVERRIDE; + std::vector> getActualDetectedContours() CV_OVERRIDE; Mat getChartsRGB() CV_OVERRIDE; Mat getChartsYCbCr() CV_OVERRIDE; + Mat getActualChartsColors() CV_OVERRIDE; // the actual color profile float getCost() CV_OVERRIDE; Point2f getCenter() CV_OVERRIDE; std::vector getPatchCenters() CV_OVERRIDE; @@ -160,9 +162,10 @@ class CCheckerImpl : public CChecker std::vector perPatchCost; ///< Cost of each patch in chart std::vector patchBoundingBoxes; ///< Bounding box of the patches std::vector patchCenters; ///< Centers of all the patches - std::vector> boxDetectionType; ///< contours of patches directly dectected, not using geometry + std::vector> actualDetectedContours; ///< contours of patches directly dectected, not using geometry cv::Mat chartsRGB; ///< charts profile in rgb color space cv::Mat chartsYCbCr; ///< charts profile in YCbCr color space + cv::Mat actualChartsColors; ///< expected charts profile, contains both rgb and YCbCr float cost; ///< cost to aproximate cv::Point2f center; ///< center of the chart. float defaultSideRatio = 0.5; ///< ratio of side of patchBoundingBox and actual patch size diff --git a/modules/mcc/src/common.cpp b/modules/mcc/src/common.cpp index 77c21d2f86a..b3e95bf5771 100644 --- a/modules/mcc/src/common.cpp +++ b/modules/mcc/src/common.cpp @@ -118,5 +118,7 @@ void transform_points_inverse(InputArray T, const std::vector &X, cv::Matx33f Tinv = _T.inv(); transform_points_forward(Tinv, X, Xt); } + + } // namespace mcc } // namespace cv diff --git a/modules/mcc/src/common.hpp b/modules/mcc/src/common.hpp index 0073364c516..7d361505651 100644 --- a/modules/mcc/src/common.hpp +++ b/modules/mcc/src/common.hpp @@ -47,6 +47,23 @@ void transform_points_forward(InputArray T, const std::vector &X, void transform_points_inverse(InputArray T, const std::vector &X, std::vector &Xt); + +template +cv::Mat Vect2Mat(std::vector> vect) +{ + cv::Mat mtx = cv::Mat::zeros(vect.size(), vect[0].size(), cv::DataType::type); + //Mat mtx; + + // copy data + for (size_t i=0; i(i,j) = vect[i][j]; + //cout << vect[i][j] << " "; + } + + return mtx; +} template void circshift(std::vector &A, int shiff) { diff --git a/modules/mcc/src/mcc.cpp b/modules/mcc/src/mcc.cpp index 9f2d96ab7fc..83b1fc2a4b8 100644 --- a/modules/mcc/src/mcc.cpp +++ b/modules/mcc/src/mcc.cpp @@ -38,7 +38,7 @@ namespace mcc */ DetectorParameters::DetectorParameters() : adaptiveThreshWinSizeMin(23), - adaptiveThreshWinSizeMax(153), + adaptiveThreshWinSizeMax(303), adaptiveThreshWinSizeStep(16), adaptiveThreshConstant(7), minContoursAreaRate(0.003), @@ -46,9 +46,10 @@ DetectorParameters::DetectorParameters() confidenceThreshold(0.5), minContourSolidity(0.9), findCandidatesApproxPolyDPEpsMultiplier(0.05), - borderWidth(0), + borderWidth(20), B0factor(1.25f), maxError(0.1f), + minContourPointsAllowed(4), minContourLengthAllowed(100), minInterContourDistance(100), diff --git a/modules/mcc/test/test_mcc.cpp b/modules/mcc/test/test_mcc.cpp index adb1857e59d..1800f188292 100644 --- a/modules/mcc/test/test_mcc.cpp +++ b/modules/mcc/test/test_mcc.cpp @@ -23,8 +23,6 @@ void runCCheckerDraw(Ptr pChecker, int rows, int cols, unsigned int nu Ptr cdraw = CCheckerDraw::create(pChecker); cdraw->draw(img); - imshow("a", img); - cv2.waitKey(0); //make sure this contains extacly as many rectangles as in the pChecker vector> contours; @@ -39,7 +37,7 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_MCC24) Ptr pChecker = CChecker::create(); pChecker->setTarget(MCC24); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); - ASSERT_EQ(pChecker->calculate() == true); + pChecker->calculate(); runCCheckerDraw(pChecker, 640, 480, 24); } @@ -49,6 +47,7 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_SG140) pChecker->setTarget(SG140); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); pChecker->calculate(); + runCCheckerDraw(pChecker, 640, 480, 140); } TEST(CV_mccRunCCheckerDrawTest, accuracy_VINYL18) @@ -57,6 +56,7 @@ TEST(CV_mccRunCCheckerDrawTest, accuracy_VINYL18) pChecker->setTarget(VINYL18); pChecker->setBox({{0, 0}, {480, 0}, {480, 640}, {0, 640}}); pChecker->calculate(); + runCCheckerDraw(pChecker, 640, 480, 18); } From 8f1caeaaa7abd9a537770e337b64d96d404987ff Mon Sep 17 00:00:00 2001 From: Ajit Pant <43715439+AjitPant@users.noreply.github.com> Date: Mon, 31 Aug 2020 11:05:17 +0530 Subject: [PATCH 4/5] Fixed windows build warning --- modules/mcc/include/opencv2/mcc/checker_model.hpp | 7 ++++--- modules/mcc/src/common.hpp | 11 +++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/mcc/include/opencv2/mcc/checker_model.hpp b/modules/mcc/include/opencv2/mcc/checker_model.hpp index a5717ca0a2e..f42dab4f264 100644 --- a/modules/mcc/include/opencv2/mcc/checker_model.hpp +++ b/modules/mcc/include/opencv2/mcc/checker_model.hpp @@ -147,7 +147,6 @@ class CV_EXPORTS_W CCheckerDraw int thickness = 2); }; - /** @brief draws a single mcc::ColorChecker on the given image * This is a functional version of the CCheckerDraw class, provided for convenience * \param img image in color space BGR, it gets changed by this call @@ -157,10 +156,12 @@ class CV_EXPORTS_W CCheckerDraw * \param sideRatio ratio between the side length of drawed boxes, and the actual side of squares * keeping sideRatio = 1.0 is not recommended as the border can be a bit inaccurate * in detection, for best output keep it at less than 1.0 + * \param drawActualDetection draw the actually detected patch,i.e,, the non occuled ones, + * useful for debugging, default (false) */ CV_EXPORTS_W void drawColorChecker(InputOutputArray img, Ptr pChecker, - cv::Scalar color = CV_RGB(0, 255, 0), int thickness = 2, float sideRatio = 0.5, - bool drawActualDetection = false); + cv::Scalar color = CV_RGB(0, 255, 0), int thickness = 2, float sideRatio = 0.5, + bool drawActualDetection = false); //! @} mcc } // namespace mcc } // namespace cv diff --git a/modules/mcc/src/common.hpp b/modules/mcc/src/common.hpp index 7d361505651..6e46497d2ed 100644 --- a/modules/mcc/src/common.hpp +++ b/modules/mcc/src/common.hpp @@ -51,18 +51,17 @@ void transform_points_inverse(InputArray T, const std::vector &X, template cv::Mat Vect2Mat(std::vector> vect) { - cv::Mat mtx = cv::Mat::zeros(vect.size(), vect[0].size(), cv::DataType::type); + cv::Mat matrix = cv::Mat::zeros(vect.size(), vect[0].size(), cv::DataType::type); //Mat mtx; // copy data - for (size_t i=0; i(i,j) = vect[i][j]; - //cout << vect[i][j] << " "; + matrix.at(i,j) = vect[i][j]; } - return mtx; + return matrix; } template void circshift(std::vector &A, int shiff) From 6a4753799ec0e17615b85339d7facedcdfd6e8ce Mon Sep 17 00:00:00 2001 From: Ajit Pant <43715439+AjitPant@users.noreply.github.com> Date: Mon, 31 Aug 2020 14:07:41 +0530 Subject: [PATCH 5/5] Fixed another windows build warning --- modules/mcc/src/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mcc/src/common.hpp b/modules/mcc/src/common.hpp index 6e46497d2ed..ffdaf1f0fdb 100644 --- a/modules/mcc/src/common.hpp +++ b/modules/mcc/src/common.hpp @@ -51,7 +51,7 @@ void transform_points_inverse(InputArray T, const std::vector &X, template cv::Mat Vect2Mat(std::vector> vect) { - cv::Mat matrix = cv::Mat::zeros(vect.size(), vect[0].size(), cv::DataType::type); + cv::Mat matrix = cv::Mat::zeros((int)vect.size(), (int)vect[0].size(), cv::DataType::type); //Mat mtx; // copy data