简体   繁体   English

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

[英]C++ calculate 2 3x3 Covariance matrices for each region in image

I have an image img in c++ of size mxn of type CV_8UC3 in OpenCV. 我在C ++中的OpenCV中类型为CV_8UC3的大小为mxn的图像img I have another vector b of size 1xn splitting img "horizontally" into two parts: 我还有另一个大小为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} , lower_part = {(row,col)|1<=col<=n, b(1,col)<row<=m}

where 1<=b(1,col)<=m (1<=col<=n). 其中1 <= b(1,col)<= m(1 <= col <= n)。

For these two parts of the image I'd like to have the covariance matrices M_u and M_l sort of "per" channel. 对于图像的这两部分,我希望具有“每个”通道的协方差矩阵M_uM_l This means the resulting matrices should have size 3x3 and should be derived like: 这意味着所得矩阵的大小应为3x3,并应按以下方式得出:

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

where N_u is the number of elements in the upper part, mu_u a 3x1 vector describing the average RGB values in the upper part and img(row,col) is a 3x1 vector with the RGB values of img at position (row,col) . 其中N_u是上部的元素数,mu_u是描述上部平均RGB值的3x1向量, img(row,col)是3x1向量,其img的RGB值在(row,col)位置。 M_l is calculated equivalently with N_l and mu_l considering the lower_part . M_l与等效计算N_lmu_l考虑lower_part

Furthermore, I also (sometimes) have to calculate the covariance for an CV_8UC1 image. 此外,我(有时)还必须计算CV_8UC1图像的协方差。 Of course then the matrix is just a scalar. 当然,矩阵只是一个标量。

Is there a solution primarily for the CV_8UC3 type and if yes is there a solution which also works for the CV_8UC1 type image? 是否有主要针对CV_8UC3类型的解决方案,如果是,是否存在也适用于CV_8UC1类型图像的解决方案?

My current solution is to iterate over each pixel and calculate it by getting the values with img.at<Vec3b>(row,col) or img.at<unsigned char>(row,col) respectively (first for the mean, then for the covariance, thus two loops over all pixels), but what I've heard and now see is that this function is quite inefficient/slow. 我当前的解决方案是遍历每个像素,并分别通过分别使用img.at<Vec3b>(row,col)img.at<unsigned char>(row,col)获得值进行计算(首先是平均值,然后是协方差,因此在所有像素上有两个循环),但是我已经听到并且现在看到的是该函数效率很低/很慢。 As I've to do this process of calculating M_u and M_l within a loop I'd like to derive the covariances efficiently. 由于必须执行在循环内计算M_uM_l过程, M_u我想高效地导出协方差。 Any ideas? 有任何想法吗?

Thank you. 谢谢。

PS: m~1280 and n~960 . PS: m~1280n~960

Calculation of covariance within a single loop of iteration of all pixels is possible. 可以在所有像素的单个迭代循环内计算协方差。

I have the following code that iterates through the entire set of pixels of an image,just one time and calculate the co-variance matrix. 我有以下代码遍历图像的整个像素集,仅一次并计算协方差矩阵。 This can be very well extended to your case of split images. 这可以很好地扩展到您拆分图像的情况。

   {
    //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;

}

In the case of the calculating the covariance for full image (ie: not split image), you could check whether the covariance is correct by using opencv's 'calcCovarMatrix' as well. 在计算完整图像(即非分割图像)的协方差的情况下,您也可以使用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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM