mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Adding macbeth chart detector to objdetect module from opencv_contrib (#26906)
* Added mcc to opencv modules * Removed color correction module * Updated parameters return type * Added python sample for macbeth_chart_detection * Added models.yml support to samples * Removed unnecessary headers and classes * fixed datatype conversion * fixed datatype conversion * Cleaned headers and added reference/actual colors to samples * Added mcc tutorial * fixed datatype and header * replaced unsigned with int * Aligned actual and reference color function, added imread * Fixed shadow variable * Updated samples * Added last frame colors prints * updated detector class * Added getter functions and useNet function * Refactoring * Fixes in test * fixed infinite divison issue
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "bound_min.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
CBoundMin::CBoundMin()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
CBoundMin::~CBoundMin()
|
||||
{
|
||||
}
|
||||
|
||||
void CBoundMin::calculate()
|
||||
{
|
||||
|
||||
corners.clear();
|
||||
size_t N = chart.size();
|
||||
if (!N)
|
||||
return;
|
||||
|
||||
std::vector<Point2f> X(4 * N);
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
mcc::CChart cc = chart[i];
|
||||
for (size_t j = 0; j < 4; j++)
|
||||
{
|
||||
X[i * 4 + j] = cc.corners[j];
|
||||
}
|
||||
}
|
||||
|
||||
// media
|
||||
Point2f mu(0, 0);
|
||||
for (size_t i = 0; i < 4 * N; i++)
|
||||
mu += X[i];
|
||||
mu /= (4 * (int)N);
|
||||
|
||||
for (size_t i = 0; i < 4 * N; i++)
|
||||
X[i] -= mu;
|
||||
|
||||
// calculate all line
|
||||
std::vector<Point3f> L;
|
||||
L.resize(4 * N);
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
Point3f v0, v1, v2, v3;
|
||||
v0.x = X[4 * i + 0].x;
|
||||
v0.y = X[4 * i + 0].y;
|
||||
v0.z = 1;
|
||||
v1.x = X[4 * i + 1].x;
|
||||
v1.y = X[4 * i + 1].y;
|
||||
v1.z = 1;
|
||||
v2.x = X[4 * i + 2].x;
|
||||
v2.y = X[4 * i + 2].y;
|
||||
v2.z = 1;
|
||||
v3.x = X[4 * i + 3].x;
|
||||
v3.y = X[4 * i + 3].y;
|
||||
v3.z = 1;
|
||||
|
||||
L[4 * i + 0] = v0.cross(v1);
|
||||
L[4 * i + 1] = v1.cross(v2);
|
||||
L[4 * i + 2] = v2.cross(v3);
|
||||
L[4 * i + 3] = v3.cross(v0);
|
||||
}
|
||||
|
||||
// line convex hull
|
||||
std::vector<int> dist;
|
||||
dist.resize(4 * N);
|
||||
Point2f n;
|
||||
float d;
|
||||
|
||||
for (size_t i = 0; i < 4 * N; i++)
|
||||
{
|
||||
n.x = L[i].x;
|
||||
n.y = L[i].y;
|
||||
d = L[i].z;
|
||||
|
||||
int s = 0;
|
||||
for (size_t j = 0; j < N; j++)
|
||||
s += (X[j].dot(n) + d) <= 0;
|
||||
dist[i] = s;
|
||||
}
|
||||
|
||||
// sort
|
||||
std::vector<int> idx;
|
||||
std::vector<Point3f> Ls;
|
||||
Ls.resize(4 * N);
|
||||
mcc::sort(dist, idx);
|
||||
for (size_t i = 0; i < 4 * N; i++)
|
||||
Ls[i] = L[idx[i]];
|
||||
|
||||
std::vector<Point3f> Lc;
|
||||
Lc.resize(4 * N);
|
||||
Lc[0] = Ls[0];
|
||||
Point3f ln;
|
||||
|
||||
int j, k = 0;
|
||||
for (size_t i = 0; i < 4 * N; i++)
|
||||
{
|
||||
|
||||
ln = Ls[i]; //current line
|
||||
if (!validateLine(Lc, ln, k, j))
|
||||
{
|
||||
|
||||
Lc[k] = ln;
|
||||
k++;
|
||||
}
|
||||
else if ((abs(Lc[j].z) < abs(ln.z)) && (abs(dist[i] - dist[j]) < 2))
|
||||
{
|
||||
Lc[j] = ln;
|
||||
}
|
||||
if (k == 4 && abs(dist[i] - dist[k - 1]) > 2)
|
||||
break;
|
||||
}
|
||||
if (k < 4)
|
||||
return;
|
||||
|
||||
std::vector<float> thetas;
|
||||
thetas.resize(4);
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
thetas[i] = atan2(Lc[i].y / Lc[i].z, Lc[i].x / Lc[i].z);
|
||||
|
||||
sort(thetas, idx, false);
|
||||
std::vector<Point3f> lines;
|
||||
lines.resize(4);
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
lines[i] = Lc[idx[i]];
|
||||
|
||||
Point3f Vcart;
|
||||
Point2f Vhom;
|
||||
std::vector<Point2f> V;
|
||||
V.resize(4);
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
j = (i + 1) % 4;
|
||||
Vcart = lines[i].cross(lines[j]);
|
||||
if (fabs(Vcart.z) <= 1e-6){
|
||||
continue;
|
||||
}
|
||||
Vhom.x = Vcart.x / Vcart.z;
|
||||
Vhom.y = Vcart.y / Vcart.z;
|
||||
V[i] = Vhom + mu;
|
||||
}
|
||||
|
||||
corners = V;
|
||||
}
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,83 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_BOUND_MIN_HPP
|
||||
#define _MCC_BOUND_MIN_HPP
|
||||
|
||||
#include "charts.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
class CBoundMin
|
||||
{
|
||||
|
||||
public:
|
||||
CBoundMin();
|
||||
~CBoundMin();
|
||||
|
||||
void setCharts(const std::vector<CChart> &chartIn) { chart = chartIn; }
|
||||
void getCorners(std::vector<Point2f> &cornersOut) { cornersOut = corners; }
|
||||
void calculate();
|
||||
|
||||
private:
|
||||
std::vector<CChart> chart;
|
||||
std::vector<Point2f> corners;
|
||||
|
||||
private:
|
||||
bool validateLine(const std::vector<Point3f> &Lc, Point3f ln,
|
||||
int k, int &j)
|
||||
{
|
||||
|
||||
double theta;
|
||||
Point2d v0, v1;
|
||||
|
||||
for (j = 0; j < k; j++)
|
||||
{
|
||||
v0.x = Lc[j].x;
|
||||
v0.y = Lc[j].y;
|
||||
v1.x = ln.x;
|
||||
v1.y = ln.y;
|
||||
theta = v0.dot(v1) / (norm(v0) * norm(v1));
|
||||
theta = acos(theta);
|
||||
|
||||
if (theta < 0.5)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
} // namespace cv
|
||||
#endif //_MCC_BOUND_MIN_HPP
|
||||
@@ -0,0 +1,96 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "charts.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
CChart::CChart()
|
||||
: perimetro(0), area(0), large_side(0)
|
||||
{
|
||||
}
|
||||
|
||||
CChart::~CChart()
|
||||
{
|
||||
}
|
||||
|
||||
void CChart::
|
||||
setCorners(std::vector<Point2f> p)
|
||||
{
|
||||
Point v1, v2;
|
||||
if (p.empty())
|
||||
return;
|
||||
|
||||
// copy
|
||||
corners = p;
|
||||
|
||||
// Sort the corners in anti-clockwise order
|
||||
polyanticlockwise(corners);
|
||||
|
||||
// Properties
|
||||
area = contourArea(corners);
|
||||
perimetro = perimeter(corners);
|
||||
center = mace_center(corners);
|
||||
|
||||
v1 = corners[2] - corners[0];
|
||||
v2 = corners[3] - corners[1];
|
||||
large_side = std::max(norm(v1), norm(v2));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CChartDraw::
|
||||
CChartDraw(CChart &pChart, InputOutputArray image)
|
||||
: m_pChart(pChart), m_image(image.getMat())
|
||||
{
|
||||
}
|
||||
|
||||
void CChartDraw::
|
||||
drawContour(Scalar color /*= CV_RGB(0, 250, 0)*/) const
|
||||
{
|
||||
|
||||
//Draw lines
|
||||
int thickness = 2;
|
||||
line(m_image, (m_pChart).corners[0], (m_pChart).corners[1], color, thickness, LINE_AA);
|
||||
line(m_image, (m_pChart).corners[1], (m_pChart).corners[2], color, thickness, LINE_AA);
|
||||
line(m_image, (m_pChart).corners[2], (m_pChart).corners[3], color, thickness, LINE_AA);
|
||||
line(m_image, (m_pChart).corners[3], (m_pChart).corners[0], color, thickness, LINE_AA);
|
||||
}
|
||||
|
||||
void CChartDraw::
|
||||
drawCenter(Scalar color /*= CV_RGB(0, 0, 255)*/) const
|
||||
{
|
||||
int radius = 3;
|
||||
int thickness = 2;
|
||||
circle(m_image, (m_pChart).center, radius, color, thickness);
|
||||
}
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,90 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_CHARTS_HPP
|
||||
#define _MCC_CHARTS_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
/** @brief Chart model
|
||||
*
|
||||
* .--------. <- px,py
|
||||
* | | one chart for checker color
|
||||
* | RGB |
|
||||
* | Lab |
|
||||
* | |
|
||||
* .--------.
|
||||
*
|
||||
* @author Pedro Marrero Fernndez
|
||||
*/
|
||||
|
||||
class CChart
|
||||
{
|
||||
|
||||
public:
|
||||
CChart();
|
||||
~CChart();
|
||||
|
||||
/** @brief set corners
|
||||
*@param p[in] new corners
|
||||
*/
|
||||
void setCorners(std::vector<Point2f> p);
|
||||
|
||||
public:
|
||||
std::vector<Point2f> corners;
|
||||
Point2f center;
|
||||
double perimetro;
|
||||
double area;
|
||||
double large_side;
|
||||
};
|
||||
|
||||
/** @brief Chart draw */
|
||||
class CChartDraw
|
||||
{
|
||||
public:
|
||||
/** @brief contructor */
|
||||
CChartDraw(CChart &pChart, InputOutputArray image);
|
||||
|
||||
/** @brief draw the chart contour over the image */
|
||||
void drawContour(Scalar color = CV_RGB(0, 250, 0)) const;
|
||||
|
||||
/** @brief draw the chart center over the image */
|
||||
void drawCenter(Scalar color = CV_RGB(0, 0, 255)) const;
|
||||
|
||||
private:
|
||||
CChart &m_pChart;
|
||||
Mat m_image;
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif //_MCC_CHARTS_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,207 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_CHECKER_DETECTOR_HPP
|
||||
#define _MCC_CHECKER_DETECTOR_HPP
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "charts.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
class CCheckerDetectorImpl : public CCheckerDetector
|
||||
{
|
||||
|
||||
typedef std::vector<Point> PointsVector;
|
||||
typedef std::vector<PointsVector> ContoursVector;
|
||||
|
||||
public:
|
||||
CCheckerDetectorImpl();
|
||||
CCheckerDetectorImpl(const dnn::Net& _net){
|
||||
net = _net;
|
||||
}
|
||||
virtual ~CCheckerDetectorImpl();
|
||||
|
||||
bool process(InputArray image, const std::vector<Rect> ®ionsOfInterest,
|
||||
const int nc = 1) CV_OVERRIDE;
|
||||
|
||||
bool process(InputArray image, const int nc = 1) CV_OVERRIDE;
|
||||
|
||||
Ptr<CChecker> getBestColorChecker() CV_OVERRIDE
|
||||
{
|
||||
if (m_checkers.size())
|
||||
return m_checkers[0];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Ptr<CChecker>> getListColorChecker() CV_OVERRIDE
|
||||
{
|
||||
return m_checkers;
|
||||
}
|
||||
virtual Mat getRefColors() CV_OVERRIDE;
|
||||
|
||||
virtual void setDetectionParams(const DetectorParametersMCC ¶ms) CV_OVERRIDE;
|
||||
|
||||
virtual void setColorChartType(ColorChart chartType) CV_OVERRIDE;
|
||||
|
||||
virtual void setUseDnnModel(bool useDnn) CV_OVERRIDE;
|
||||
|
||||
virtual bool getUseDnnModel() const CV_OVERRIDE;
|
||||
|
||||
virtual const DetectorParametersMCC& getDetectionParams() const CV_OVERRIDE;
|
||||
|
||||
virtual ColorChart getColorChartType() const CV_OVERRIDE;
|
||||
|
||||
virtual void draw(std::vector<Ptr<CChecker>>& checkers, InputOutputArray img, const Scalar color = CV_RGB(0,250,0), const int thickness = 2) CV_OVERRIDE;
|
||||
|
||||
protected: // methods pipeline
|
||||
bool _no_net_process(InputArray image, const int nc, std::vector<Rect> regionsOfInterest);
|
||||
/// prepareImage
|
||||
/** @brief Prepare Image
|
||||
* @param bgrMat image in color space BGR
|
||||
* @param grayOut gray scale
|
||||
* @param bgrOut rescale image
|
||||
* @param aspOut aspect ratio
|
||||
* @param max_size rescale factor in max dim
|
||||
*/
|
||||
virtual void
|
||||
prepareImage(InputArray bgr, OutputArray grayOut, OutputArray bgrOut, float &aspOut) const;
|
||||
|
||||
/// performThreshold
|
||||
/** @brief Adaptative threshold
|
||||
* @param grayscaleImg gray scale image
|
||||
* @param thresholdImg binary image
|
||||
* @param wndx, wndy windows size
|
||||
* @param step
|
||||
*/
|
||||
virtual void
|
||||
performThreshold(InputArray grayscaleImg, OutputArrayOfArrays thresholdImg) const;
|
||||
|
||||
/// findContours
|
||||
/** @brief find contour in the image
|
||||
* @param srcImg binary imagen
|
||||
* @param contours
|
||||
* @param minContourPointsAllowed
|
||||
*/
|
||||
virtual void
|
||||
findContours(InputArray srcImg, ContoursVector &contours) const;
|
||||
|
||||
/// findCandidates
|
||||
/** @brief find posibel candidates
|
||||
* @param contours
|
||||
* @param detectedCharts
|
||||
* @param minContourLengthAllowed
|
||||
*/
|
||||
virtual void
|
||||
findCandidates(const ContoursVector &contours, std::vector<CChart> &detectedCharts);
|
||||
|
||||
/// clustersAnalysis
|
||||
/** @brief clusters charts analysis
|
||||
* @param detectedCharts
|
||||
* @param groups
|
||||
*/
|
||||
virtual void
|
||||
clustersAnalysis(const std::vector<CChart> &detectedCharts, std::vector<int> &groups);
|
||||
|
||||
/// checkerRecognize
|
||||
/** @brief checker color recognition
|
||||
* @param img
|
||||
* @param detectedCharts
|
||||
* @param G
|
||||
* @param colorChartsOut
|
||||
*/
|
||||
virtual void
|
||||
checkerRecognize(InputArray img, const std::vector<CChart> &detectedCharts, const std::vector<int> &G,
|
||||
std::vector<std::vector<Point2f>> &colorChartsOut);
|
||||
|
||||
/// checkerAnalysis
|
||||
/** @brief evaluate checker
|
||||
* @param img
|
||||
* @param img_org
|
||||
* @param colorCharts
|
||||
* @param checker
|
||||
* @param asp
|
||||
*/
|
||||
virtual void
|
||||
checkerAnalysis(InputArray img_rgb_f, const unsigned int nc,
|
||||
const std::vector<std::vector<Point2f>> &colorCharts,
|
||||
std::vector<Ptr<CChecker>> &checkers, float asp,
|
||||
const Mat &img_rgb_org,
|
||||
const Mat &img_ycbcr_org,
|
||||
std::vector<Mat> &rgb_planes,
|
||||
std::vector<Mat> &ycbcr_planes);
|
||||
|
||||
virtual void
|
||||
removeTooCloseDetections();
|
||||
|
||||
protected:
|
||||
std::vector<Ptr<CChecker>> m_checkers;
|
||||
dnn::Net net;
|
||||
DetectorParametersMCC m_params = DetectorParametersMCC();
|
||||
ColorChart m_chartType;
|
||||
bool m_useDnn = true;
|
||||
|
||||
private: // methods aux
|
||||
void get_subbox_chart_physical(
|
||||
const std::vector<Point2f> &points,
|
||||
std::vector<Point2f> &chartPhy);
|
||||
|
||||
void reduce_array(
|
||||
const std::vector<float> &x,
|
||||
std::vector<float> &x_new,
|
||||
float tol);
|
||||
|
||||
void transform_points_inverse(
|
||||
InputArray T,
|
||||
const std::vector<Point2f> &X,
|
||||
std::vector<Point2f> &Xt);
|
||||
|
||||
void get_profile(
|
||||
const std::vector<Point2f> &ibox,
|
||||
OutputArray charts_rgb,
|
||||
OutputArray charts_ycbcr,
|
||||
InputArray im_rgb,
|
||||
InputArray im_ycbcr,
|
||||
std::vector<Mat> &rgb_planes,
|
||||
std::vector<Mat> &ycbcr_planes);
|
||||
|
||||
/** @brief cost function
|
||||
* e(p) = ||f(p)||^2 = \sum_k (mu_{k,p}*r_k')/||mu_{k,p}||||r_k|| + ...
|
||||
* + \sum_k || \sigma_{k,p} ||^2
|
||||
*/
|
||||
float cost_function(InputArray img, InputOutputArray mask, InputArray lab,
|
||||
const std::vector<Point2f> &ibox);
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif //_MCC_CHECKER_DETECTOR_HPP
|
||||
@@ -0,0 +1,487 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include "checker_model.hpp"
|
||||
#include "dictionary.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// CChartModel
|
||||
CChartModel::CChartModel(const ColorChart chartType)
|
||||
{
|
||||
switch (chartType)
|
||||
{
|
||||
case MCC24: //Standard
|
||||
size = Size2i(4, 6);
|
||||
boxsize = Size2f(11.25, 16.75);
|
||||
box.resize(4);
|
||||
box[0] = Point2f(0.00, 0.00);
|
||||
box[1] = Point2f(16.75, 0.00);
|
||||
box[2] = Point2f(16.75, 11.25);
|
||||
box[3] = Point2f(0.00, 11.25);
|
||||
|
||||
cellchart.assign(CChartClassicModelCellchart, CChartClassicModelCellchart + 4 * 24);
|
||||
center.assign(CChartClassicModelCenter, CChartClassicModelCenter + 24);
|
||||
|
||||
chart.resize(size.area(), std::vector<float>(9));
|
||||
for(int color = 0 ; color < (int)chart.size() ; color++)
|
||||
chart[color].assign(CChartClassicModelColors[color] , CChartClassicModelColors[color] + 9 );
|
||||
|
||||
break;
|
||||
case SG140: //DigitalSG
|
||||
size = Size2i(10, 14);
|
||||
boxsize = Size2f(27.75, 38.75);
|
||||
box.resize(4);
|
||||
box[0] = Point2f(0.00, 0.00);
|
||||
box[1] = Point2f(38.75, 0.00);
|
||||
box[2] = Point2f(38.75, 27.75);
|
||||
box[3] = Point2f(0.00, 27.75);
|
||||
|
||||
cellchart.assign(CChartDigitalSGCellchart, CChartDigitalSGCellchart + 4 * 140);
|
||||
center.assign(CChartDigitalSGCenter, CChartDigitalSGCenter + 140);
|
||||
|
||||
chart.resize(size.area(), std::vector<float>(9));
|
||||
for(int color = 0 ; color < (int)chart.size() ; color++)
|
||||
chart[color].assign(CChartDigitalSGColors[color] , CChartDigitalSGColors[color] + 9 );
|
||||
|
||||
break;
|
||||
case VINYL18: //Vinyl
|
||||
size = Size2i(3, 6);
|
||||
boxsize = Size2f(12.50, 18.25);
|
||||
box.resize(4);
|
||||
box[0] = Point2f(0.00, 0.00);
|
||||
box[1] = Point2f(18.25, 0.00);
|
||||
box[2] = Point2f(18.25, 12.50);
|
||||
box[3] = Point2f(0.00, 12.50);
|
||||
|
||||
cellchart.assign(CChartVinylCellchart, CChartVinylCellchart + 4 * 18);
|
||||
center.assign(CChartVinylCenter, CChartVinylCenter + 18);
|
||||
|
||||
chart.resize(size.area(), std::vector<float>(9));
|
||||
for(int color = 0 ; color < (int)chart.size() ; color++)
|
||||
chart[color].assign(CChartVinylColors[color] , CChartVinylColors[color] + 9 );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CChartModel::~CChartModel()
|
||||
{
|
||||
}
|
||||
|
||||
bool CChartModel::
|
||||
evaluate(const SUBCCMModel &subModel, int &offset, int &iTheta, float &error)
|
||||
{
|
||||
|
||||
float tError;
|
||||
int tTheta, tOffset;
|
||||
error = INFINITY;
|
||||
bool beval = false;
|
||||
|
||||
// para todas las orientaciones
|
||||
// min_{ theta,dt } | CC_e - CC |
|
||||
for (tTheta = 0; tTheta < 8; tTheta++)
|
||||
{
|
||||
if (match(subModel, tTheta, tError, tOffset) && tError < error)
|
||||
{
|
||||
error = tError;
|
||||
iTheta = tTheta;
|
||||
offset = tOffset;
|
||||
beval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return beval;
|
||||
}
|
||||
|
||||
void CChartModel::
|
||||
copyToColorMat(OutputArray lab, int cs)
|
||||
{
|
||||
size_t N, M, k;
|
||||
|
||||
N = size.width;
|
||||
M = size.height;
|
||||
Mat im_lab_org((int)N, (int)M, CV_32FC3);
|
||||
int type_color = 3 * cs;
|
||||
k = 0;
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
for (size_t j = 0; j < M; j++)
|
||||
{
|
||||
Vec3f &lab_values = im_lab_org.at<Vec3f>((int)i, (int)j);
|
||||
lab_values[0] = chart[k][type_color + 0];
|
||||
lab_values[1] = chart[k][type_color + 1];
|
||||
lab_values[2] = chart[k][type_color + 2];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
lab.assign(im_lab_org);
|
||||
}
|
||||
|
||||
void mcc::CChartModel::
|
||||
rotate90()
|
||||
{
|
||||
|
||||
size = Size2i(size.height, size.width);
|
||||
|
||||
//the matrix is roated clockwise 90 degree, so first row will become last column, second row second last column and so on
|
||||
//doing this inplace will make the code a bit hard to read, so creating a temporary array
|
||||
|
||||
std::vector<Point2f> _cellchart(cellchart.size());
|
||||
std::vector<Point2f> _center(center.size());
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < size.width; i++)
|
||||
{
|
||||
for (int j = 0; j < size.height; j++)
|
||||
{
|
||||
//k contains the new coordintes,
|
||||
int old_i = size.height - j - 1;
|
||||
int old_j = i;
|
||||
int old_k = (old_i)*size.width + old_j;
|
||||
|
||||
_cellchart[4 * k + 0] = cellchart[4 * old_k + 3];
|
||||
_cellchart[4 * k + 1] = cellchart[4 * old_k + 0];
|
||||
_cellchart[4 * k + 2] = cellchart[4 * old_k + 1];
|
||||
_cellchart[4 * k + 3] = cellchart[4 * old_k + 2];
|
||||
|
||||
// center
|
||||
_center[k] = center[old_k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
cellchart = _cellchart;
|
||||
center = _center;
|
||||
|
||||
boxsize = Size2f(boxsize.height, boxsize.width);
|
||||
}
|
||||
|
||||
void mcc::CChartModel::
|
||||
flip()
|
||||
{
|
||||
|
||||
std::vector<Point2f> _cellchart(cellchart.size());
|
||||
std::vector<Point2f> _center(center.size());
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < size.width; i++)
|
||||
{
|
||||
for (int j = 0; j < size.height; j++)
|
||||
{
|
||||
//k contains the new coordintes,
|
||||
int old_i = i;
|
||||
int old_j = size.height - j - 1;
|
||||
int old_k = (old_i)*size.height + old_j;
|
||||
|
||||
_cellchart[4 * k + 0] = cellchart[4 * old_k + 1];
|
||||
_cellchart[4 * k + 1] = cellchart[4 * old_k + 0];
|
||||
_cellchart[4 * k + 2] = cellchart[4 * old_k + 3];
|
||||
_cellchart[4 * k + 3] = cellchart[4 * old_k + 2];
|
||||
|
||||
// center
|
||||
_center[k] = center[old_k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
cellchart = _cellchart;
|
||||
center = _center;
|
||||
}
|
||||
|
||||
float CChartModel::
|
||||
dist_color_lab(InputArray lab1, InputArray lab2)
|
||||
{
|
||||
|
||||
int N = lab1.rows();
|
||||
float dist = 0, dist_i;
|
||||
|
||||
Mat _lab1 = lab1.getMat(), _lab2 = lab2.getMat();
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
Vec3f v1 = _lab1.at<Vec3f>(i, 0);
|
||||
Vec3f v2 = _lab2.at<Vec3f>(i, 0);
|
||||
// v1[0] = 1;
|
||||
// v2[0] = 1; // L <- 0
|
||||
|
||||
// euclidean
|
||||
Vec3f v = v1 - v2;
|
||||
dist_i = v.dot(v);
|
||||
dist += sqrt(dist_i);
|
||||
|
||||
// cosine
|
||||
//float costh = v1.dot(v2) / (norm(v1)*norm(v2));
|
||||
//dist += 1 - (1 + costh) / 2;
|
||||
}
|
||||
|
||||
dist /= N;
|
||||
return dist;
|
||||
}
|
||||
|
||||
bool CChartModel::
|
||||
match(const SUBCCMModel &subModel, int iTheta, float &error, int &ierror)
|
||||
{
|
||||
|
||||
size_t N, M, k;
|
||||
|
||||
N = size.width;
|
||||
M = size.height;
|
||||
Mat im_lab_org((int)N, (int)M, CV_32FC3);
|
||||
int type_color = 3;
|
||||
k = 0;
|
||||
|
||||
for (size_t i = 0; i < N; i++)
|
||||
{
|
||||
for (size_t j = 0; j < M; j++)
|
||||
{
|
||||
Vec3f &lab = im_lab_org.at<Vec3f>((int)i, (int)j);
|
||||
lab[0] = chart[k][type_color + 0];
|
||||
lab[1] = chart[k][type_color + 1];
|
||||
lab[2] = chart[k][type_color + 2];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
rot90(im_lab_org, iTheta);
|
||||
N = im_lab_org.rows;
|
||||
M = im_lab_org.cols;
|
||||
|
||||
size_t n, m;
|
||||
n = subModel.color_size.height;
|
||||
m = subModel.color_size.width;
|
||||
|
||||
// boundary condition
|
||||
if (N < n || M < m)
|
||||
return false;
|
||||
|
||||
// rgb to La*b*
|
||||
Mat rgb_est = subModel.sub_chart;
|
||||
Mat lab_est;
|
||||
|
||||
cvtColor(rgb_est, lab_est, COLOR_BGR2Lab);
|
||||
|
||||
size_t nN, mM;
|
||||
nN = N - n + 1;
|
||||
mM = M - m + 1;
|
||||
std::vector<float> lEcm(nN * mM);
|
||||
k = 0;
|
||||
for (size_t i = 0; i < nN; i++)
|
||||
{
|
||||
for (size_t j = 0; j < mM; j++)
|
||||
{
|
||||
Mat lab_curr, lab_roi;
|
||||
lab_roi = im_lab_org(Rect((int)j, (int)i, (int)m, (int)n));
|
||||
lab_roi.copyTo(lab_curr);
|
||||
lab_curr = lab_curr.t();
|
||||
lab_curr = lab_curr.reshape(3, (int)n * (int)m);
|
||||
|
||||
// Mean squared error
|
||||
// ECM = 1 / N sum_i(Y - Yp) ^ 2
|
||||
lEcm[k] = dist_color_lab(lab_curr, lab_est) / (M * N);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// minimo
|
||||
error = lEcm[0];
|
||||
ierror = 0;
|
||||
for (int i = 1; i < (int)lEcm.size(); i++)
|
||||
if (error > lEcm[i])
|
||||
{
|
||||
error = lEcm[i];
|
||||
ierror = i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CChartModel::
|
||||
rot90(InputOutputArray mat, int itheta)
|
||||
{
|
||||
|
||||
//1=CW, 2=CCW, 3=180
|
||||
switch (itheta)
|
||||
{
|
||||
case 1: //transpose+flip(1)=CW
|
||||
transpose(mat, mat);
|
||||
cv::flip(mat, mat, 1);
|
||||
break;
|
||||
case 2: //flip(-1)=180
|
||||
cv::flip(mat, mat, -1);
|
||||
break;
|
||||
case 3: //transpose+flip(0)=CCW
|
||||
transpose(mat, mat);
|
||||
cv::flip(mat, mat, 0);
|
||||
break;
|
||||
//flipped images start here
|
||||
case 4: //flip(1)=no rotation, just flipped
|
||||
cv::flip(mat, mat, 1);
|
||||
break;
|
||||
case 5: //flip(1)+transpose + flip(1)=CW
|
||||
cv::flip(mat, mat, 1);
|
||||
transpose(mat, mat);
|
||||
cv::flip(mat, mat, 1);
|
||||
break;
|
||||
case 6: //flip(1)+flip(-1)=180
|
||||
cv::flip(mat, mat, 1);
|
||||
cv::flip(mat, mat, -1);
|
||||
break;
|
||||
case 7: //flip(1)+transpose+flip(0)=CCW
|
||||
cv::flip(mat, mat, 1);
|
||||
transpose(mat, mat);
|
||||
cv::flip(mat, mat, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// // CChecker
|
||||
|
||||
Ptr<CChecker> CChecker::create()
|
||||
{
|
||||
return makePtr<CCheckerImpl>();
|
||||
}
|
||||
|
||||
void CCheckerImpl::setTarget(ColorChart _target)
|
||||
{
|
||||
target = _target;
|
||||
}
|
||||
void CCheckerImpl::setBox(std::vector<Point2f> _box)
|
||||
{
|
||||
box = _box;
|
||||
}
|
||||
void CCheckerImpl::setChartsRGB(Mat _chartsRGB)
|
||||
{
|
||||
chartsRGB = _chartsRGB;
|
||||
}
|
||||
void CCheckerImpl::setChartsYCbCr(Mat _chartsYCbCr)
|
||||
{
|
||||
chartsYCbCr = _chartsYCbCr;
|
||||
}
|
||||
void CCheckerImpl::setCost(float _cost)
|
||||
{
|
||||
cost = _cost;
|
||||
}
|
||||
void CCheckerImpl::setCenter(Point2f _center)
|
||||
{
|
||||
center = _center;
|
||||
}
|
||||
|
||||
ColorChart CCheckerImpl::getTarget()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
std::vector<Point2f> CCheckerImpl::getBox()
|
||||
{
|
||||
return box;
|
||||
}
|
||||
std::vector<Point2f> CCheckerImpl::getColorCharts()
|
||||
{
|
||||
// color chart classic model
|
||||
CChartModel cccm(getTarget());
|
||||
Mat lab;
|
||||
size_t N;
|
||||
std::vector<Point2f> fbox = cccm.box;
|
||||
std::vector<Point2f> cellchart = cccm.cellchart;
|
||||
std::vector<Point2f> charts(cellchart.size());
|
||||
|
||||
// tranformation
|
||||
Matx33f ccT = getPerspectiveTransform(fbox, getBox());
|
||||
|
||||
std::vector<Point2f> bch(4), bcht(4);
|
||||
N = cellchart.size() / 4;
|
||||
for (size_t i = 0, k; i < N; i++)
|
||||
{
|
||||
k = 4 * i;
|
||||
for (size_t j = 0ull; j < 4ull; j++)
|
||||
bch[j] = cellchart[k + j];
|
||||
|
||||
polyanticlockwise(bch);
|
||||
transform_points_forward(ccT, bch, bcht);
|
||||
|
||||
Point2f c(0, 0);
|
||||
for (size_t j = 0; j < 4; j++)
|
||||
c += bcht[j];
|
||||
c /= 4;
|
||||
for (size_t j = 0ull; j < 4ull; j++)
|
||||
charts[k+j] = ((bcht[j] - c) * 0.50) + c;
|
||||
}
|
||||
return charts;
|
||||
}
|
||||
Mat CCheckerImpl::getChartsRGB(bool getStats /* = true */)
|
||||
{
|
||||
if (!getStats){
|
||||
Mat src = chartsRGB.col(1).clone().reshape(3, chartsRGB.rows/3);
|
||||
return src;
|
||||
}
|
||||
return chartsRGB;
|
||||
}
|
||||
Mat CCheckerImpl::getChartsYCbCr()
|
||||
{
|
||||
return chartsYCbCr;
|
||||
}
|
||||
float CCheckerImpl::getCost()
|
||||
{
|
||||
return cost;
|
||||
}
|
||||
Point2f CCheckerImpl::getCenter()
|
||||
{
|
||||
return center;
|
||||
}
|
||||
|
||||
void transform_points_forward(const Matx33f& T, const std::vector<Point2f> &X, std::vector<Point2f> &Xt)
|
||||
{
|
||||
size_t N = X.size();
|
||||
if (Xt.size() != N)
|
||||
Xt.resize(N);
|
||||
std::fill(Xt.begin(), Xt.end(), Point2f(0.f, 0.f));
|
||||
if (N == 0)
|
||||
return;
|
||||
|
||||
Matx31f p, xt;
|
||||
Point2f pt;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,161 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_CHECKER_MODEL_HPP
|
||||
#define _MCC_CHECKER_MODEL_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
//! @addtogroup mcc
|
||||
//! @{
|
||||
|
||||
/** CChartModel
|
||||
*
|
||||
* @brief Class for handing the different chart models.
|
||||
*
|
||||
* This class contains the variables and functions which are specific
|
||||
* to a given chart type and will be used for it detections.
|
||||
|
||||
*/
|
||||
|
||||
class CChartModel
|
||||
{
|
||||
|
||||
public:
|
||||
/** SUBCCMModel
|
||||
*
|
||||
* @brief Information about a continuous subregion of the chart.
|
||||
*
|
||||
* Usually not all the cells of the chart can be detected by the
|
||||
* detector. This submodel contains the information about the
|
||||
* detected squares.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
_SUBCCMModel
|
||||
{
|
||||
|
||||
Mat sub_chart;
|
||||
Size2i color_size;
|
||||
std::vector<Point2f> centers;
|
||||
|
||||
} SUBCCMModel;
|
||||
|
||||
public:
|
||||
CChartModel(const ColorChart chartType);
|
||||
~CChartModel();
|
||||
|
||||
/** @brief evaluate submodel in this checker type*/
|
||||
bool evaluate(const SUBCCMModel &subModel, int &offset, int &iTheta, float &error);
|
||||
|
||||
// function utils
|
||||
|
||||
void copyToColorMat(OutputArray lab, int cs = 0);
|
||||
void rotate90();
|
||||
void flip();
|
||||
|
||||
public:
|
||||
// Cie L*a*b* values use illuminant D50 2 degree observer sRGB values for
|
||||
// for iluminante D65.
|
||||
|
||||
Size2i size;
|
||||
Size2f boxsize;
|
||||
std::vector<Point2f> box;
|
||||
std::vector<Point2f> cellchart;
|
||||
std::vector<Point2f> center;
|
||||
std::vector<std::vector<float>> chart;
|
||||
|
||||
protected:
|
||||
/** \brief match checker color
|
||||
* \param[in] subModel sub-checker
|
||||
* \param[in] iTheta angle
|
||||
* \param[out] error
|
||||
* \param[out] ierror
|
||||
* \return state
|
||||
*/
|
||||
bool match(const SUBCCMModel &subModel, int iTheta, float &error, int &ierror);
|
||||
|
||||
/** \brief euclidian dist L2 for Lab space
|
||||
* \note
|
||||
* \f$ \sum_i \sqrt (\sum_k (ab1-ab2)_k.^2) \f$
|
||||
* \param[in] lab1
|
||||
* \param[in] lab2
|
||||
* \return distance
|
||||
*/
|
||||
float dist_color_lab(InputArray lab1, InputArray lab2);
|
||||
|
||||
/** \brief rotate matrix 90 degree */
|
||||
void rot90(InputOutputArray mat, int itheta);
|
||||
};
|
||||
/** CChecker
|
||||
*
|
||||
* \brief checker model
|
||||
* \author Pedro Marrero Fernandez
|
||||
*
|
||||
*/
|
||||
class CCheckerImpl : public CChecker
|
||||
{
|
||||
public:
|
||||
public:
|
||||
CCheckerImpl() {}
|
||||
~CCheckerImpl() {}
|
||||
|
||||
void setTarget(ColorChart _target) CV_OVERRIDE;
|
||||
void setBox(std::vector<Point2f> _box) 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;
|
||||
|
||||
ColorChart getTarget() CV_OVERRIDE;
|
||||
std::vector<Point2f> getBox() CV_OVERRIDE;
|
||||
std::vector<Point2f> getColorCharts() CV_OVERRIDE;
|
||||
Mat getChartsRGB(bool getStats = true) CV_OVERRIDE;
|
||||
Mat getChartsYCbCr() CV_OVERRIDE;
|
||||
float getCost() CV_OVERRIDE;
|
||||
Point2f getCenter() CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
ColorChart target; ///< type of checkercolor
|
||||
std::vector<Point2f> box; ///< positions of the corners
|
||||
Mat chartsRGB; ///< charts profile in rgb color space
|
||||
Mat chartsYCbCr; ///< charts profile in YCbCr color space
|
||||
float cost; ///< cost to aproximate
|
||||
Point2f center; ///< center of the chart.
|
||||
};
|
||||
// @}
|
||||
|
||||
void transform_points_forward(const Matx33f& T, const std::vector<Point2f> &X, std::vector<Point2f> &Xt);
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif //_MCC_CHECKER_MODEL_HPP
|
||||
@@ -0,0 +1,111 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
Rect poly2mask(const std::vector<Point2f> &poly, Size size, InputOutputArray mask)
|
||||
{
|
||||
// Create Polygon from vertices
|
||||
std::vector<Point> roi_poly;
|
||||
approxPolyDP(poly, roi_poly, 1.0, true);
|
||||
|
||||
Rect roi = boundingRect(roi_poly);
|
||||
|
||||
// Fill polygon white
|
||||
fillConvexPoly(mask, &roi_poly[0], (int)roi_poly.size(), 1, 8, 0);
|
||||
|
||||
roi &= Rect(0, 0, size.width, size.height);
|
||||
if (roi.empty())
|
||||
roi = Rect(0, 0, 1, 1);
|
||||
return roi;
|
||||
}
|
||||
|
||||
float perimeter(const std::vector<Point2f> &ps)
|
||||
{
|
||||
float sum = 0, dx, dy;
|
||||
|
||||
for (size_t i = 0; i < ps.size(); i++)
|
||||
{
|
||||
int i2 = (i + 1) % (int)ps.size();
|
||||
|
||||
dx = ps[i].x - ps[i2].x;
|
||||
dy = ps[i].y - ps[i2].y;
|
||||
|
||||
sum += sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
Point2f
|
||||
mace_center(const std::vector<Point2f> &ps)
|
||||
{
|
||||
Point2f center;
|
||||
int n;
|
||||
|
||||
center = Point2f(0);
|
||||
n = (int)ps.size();
|
||||
for (int i = 0; i < n; i++)
|
||||
center += ps[i];
|
||||
center /= n;
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
void polyanticlockwise(std::vector<Point2f> &points)
|
||||
{
|
||||
// Sort the points in anti-clockwise order
|
||||
// Trace a line between the first and second point.
|
||||
// If the third point is at the right side, then the points are anti-clockwise
|
||||
Point2f v1 = points[1] - points[0];
|
||||
Point2f v2 = points[2] - points[0];
|
||||
|
||||
//if the third point is in the left side, then sort in anti-clockwise order
|
||||
if ((v1.x * v2.y) - (v1.y * v2.x) < 0.0)
|
||||
std::swap(points[1], points[3]);
|
||||
}
|
||||
void polyclockwise(std::vector<Point2f> &points)
|
||||
{
|
||||
// Sort the points in clockwise order
|
||||
// Trace a line between the first and second point.
|
||||
// If the third point is at the right side, then the points are clockwise
|
||||
Point2f v1 = points[1] - points[0];
|
||||
Point2f v2 = points[2] - points[0];
|
||||
|
||||
//if the third point is in the left side, then sort in clockwise order
|
||||
if ((v1.x * v2.y) - (v1.y * v2.x) > 0.0)
|
||||
std::swap(points[1], points[3]);
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,133 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_COMMON_HPP
|
||||
#define _MCC_COMMON_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
Rect poly2mask(const std::vector<Point2f> &poly, Size size, InputOutputArray mask);
|
||||
|
||||
template <typename T>
|
||||
void circshift(std::vector<T> &A, int shiff)
|
||||
{
|
||||
if (A.empty() || shiff < 1)
|
||||
return;
|
||||
int n = A.size();
|
||||
|
||||
if (shiff >= n)
|
||||
return;
|
||||
|
||||
std::vector<T> Tmp(n);
|
||||
for (int i = shiff; i < n + shiff; i++)
|
||||
Tmp[(i % n)] = A[i - shiff];
|
||||
|
||||
A = Tmp;
|
||||
}
|
||||
|
||||
float perimeter(const std::vector<Point2f> &ps);
|
||||
|
||||
Point2f mace_center(const std::vector<Point2f> &ps);
|
||||
|
||||
template <typename T>
|
||||
void unique(const std::vector<T> &A, std::vector<T> &U)
|
||||
{
|
||||
|
||||
int n = (int)A.size();
|
||||
std::vector<T> Tm = A;
|
||||
|
||||
std::sort(Tm.begin(), Tm.end());
|
||||
|
||||
U.clear();
|
||||
U.push_back(Tm[0]);
|
||||
for (int i = 1; i < n; i++)
|
||||
if (Tm[i] != Tm[i - 1])
|
||||
U.push_back(Tm[i]);
|
||||
}
|
||||
|
||||
void polyanticlockwise(std::vector<Point2f> &points);
|
||||
void polyclockwise(std::vector<Point2f> &points);
|
||||
|
||||
// Does lexical cast of the input argument to string
|
||||
template <typename T>
|
||||
std::string ToString(const T &value)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << value;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void change(T &a, T &b)
|
||||
{
|
||||
T c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void sort(std::vector<T> &A, std::vector<int> &idx, bool ord = true)
|
||||
{
|
||||
size_t N = A.size();
|
||||
if (N == 0)
|
||||
return;
|
||||
|
||||
idx.clear();
|
||||
idx.resize(N);
|
||||
for (size_t i = 0; i < N; i++)
|
||||
idx[i] = (int)i;
|
||||
|
||||
for (size_t i = 0; i < N - 1; i++)
|
||||
{
|
||||
|
||||
size_t k = i;
|
||||
T valor = A[i];
|
||||
for (size_t j = i + 1; j < N; j++)
|
||||
{
|
||||
if ((A[j] < valor && ord) || (A[j] > valor && !ord))
|
||||
{
|
||||
valor = A[j];
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (k == i)
|
||||
continue;
|
||||
|
||||
change(A[i], A[k]);
|
||||
change(idx[i], idx[k]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif //_MCC_COMMON_HPP
|
||||
@@ -0,0 +1,68 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#ifdef MCC_DEBUG
|
||||
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
Scalar randomcolor(RNG &rng)
|
||||
{
|
||||
int icolor = (unsigned)rng;
|
||||
return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
|
||||
}
|
||||
|
||||
void imshow_250xN(const std::string &name_, InputArray patch)
|
||||
{
|
||||
|
||||
Mat bigpatch;
|
||||
Size size = patch.size();
|
||||
float asp = (float)size.height / size.width;
|
||||
int new_size = 550;
|
||||
resize(patch, bigpatch, Size((int)new_size, int(new_size * asp)));
|
||||
imshow(name_, bigpatch);
|
||||
}
|
||||
|
||||
void showAndSave(std::string name, InputArray m, std::string path)
|
||||
{
|
||||
imshow_250xN(name, m);
|
||||
imwrite(path + "/" + name + ".png", m);
|
||||
if (waitKey(0) == 'q')
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_DEBUG_HPP
|
||||
#define _MCC_DEBUG_HPP
|
||||
|
||||
#include "opencv2/objdetect/mcc_checker_detector.hpp"
|
||||
#ifdef MCC_DEBUG
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
Scalar randomcolor(RNG &rng);
|
||||
|
||||
void imshow_250xN(const std::string &name_, InputArray patch);
|
||||
|
||||
void showAndSave(std::string name, InputArray m, std::string path);
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
||||
|
||||
#endif //_MCC_DEBUG_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "graph_cluster.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
CB0cluster::CB0cluster()
|
||||
{
|
||||
}
|
||||
|
||||
CB0cluster::~CB0cluster()
|
||||
{
|
||||
}
|
||||
|
||||
void CB0cluster::
|
||||
group()
|
||||
{
|
||||
|
||||
size_t n = X.size();
|
||||
G.clear();
|
||||
G.resize(n);
|
||||
|
||||
for (int i = 0; i < (int)n - 1; i++)
|
||||
{
|
||||
std::vector<double> Y;
|
||||
Y.clear();
|
||||
Y.resize(n - i);
|
||||
Y[0] = 0;
|
||||
|
||||
// 1. group similar blobs
|
||||
double dist, w, y;
|
||||
for (int j = i + 1, k = 1; j < (int)n; j++, k++)
|
||||
{
|
||||
//dist(X_i,X_j)
|
||||
dist = norm(X[i] - X[j]);
|
||||
|
||||
//heuristic to combine two sub charts, This is pretty ugly at the moment,
|
||||
//Looking for somthing better
|
||||
w = min(abs(W[i] - W[j]) / (W[i] + W[j]),
|
||||
abs(max(W[i], W[j]) - 24 / 11.0f * min(W[i], W[j])) / (max(W[i], W[j]) + 24 / 11.0f * min(W[i], W[j])));
|
||||
w = (w < 0.1);
|
||||
|
||||
y = w * dist;
|
||||
Y[k] = (y < B0[i]) * y;
|
||||
;
|
||||
}
|
||||
|
||||
if (!G[i])
|
||||
G[i] = i + 1;
|
||||
|
||||
std::vector<int> pos_b0;
|
||||
find(Y, pos_b0);
|
||||
|
||||
size_t m = pos_b0.size();
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
std::vector<int> pos_nz, pos_z;
|
||||
for (int j = 0; j < (int)m; j++)
|
||||
{
|
||||
pos_b0[j] = pos_b0[j] + i;
|
||||
if (G[pos_b0[j]])
|
||||
pos_nz.push_back(j);
|
||||
else
|
||||
pos_z.push_back(j);
|
||||
}
|
||||
|
||||
for (int j = 0; j < (int)pos_z.size(); j++)
|
||||
{
|
||||
pos_z[j] = pos_b0[pos_z[j]];
|
||||
G[pos_z[j]] = G[i];
|
||||
}
|
||||
|
||||
if (!pos_nz.size())
|
||||
continue;
|
||||
|
||||
std::vector<int> g;
|
||||
for (size_t j = 0; j < pos_nz.size(); j++)
|
||||
{
|
||||
pos_nz[j] = pos_b0[pos_nz[j]];
|
||||
g.push_back(G[pos_nz[j]]);
|
||||
}
|
||||
|
||||
unique(g, g);
|
||||
for (size_t k = 0; k < g.size(); k++)
|
||||
{
|
||||
int gk = g[k];
|
||||
for (size_t j = 0; j < G.size(); j++)
|
||||
if (G[j] == gk)
|
||||
G[j] = G[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!G[n - 1])
|
||||
G[n - 1] = (int)n;
|
||||
|
||||
std::vector<int> S;
|
||||
S = G;
|
||||
unique(S, S);
|
||||
for (int k = 0; k < (int)S.size(); k++)
|
||||
{
|
||||
int gk = S[k];
|
||||
for (int j = 0; j < (int)G.size(); j++)
|
||||
if (G[j] == gk)
|
||||
G[j] = k;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,74 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_GRAPH_CLUSTERS_HPP
|
||||
#define _MCC_GRAPH_CLUSTERS_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
class CB0cluster
|
||||
{
|
||||
public:
|
||||
CB0cluster();
|
||||
~CB0cluster();
|
||||
|
||||
inline void setVertex(const std::vector<Point> &V) { X = V; }
|
||||
inline void setB0(const std::vector<double> &b0) { B0 = b0; }
|
||||
inline void setWeight(const std::vector<double> &Weight) { W = Weight; }
|
||||
|
||||
void group();
|
||||
|
||||
void getGroup(std::vector<int> &g) { g = G; }
|
||||
|
||||
private:
|
||||
//entrada
|
||||
std::vector<Point> X;
|
||||
std::vector<double> B0;
|
||||
std::vector<double> W;
|
||||
|
||||
//salida
|
||||
std::vector<int> G;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void find(const std::vector<T> &A, std::vector<int> &indx)
|
||||
{
|
||||
indx.clear();
|
||||
for (int i = 0; i < (int)A.size(); i++)
|
||||
if (A[i])
|
||||
indx.push_back(i);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
|
||||
#endif //_MCC_GRAPH_CLUSTERS_HPP
|
||||
@@ -0,0 +1,46 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MCC_PRECOMP_HPP
|
||||
#define _MCC_PRECOMP_HPP
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/3d.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#endif //_MCC_PRECOMP_HPP
|
||||
@@ -0,0 +1,98 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "wiener_filter.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
CWienerFilter::CWienerFilter()
|
||||
{
|
||||
}
|
||||
|
||||
CWienerFilter::~CWienerFilter()
|
||||
{
|
||||
}
|
||||
|
||||
void CWienerFilter::
|
||||
wiener2(InputArray _src, OutputArray _dst, int szWindowX, int szWindowY)
|
||||
{
|
||||
|
||||
CV_Assert(szWindowX > 0 && szWindowY > 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
int nRows;
|
||||
int nCols;
|
||||
Scalar v = 0;
|
||||
Mat p_kernel;
|
||||
Mat srcStub;
|
||||
//Now create a temporary holding matrix
|
||||
Mat p_tmpMat1, p_tmpMat2, p_tmpMat3, p_tmpMat4;
|
||||
double noise_power;
|
||||
|
||||
nRows = szWindowY;
|
||||
nCols = szWindowX;
|
||||
|
||||
p_kernel = Mat(nRows, nCols, CV_32F, Scalar(1.0 / (double)(nRows * nCols)));
|
||||
|
||||
//Local mean of input
|
||||
filter2D(src, p_tmpMat1, -1, p_kernel, Point(nCols / 2, nRows / 2)); //localMean
|
||||
|
||||
//Local variance of input
|
||||
p_tmpMat2 = src.mul(src);
|
||||
filter2D(p_tmpMat2, p_tmpMat3, -1, p_kernel, Point(nCols / 2, nRows / 2));
|
||||
|
||||
//Subtract off local_mean^2 from local variance
|
||||
p_tmpMat4 = p_tmpMat1.mul(p_tmpMat1); //localMean^2
|
||||
p_tmpMat3 = p_tmpMat3 - p_tmpMat4;
|
||||
// Sub(p_tmpMat3, p_tmpMat4, p_tmpMat3); //filter(in^2) - localMean^2 ==> localVariance
|
||||
|
||||
//Estimate noise power
|
||||
v = mean(p_tmpMat3);
|
||||
noise_power = v.val[0];
|
||||
// result = local_mean + ( max(0, localVar - noise) ./ max(localVar, noise)) .* (in - local_mean)
|
||||
|
||||
p_tmpMat4 = src - p_tmpMat1; //in - local_mean
|
||||
|
||||
p_tmpMat2 = max(p_tmpMat3, noise_power); //max(localVar, noise)
|
||||
|
||||
add(p_tmpMat3, Scalar(-noise_power), p_tmpMat3); //localVar - noise
|
||||
p_tmpMat3 = max(p_tmpMat3, 0); // max(0, localVar - noise)
|
||||
|
||||
p_tmpMat3 = (p_tmpMat3 / p_tmpMat2); //max(0, localVar-noise) / max(localVar, noise)
|
||||
|
||||
Mat dst = p_tmpMat3.mul(p_tmpMat4);
|
||||
dst = dst + p_tmpMat1;
|
||||
|
||||
_dst.assign(dst);
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,68 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Pedro Diamel Marrero Fernández
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wiener_filter
|
||||
* @brief filter wiener for denoise
|
||||
* @author: Pedro D. Marrero Fernandez
|
||||
* @data: 17/05/2016
|
||||
*/
|
||||
|
||||
#ifndef _WIENER_FILTER_HPP
|
||||
#define _WIENER_FILTER_HPP
|
||||
|
||||
#include "precomp.hpp"
|
||||
namespace cv
|
||||
{
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
/// CWienerFilter
|
||||
/** @brief wiener class filter for denoise
|
||||
* @author: Pedro D. Marrero Fernandez
|
||||
* @data: 17/05/2016
|
||||
*/
|
||||
class CWienerFilter
|
||||
{
|
||||
public:
|
||||
CWienerFilter();
|
||||
~CWienerFilter();
|
||||
|
||||
/** cvWiener2
|
||||
* @brief A Wiener 2D Filter implementation for OpenCV
|
||||
* @author: Ray Juang / rayver{ _at_ } hkn{ / _dot_ / } berkeley(_dot_) edu
|
||||
* @date : 12.1.2006
|
||||
*/
|
||||
void wiener2(InputArray _src, OutputArray _dst, int szWindowX, int szWindowY);
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif //_WIENER_FILTER_HPP
|
||||
Reference in New Issue
Block a user