Austin Schuh | e3e3254 | 2024-01-01 12:24:11 -0800 | [diff] [blame] | 1 | #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 Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame^] | 11 | namespace y2023::vision { |
Austin Schuh | e3e3254 | 2024-01-01 12:24:11 -0800 | [diff] [blame] | 12 | namespace { |
| 13 | |
| 14 | // Adapted from the opencv example code for color calibration. |
| 15 | void 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 Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame^] | 75 | } // namespace y2023::vision |
Austin Schuh | e3e3254 | 2024-01-01 12:24:11 -0800 | [diff] [blame] | 76 | |
| 77 | int 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 | } |