[英]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_u
和M_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_l
和mu_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_u
和M_l
过程, M_u
我想高效地导出协方差。 Any ideas? 有任何想法吗?
Thank you. 谢谢。
PS: m~1280
and n~960
. PS: m~1280
和n~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 ¤tPixel = 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.