Skip to content

Added some helper function in 'mcc' #2644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: 4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/mcc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
46 changes: 38 additions & 8 deletions modules/mcc/include/opencv2/mcc/checker_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,35 @@ class CV_EXPORTS_W CChecker
CV_WRAP static Ptr<CChecker> create();

public:
// CV_PROP_RW TYPECHART target; ///< type of checkercolor
// CV_PROP_RW std::vector<cv::Point2f> 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<Point2f> _box) = 0;
CV_WRAP virtual void setPerPatchCosts(std::vector<Point2f> _patchCosts) = 0;

// Detected directly by the detector or found using geometry, useful to determine if a patch is occluded
CV_WRAP virtual void setActualDetectedContours(std::vector<std::vector<Point2f>> 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<Point2f> _patchCenters) = 0;
CV_WRAP virtual void setPatchBoundingBoxes(std::vector<Point2f> _patchBoundingBoxes) = 0;

CV_WRAP virtual TYPECHART getTarget() = 0;
CV_WRAP virtual std::vector<Point2f> getBox() = 0;
CV_WRAP virtual std::vector<Point2f> getPerPatchCosts() = 0;
CV_WRAP virtual std::vector<std::vector<Point2f>> 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<Point2f> getPatchCenters() = 0;
CV_WRAP virtual std::vector<Point2f> getPatchBoundingBoxes(float sideRatio=0.5) =0;


CV_WRAP virtual bool calculate() = 0; ///< Return false if some error occured, true otherwise
};

/** \brief checker draw
Expand All @@ -115,10 +124,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
Expand All @@ -132,6 +147,21 @@ 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
* \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<CChecker> pChecker,
cv::Scalar color = CV_RGB(0, 255, 0), int thickness = 2, float sideRatio = 0.5,
bool drawActualDetection = false);
//! @} mcc
} // namespace mcc
} // namespace cv
Expand Down
168 changes: 168 additions & 0 deletions modules/mcc/samples/basic_color_calibration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include <opencv2/core.hpp>

#include <opencv2/highgui.hpp>
#include <opencv2/mcc.hpp>
#include <iostream>

using namespace std;
using namespace cv;
using namespace mcc;

#include <opencv2/core.hpp>

#include <opencv2/highgui.hpp>
#include <opencv2/mcc.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>

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<int>("t");

CV_Assert(0 <= t && t <= 2);
TYPECHART chartType = TYPECHART(t);

string model_path = parser.get<string>("m");
string pbtxt_path = parser.get<string>("pb");

int camId = parser.get<int>("ci");
int nc = parser.get<int>("nc");

String video;

if (parser.has("v"))
video = parser.get<String>("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<CCheckerDetector> 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<Ptr<mcc::CChecker>> checkers = detector->getListColorChecker();
for (Ptr<mcc::CChecker> checker : checkers)
{
// current checker
Ptr<CCheckerDraw> 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;
}
4 changes: 4 additions & 0 deletions modules/mcc/samples/chart_detection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ int main(int argc, char *argv[])
if (!parser.check())
{
parser.printErrors();
parser.printMessage();
return 0;
}

Expand All @@ -60,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())
{

Expand Down
5 changes: 5 additions & 0 deletions modules/mcc/samples/chart_detection_with_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ int main(int argc, char *argv[])
if (!parser.check())
{
parser.printErrors();
parser.printMessage();
return 0;
}

Expand Down Expand Up @@ -95,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;
Expand Down Expand Up @@ -126,6 +130,7 @@ int main(int argc, char *argv[])
char key = (char)waitKey(waitTime);
if (key == 27)
break;

}

return 0;
Expand Down
Loading