c++计算图像中每个区域的2 3x3协方差矩阵



我有一个图像img在c++的大小mxn类型的CV_8UC3在OpenCV。我有另一个大小为1xn的矢量b,将img"水平"分成两部分:

upper_part = {(row,col)|1<=col<=n, 1<=row<=b(1,col)}

lower_part = {(row,col)|1<=col<=n, b(1,col)<row<=m}

1 & lt; = b (col) & lt; = m (1 & lt; = col<= n)。

对于图像的这两个部分,我希望有"每个"通道的协方差矩阵M_uM_l。这意味着结果矩阵的大小应该是3x3,并且应该像这样派生:

M_u = 1/(N_u-1) * sum_{(row,col)in upper_part} (img(row,col)-mu_u)*(img(row,col)-mu_u)^T

,其中N_u为上半部分的元素个数,mu_u为描述上半部分RGB平均值的3x1向量,img(row,col)为位置(row,col)img的RGB值的3x1向量。考虑到lower_part, M_lN_lmu_l的计算是等价的。

此外,我还(有时)必须计算CV_8UC1图像的协方差。当然,这个矩阵只是一个标量。

是否有主要针对CV_8UC3类型的解决方案,如果是,是否有适用于CV_8UC1类型图像的解决方案?

我目前的解决方案是迭代每个像素,并通过分别获得img.at<Vec3b>(row,col)img.at<unsigned char>(row,col)的值来计算它(首先是平均值,然后是协方差,因此两个循环遍历所有像素),但我所听到的和现在看到的是这个函数相当低效/缓慢。因为我必须在一个循环中计算M_uM_l,所以我想有效地推导协方差。什么好主意吗?

谢谢。

PS: m~1280 and n~960 .

在所有像素的单一迭代循环中计算协方差是可能的。

我有以下代码,迭代通过图像的整个像素集,只是一次,并计算协方差矩阵。这可以很好地扩展到分割图像的情况。

   {
    //img is a CV_8UC3 image in RGB format
    Vec3f sumOfPixels=Vec3f(0,0,0);
    float sumRR=0, sumRG=0, sumRB=0, sumGG=0, sumGB=0, sumBB=0;
    Mat covarianceMat = Mat::zeros(3, 3, CV_32FC1);
    for(int r= 0; r < img.rows; ++r) {
        for(int c=0; c < img.cols; ++c) {
            const Vec3b &currentPixel = img.at<Vec3b>(Point(c,r));
            sumOfPixels += Vec3b(currentPixel[0], currentPixel[1], currentPixel[2]);
            sumRR += currentPixel[0] * currentPixel[0];
            sumRG += currentPixel[0] * currentPixel[1];
            sumRB += currentPixel[0] * currentPixel[2];
            sumGG += currentPixel[1] * currentPixel[1];
            sumGB += currentPixel[1] * currentPixel[2];
            sumBB += currentPixel[2] * currentPixel[2];
        }
    }
    int nPixels = img.rows * img.cols;
    assert(nPixels > 0);
    Vec3f avgOfPixels = sumOfPixels / nPixels;
    covarianceMat.at<float>(0,0) = sumRR/nPixels - avgOfPixels[0]*avgOfPixels[0];
    covarianceMat.at<float>(0,1) = sumRG/nPixels - avgOfPixels[0]*avgOfPixels[1];
    covarianceMat.at<float>(0,2) = sumRB/nPixels - avgOfPixels[0]*avgOfPixels[2];
    covarianceMat.at<float>(1,1) = sumGG/nPixels - avgOfPixels[1]*avgOfPixels[1];
    covarianceMat.at<float>(1,2) = sumGB/nPixels - avgOfPixels[1]*avgOfPixels[2];
    covarianceMat.at<float>(2,2) = sumBB/nPixels - avgOfPixels[2]*avgOfPixels[2];
    covarianceMat.at<float>(1,0) =  covarianceMat.at<float>(0,1);
    covarianceMat.at<float>(2,0) =  covarianceMat.at<float>(0,2);
    covarianceMat.at<float>(2,1) =  covarianceMat.at<float>(1,2);
    cout << "covariance of image: " << covarianceMat << endl;
}

在计算完整图像的协方差的情况下(即:不分割图像),你可以检查协方差是否正确使用opencv的'calcCovarMatrix'为好。

    Mat img_copy = img;
    assert(img.type() == img_copy.type());
    img_copy = img.reshape(1, img.rows *img.cols);
    cv::Mat covar, mean;
    cv::calcCovarMatrix(img_copy, covar, mean, CV_COVAR_NORMAL | CV_COVAR_ROWS );
    covar /= (img.rows * img.cols);
    std::cout << "covariance through opencv: " << covar << std::endl;

相关内容

  • 没有找到相关文章

最新更新