我有2600x2600灰色图片。 或者它可以被看作是无符号短的矩阵。 我想找到最暗的(或通过计算逆图像最亮的)方形具有固定大小的N.N可以被参数化(如果有多个最暗的方形,我想要所有)。
我看了detection-of-rectangular-bright-area-in-a-image-using-opencv 但它需要一个我没有的阈值,而且我搜索一个固定的大小。
有人在c ++或python中找到它吗?
答案 0 :(得分:1)
For each row of the image,
Add up the N consecutive pixels, so you get W - N + 1 pixels.
For each column of the new image,
For each consecutive sequence of N pixels, (H - N + 1)
Add them up and compare to the current best.
要添加每个连续的像素序列,您可以减去最后一个像素,然后添加下一个像素。
如果可以修改图像数组,也可以将其重新用作存储。如果没有,则内存优化将仅存储最新的列,并在第一个循环中的每个步骤中进行优化。
运行时:O( w · h )
以下是C#中的一些代码,用于演示(忽略像素格式和任何潜在的溢出):
List<Point> FindBrightestSquare(int[,] image, int N, out int squareSum)
{
int width = image.GetLength(0);
int height = image.GetLength(1);
if (width < N || height < N)
{
return false;
}
int currentSum;
for (int y = 0; y < height; y++)
{
currentSum = 0;
for (int x = 0; x < width; x++)
{
currentSum += image[x,y];
if (x => N)
{
currentSum -= image[x-N,y];
image[x-N,y] = currentSum;
}
}
}
int? bestSum = null;
List<Point> bestCandidates = new List<Point>();
for (int x = 0; x <= width-N; x++)
{
currentSum = 0;
for (int y = 0; y < height; y++)
{
currentSum += image[x,y];
if (y >= N)
{
currentSum -= image[x, y-N];
if (bestSum == null || currentSum > bestSum)
{
bestSum = currentSum;
bestCandidates.Clear();
bestCandidates.Add(new Point(x, y-N));
}
else if (currentSum == bestSum)
{
bestCandidates.Add(new Point(x, y-N));
}
}
}
}
squareSum = bestSum.Value;
return bestCandidates;
}
答案 1 :(得分:0)
您可以增加阈值,直到找到正方形,然后使用2D FSM检测正方形。
这将在O(width * height * bpp)
中产生匹配(在可能的最低阈值上进行二分搜索,假设两次幂范围):
- set threshold to its maximum value
- for every bit of the threshold
- clear the bit in the threshold
- if there is a match
- record the set of matches as a result
- else
- set the bit
- if there is no record, then the threshold is its maximum.
to detect a square:
- for every pixel:
- if the pixel is too bright, set its line-len to 0
- else if it's the first column, set its line-len to 1
- else set its line-len to the line-len of the pixel to the left, plus one
- if the pixel line-len is less than N, set its rect-len to 0
- else if it's the first row, set its rect-len to 1
- else set its rect-len to the rect-len of the pixel above, plus one
- if the rect-len is at least N, record a match.
line-len
表示足够暗的连续像素数。
rect-len
表示足够长且对齐的连续暗像素行数。
对于视频捕获,请通过线性搜索从前一帧的阈值替换二进制搜索。
显然,你不能比theta(width/N * height/N)
最佳情况更好(因为你必须排除每个可能的位置以获得更暗的方块)并且可以假设比特深度是常数,所以这个算法是渐近的对于固定N来说是最优的。对于N来说,它也可能是渐近最优的输入,因为(直觉上)你必须考虑平均情况下的几乎每个像素。