使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿

前景概要

很多机器视觉定位与识别场景,如无人车、无人机,都会用Aruco码或特定的标志物来实现,Aruco码的优点在于,xxxx(自行搜索)。

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第1张图片

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第2张图片

 对于像在低成本轻量级的无人机这种嵌入式系统上,搭载深度学习的识别算法目前还有困难

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第3张图片

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第4张图片

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第5张图片

所以大家现在采用较多的,就是识别特定的标志物。之前看小鹏汽车的宣传片,他们也是在用黑白同心圆环的目标板。

实现内容

0、打开摄像头或某张图片

1、先检测圆环(因视角变换可能是椭圆环);

2、裁剪保留圆环区域

3、检测圆环中的Aruco码(单个或菱形或棋盘)

4、计算目标的位姿


大致效果

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第6张图片

使用C++ OpenCV实现椭圆区域检测与Aruco码的生成与检测并估计位姿_第7张图片

代码预览

完整代码请看github(测试性代码,写的很粗糙,仅供参考)

Github: https://github.com/1061700625/OpenCV_Aruco

Mat testDetect(Mat &markerImage, bool diamond = true, bool aamed=false, bool show=false) {
    /*************************************检测椭圆*****************************************************/
    // FeaturePoint(img ,img2);
    // EDCircle(markerImage);
    float t1, t2, tdelt;
    vector results;
    Mat fullSplitImage;

    if(aamed) {
        t1 = cv::getTickCount();
        AAMED_Fled(markerImage, fullSplitImage, results);
        t2 = cv::getTickCount();
        tdelt = 1000.0*(t2-t1) / cv::getTickFrequency();
        std::cout << "AAMED耗时(ms):" << tdelt << std::endl;
    }else {
        results.emplace_back(markerImage);
        fullSplitImage = markerImage.clone();
    }

    /************************************************************************************************/

    // 对每个椭圆区域进行检测
    for (auto& cropSplitImage: results) {
        // 检测Aruco
        vector> diamondCorners;
        vector diamondIds;
        vector> markerCorners;
        vector markerIds;
        vector> rejectedCandidates;
        t1 = cv::getTickCount();
        // cv::copyMakeBorder(cropSplitImage, cropSplitImage, 5, 5, 5, 5, cv::BORDER_CONSTANT, Scalar(255,0,0));
        detectAruco(cropSplitImage, markerCorners, rejectedCandidates, markerIds);
        if (markerCorners.empty()) {
            cout<<"无可用Marker"< rvecs, tvecs;
        cv::Vec3d rvec, tvec;
        t1 = cv::getTickCount();
        if(diamond) {
            if (diamondIds.empty()) {
                cout<<"无可用diamondIds"<draw( cv::Size(200, 200),  // 整个board的大小
                 boardImage,                         // 返回的图像
                 10,                            // 整个board的边距
                 1 );                           // 每个码内的边距
    imwrite("../boardImage.png", boardImage);
    cv::aruco::drawCharucoDiamond(dictionary, cv::Vec4i(0,1,2,3), 200, 150, boardImage);
    imwrite("../diamondImage.png", boardImage);
    //vector markerImages = generateAruco(5);
    //Mat markerImage = markerImages[0];
    cout<<">> 预处理完成!"<= 0)
            break;
    }

    return 0;
}

其他内容

  • 在线aruco标记生成器:https://chev.me/arucogen/
  • OpenCV识别Aruco markers库:https://docs.opencv.org/4.5.4/d5/dae/tutorial_aruco_detection.html

你可能感兴趣的:(学习之旅,opencv,c++,人工智能)