You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用cv::aruco::estimatePoseCharucoBoard触发channels断言失败问题求助

问题分析与解决方案

核心问题定位

断言失败channels() == CV_MAT_CN(dtype)本质是矩阵通道数与数据类型不匹配,但你已确认灰度图(CV_8UC1)符合要求,问题不在输入图像,而是两处关键错误触发了看似无关的内存断言:

  1. 内参矩阵赋值完全颠倒,导致相机参数错误
  2. estimatePoseCharucoBoard返回单元素姿态数组,你却用多元素的标记ID数组遍历,引发内存越界

修复步骤

1. 修正内参矩阵赋值

iOS的matrix_float3x3是列优先存储,原代码错误地将列向量按行赋值,正确逻辑:

cv::Mat intrinMat(3,3,CV_64F);
// 对应内参矩阵:[fx, 0, cx; 0, fy, cy; 0, 0, 1]
intrinMat.at<Float64>(0,0) = intrinsics.columns[0][0]; // fx
intrinMat.at<Float64>(0,1) = intrinsics.columns[1][0]; // 0
intrinMat.at<Float64>(0,2) = intrinsics.columns[2][0]; // cx
intrinMat.at<Float64>(1,0) = intrinsics.columns[0][1]; // 0
intrinMat.at<Float64>(1,1) = intrinsics.columns[1][1]; // fy
intrinMat.at<Float64>(1,2) = intrinsics.columns[2][1]; // cy
intrinMat.at<Float64>(2,0) = intrinsics.columns[0][2]; // 0
intrinMat.at<Float64>(2,1) = intrinsics.columns[1][2]; // 0
intrinMat.at<Float64>(2,2) = intrinsics.columns[2][2]; // 1

2. 修正姿态遍历逻辑

estimatePoseCharucoBoard返回整个Charuco板的单个姿态,而非每个标记的姿态,需区分两种场景处理:

if(charucoIds.size() > 0)
{
    cv::aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, charucoBoard, intrinMat, distCoeffs, rvecs, tvecs);
    // Charuco板仅一个姿态,用特殊ID标记
    if(!rvecs.empty()){
        cv::Rodrigues(rvecs[0], rotMat);
        cv::Mat extrinsics = rotateRodriques(rotMat, tvecs[0]);
        SCNMatrix4 scnMatrix = [ArucoCV transformToSceneKitMatrix:extrinsics];
        SKWorldTransform *transform = [SKWorldTransform new];
        transform.arucoId = -1; // 标记为Charuco板
        transform.transform = scnMatrix;
        [arrayMatrix addObject:transform];
    }
}
else
{
    cv::aruco::estimatePoseSingleMarkers(corners, markerSize, intrinMat, distCoeffs, rvecs, tvecs);
    // 单个标记姿态遍历,此处用ids[i]才正确
    for (int i = 0; i < rvecs.size(); i++) {
        cv::Rodrigues(rvecs[i], rotMat);
        cv::Mat extrinsics = rotateRodriques(rotMat, tvecs[i]);
        SCNMatrix4 scnMatrix = [ArucoCV transformToSceneKitMatrix:extrinsics];
        SKWorldTransform *transform = [SKWorldTransform new];
        transform.arucoId = ids[i];
        transform.transform = scnMatrix;
        [arrayMatrix addObject:transform];
    }
}

3. 调整畸变系数维度

若未专门标定8维畸变,改用OpenCV默认的5维参数:

cv::Mat distCoeffs = cv::Mat::zeros(5, 1, CV_64F);

4. 额外检查:确保输入为有效灰度图

若CVPixelBuffer不是kCVPixelFormatType_OneComponent8格式,需先转换为灰度图:

// 替换原greymat创建代码
void *baseaddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
CGFloat width = CVPixelBufferGetWidth(pixelBuffer);
CGFloat height = CVPixelBufferGetHeight(pixelBuffer);
cv::Mat inputMat(height, width, CV_8UC4, baseaddress);
cv::Mat greymat;
cv::cvtColor(inputMat, greymat, cv::COLOR_BGRA2GRAY);

验证逻辑

修复后,检测到Charuco角点时返回单个板姿态,未检测到则返回单个标记姿态,避免数组越界引发的内存错误,从而解决断言失败问题。

内容的提问来源于stack exchange,提问作者geek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:15:36