[图像]二值化检测角点

Abstract: 做棋盘格的检测——最好是先二值化,然后findchessboard。

简短记一下:

二值化:

cv::Mat binary;
blockSize = 61;
Constvalue = 0;
cv::adaptiveThreshold(SingleChartImage_roi_gray, binary, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, blockSize, Constvalue);
cv::imwrite("../debug/preprocessed_binary.jpg", binary);

cv::adaptiveThreshold是自适应二值化函数,binary是输出结果。最重要的两个超参数是blockSize和Constvalue,constvalue决定了图片的亮暗,blocksize决定了黑色方块的大小。一般这么设置61是ok的,还可以自适应调整,懒得写。

vector<int> flag_combinations = {// 单独尝试
                                    CALIB_CB_ADAPTIVE_THRESH,
                                    CALIB_CB_NORMALIZE_IMAGE,
                                    CALIB_CB_FAST_CHECK,

                                    // 组合尝试
                                    CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE,
                                    CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_FAST_CHECK,
                                    CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_FILTER_QUADS,

                                    // 更多组合
                                    CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FILTER_QUADS,
                                    CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_CLUSTERING,

                                    // 不使用任何标志(默认)
                                    0};

for (int i = 0; i < flag_combinations.size(); i++) {
    vector<cv::Point2f> test_corners;
    bool test_found = findChessboardCorners(binary, cv::Size(tag.width, tag.height), test_corners, flag_combinations[i]);

    std::cout << "标志组合 " << i << " (值=" << flag_combinations[i] << "): " << (test_found ? "成功" : "失败") << ", 检测到角点: " << test_corners.size() << std::endl;

    if (test_found) {
        corners = test_corners;
        found = true;

        // 可视化成功的检测
        cv::Mat display = binary.clone();
        if (display.channels() == 1) {
            cv::cvtColor(display, display, cv::COLOR_GRAY2BGR);
        }
        cv::drawChessboardCorners(display, cv::Size(tag.width, tag.height), test_corners, test_found);
        cv::imwrite("../debug/success_flag_" + std::to_string(i) + ".jpg", display);

        std::cout << "使用标志组合 " << i << " 检测成功!" << std::endl;
        break;
    }
}

结果所示: result

这个是进行标志的检测,具体标志的意思,可以查一下,这是debug代码,一般来说找到合适的标志后,就直接改成那个标志来调用就可以了。


Last modified on 2026-01-13