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