有一种常数时间的方法可以找到图像矩形部分的平均颜色,但需要进行线性预处理。在您的情况下,这应该没问题。此方法还可用于查找3D数组中的矩形棱柱体的平均值或任何更高维度的类似问题。我将使用灰度示例,但只需重复该过程即可轻松扩展到3个或更多通道。
假设我们有一个二维数字数组,我们称之为“img
”。
第一步是生成一个相同维度的新数组,在该数组中,每个元素都包含原始图像中位于该元素和图像左上角之间的矩形内所有值的总和。
您可以使用以下方法在线性时间内构造这样的图像:
int width = 1920;
int height = 1080;
//source data
int[] img = GrayScaleScreenCapture();
int[] helperImg = int[width * height]
for(int y = 0; y < height; ++y)
{
for(int x = 0; x < width; ++x)
{
int total = img[y * width + x];
if(x > 0)
{
//Add value from the pixel to the left in helperImg
total += helperImg[y * width + (x - 1)];
}
if(y > 0)
{
//Add value from the pixel above in helperImg
total += helperImg[(y - 1) * width + x];
}
if(x > 0 && y > 0)
{
//Subtract value from the pixel above and to the left in helperImg
total -= helperImg[(y - 1) * width + (x - 1)];
}
helperImg[y * width + x] = total;
}
}
现在我们可以使用
helperImg
在常数时间内找到
img
中给定矩形内所有值的总和:
//Some Rectangle with corners (x0, y0), (x1, y0) , (x0, y1), (x1, y1)
int x0 = 50;
int x1 = 150;
int y0 = 25;
int y1 = 200;
int totalOfRect = helperImg[y1 * width + x1];
if(x0 > 0)
{
totalOfRect -= helperImg[y1 * width + (x0 - 1)];
}
if(y0 > 0)
{
totalOfRect -= helperImg[(y0 - 1) * width + x1];
}
if(x0 > 0 && y0 > 0)
{
totalOfRect += helperImg[(y0 - 1) * width + (x0 - 1)];
}
最后,我们只需将totalOfRect
除以矩形的面积即可得到平均值:
int rWidth = x1 - x0 + 1;
int rheight = y1 - y0 + 1;
int meanOfRect = totalOfRect / (rWidth * rHeight);