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

EmguCV调用PCACompute时如何将VectorOfPoint轮廓转换为可输入的Mat

EmguCV 轮廓PCA分析实现修正方案

原有代码核心问题

  • PCACompute要求输入样本矩阵为每行/每列对应一个样本点的浮点类型(Cv32F/Cv64F)矩阵,你初始化的mean_mat、eigen_vectors用的是8U灰度图格式,不符合参数要求
  • 直接调用Mat.SetTo()传入Point数组无法正确填充矩阵数据,需要手动构造符合PCA要求的样本矩阵结构
  • 直接传入VectorOfVectorOfPoint类型的轮廓集合到PCACompute是无效输入,需提取单个轮廓的点集构造样本矩阵

正确实现逻辑

1. 构造PCA输入样本矩阵

提取单个轮廓的点集后,构造行数等于轮廓点数量、列数为2(对应x、y坐标)的32位浮点矩阵,逐点填充坐标值:

Point[] targetContour = contours.ToArrayOfArray()[0];
Mat sampleMat = new Mat(targetContour.Length, 2, DepthType.Cv32F, 1);
var matIndexer = sampleMat.GetGenericIndexer<float>();
for (int i = 0; i < targetContour.Length; i++)
{
    matIndexer[i, 0] = targetContour[i].X;
    matIndexer[i, 1] = targetContour[i].Y;
}

2. PCA计算参数修正

均值矩阵、特征向量矩阵无需提前指定大小,PCACompute会自动计算后填充,可通过最后一个参数指定保留的主成分数量:

Mat meanMat = new Mat();
Mat eigenVectors = new Mat();
// 保留2个主成分
CvInvoke.PCACompute(sampleMat, meanMat, eigenVectors, 2);

3. 轮廓朝向计算(可选)

如果需要获取轮廓的主方向,读取第一个主成分的分量计算角度即可:

var vecIndexer = eigenVectors.GetGenericIndexer<float>();
float vecX = vecIndexer[0, 0];
float vecY = vecIndexer[0, 1];
// 弧度转角度,统一为0-360范围
double angle = Math.Atan2(vecY, vecX) * 180 / Math.PI;
angle = angle < 0 ? angle + 360 : angle;

完整修正代码

public static double GetContourOrientation(Image<Gray, byte> inputImage)
{
    Image<Gray, Byte> cannyGray = inputImage.Canny(85, 255);
    VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
    CvInvoke.FindContours(cannyGray, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);

    // 无检测到轮廓直接返回
    if (contours.Size == 0) 
    {
        cannyGray.Dispose();
        contours.Dispose();
        return 0;
    }

    Point[] targetContour = contours.ToArrayOfArray()[0];
    // 构造PCA输入样本矩阵
    Mat sampleMat = new Mat(targetContour.Length, 2, DepthType.Cv32F, 1);
    var matIndexer = sampleMat.GetGenericIndexer<float>();
    for (int i = 0; i < targetContour.Length; i++)
    {
        matIndexer[i, 0] = targetContour[i].X;
        matIndexer[i, 1] = targetContour[i].Y;
    }

    // PCA计算
    Mat meanMat = new Mat();
    Mat eigenVectors = new Mat();
    CvInvoke.PCACompute(sampleMat, meanMat, eigenVectors, 2);

    // 计算朝向角度
    var vecIndexer = eigenVectors.GetGenericIndexer<float>();
    float vecX = vecIndexer[0, 0];
    float vecY = vecIndexer[0, 1];
    double angle = Math.Atan2(vecY, vecX) * 180 / Math.PI;
    angle = angle < 0 ? angle + 360 : angle;

    // 释放非托管资源
    cannyGray.Dispose();
    contours.Dispose();
    sampleMat.Dispose();
    meanMat.Dispose();
    eigenVectors.Dispose();

    return angle;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:36:04