blob: ecb9552638512acf26f6810e71361dc9e6ec91cf [file] [log] [blame]
Austin Schuh99f7c6a2024-06-25 22:07:44 -07001#include "absl/log/check.h"
2#include "absl/log/log.h"
Austin Schuhe3e32542024-01-01 12:24:11 -08003#include <opencv2/calib3d.hpp>
4#include <opencv2/highgui/highgui.hpp>
5#include <opencv2/imgproc.hpp>
6#include <opencv2/mcc.hpp>
7#include <opencv2/mcc/ccm.hpp>
8
9#include "aos/init.h"
10#include "aos/time/time.h"
11
Stephan Pleinesf63bde82024-01-13 15:59:33 -080012namespace y2023::vision {
Austin Schuhe3e32542024-01-01 12:24:11 -080013namespace {
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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080076} // namespace y2023::vision
Austin Schuhe3e32542024-01-01 12:24:11 -080077
78int main(int argc, char **argv) {
79 aos::InitGoogle(&argc, &argv);
80 if (argc != 2) {
81 LOG(FATAL) << "Expected filename as an argument.";
82 }
83 y2023::vision::CCMMain(argv[1]);
84}