我有一个图像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_u
和M_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_l
与N_l
和mu_l
的计算是等价的。
此外,我还(有时)必须计算CV_8UC1
图像的协方差。当然,这个矩阵只是一个标量。
是否有主要针对CV_8UC3
类型的解决方案,如果是,是否有适用于CV_8UC1
类型图像的解决方案?
我目前的解决方案是迭代每个像素,并通过分别获得img.at<Vec3b>(row,col)
或img.at<unsigned char>(row,col)
的值来计算它(首先是平均值,然后是协方差,因此两个循环遍历所有像素),但我所听到的和现在看到的是这个函数相当低效/缓慢。因为我必须在一个循环中计算M_u
和M_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 ¤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;
}
在计算完整图像的协方差的情况下(即:不分割图像),你可以检查协方差是否正确使用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;