blob: d32cc2f33825f6269d7bc1f2730b6875b5b584f2 [file] [log] [blame]
Austin Schuhe3e32542024-01-01 12:24:11 -08001#include "glog/logging.h"
2#include <opencv2/calib3d.hpp>
3#include <opencv2/highgui/highgui.hpp>
4#include <opencv2/imgproc.hpp>
5#include <opencv2/mcc.hpp>
6#include <opencv2/mcc/ccm.hpp>
7
8#include "aos/init.h"
9#include "aos/time/time.h"
10
Stephan Pleinesf63bde82024-01-13 15:59:33 -080011namespace y2023::vision {
Austin Schuhe3e32542024-01-01 12:24:11 -080012namespace {
13
14// Adapted from the opencv example code for color calibration.
15void CCMMain(std::string filepath) {
16 cv::Mat image = cv::imread(filepath, cv::IMREAD_COLOR);
17
18 CHECK(image.data) << "Failed to read " << filepath;
19
20 cv::Mat imageCopy = image.clone();
21 cv::Ptr<cv::mcc::CCheckerDetector> detector =
22 cv::mcc::CCheckerDetector::create();
23
24 // Marker type to detect
25 CHECK(detector->process(image, cv::mcc::MCC24, /*max number of charts*/ 1))
26 << ": Failed to detect chart.";
27
28 std::vector<cv::Ptr<cv::mcc::CChecker>> checkers =
29 detector->getListColorChecker();
30 for (cv::Ptr<cv::mcc::CChecker> checker : checkers) {
31 cv::Ptr<cv::mcc::CCheckerDraw> cdraw =
32 cv::mcc::CCheckerDraw::create(checker);
33 cdraw->draw(image);
34 cv::Mat charts_rgb = checker->getChartsRGB();
35 cv::Mat src = charts_rgb.col(1).clone().reshape(3, charts_rgb.rows / 3);
36 src /= 255.0;
37
38 // compte color correction matrix
39 cv::ccm::ColorCorrectionModel model1(src, cv::ccm::COLORCHECKER_Macbeth);
40 model1.run();
41 cv::Mat ccm = model1.getCCM();
42 LOG(INFO) << "ccm " << ccm;
43 for (int i = 0; i < 9; ++i) {
44 LOG(INFO) << "mat[" << i << "] = " << ccm.at<double>(i) << ";";
45 }
46 double loss = model1.getLoss();
47 LOG(INFO) << "loss " << loss;
48
49 cv::Mat img_;
50 cv::cvtColor(image, img_, cv::COLOR_BGR2RGB);
51 img_.convertTo(img_, CV_64F);
52 const int inp_size = 255;
53 const int out_size = 255;
54 img_ = img_ / inp_size;
55 cv::Mat calibrated_image = model1.infer(img_);
56 cv::Mat out_ = calibrated_image * out_size;
57
58 // Save the calibrated image to {FILE_NAME}.calibrated.{FILE_EXT}
59 out_.convertTo(out_, CV_8UC3);
60 cv::Mat img_out = min(max(out_, 0), out_size);
61 cv::Mat out_img;
62 cv::cvtColor(img_out, out_img, cv::COLOR_RGB2BGR);
63
64 std::string filename = filepath.substr(filepath.find_last_of('/') + 1);
65 size_t dot_index = filename.find_last_of('.');
66 std::string base_name = filename.substr(0, dot_index);
67 std::string ext =
68 filename.substr(dot_index + 1, filename.length() - dot_index);
69 std::string calibrated_file_path = base_name + ".calibrated." + ext;
70 cv::imwrite(calibrated_file_path, out_img);
71 }
72}
73
74} // namespace
Stephan Pleinesf63bde82024-01-13 15:59:33 -080075} // namespace y2023::vision
Austin Schuhe3e32542024-01-01 12:24:11 -080076
77int main(int argc, char **argv) {
78 aos::InitGoogle(&argc, &argv);
79 if (argc != 2) {
80 LOG(FATAL) << "Expected filename as an argument.";
81 }
82 y2023::vision::CCMMain(argv[1]);
83}