我对以下for循环的索引问题很少。只是我用roi扫描图像但我无法扫描整个图像。我在最后一行和列中留下了一些非扫描区域。有什么建议吗? 对不起简单的问题。
`
// Sliding Window for scaning the image
for (int rowIndex = 0; rowIndex <= lBPIIImage2.rows - roih; rowIndex = getNextIndex(rowIndex, lBPIIImage2.rows, roih, steprow))
{
for (int colindex = 0; colindex <=lBPIIImage2.cols - roiw; colindex = getNextIndex(colindex, lBPIIImage2.cols, roiw, stepcol))
{
searchRect = cvRect(colindex, rowIndex, roiw, roih);
frameSearchRect = lBPIIImage2(searchRect);
LoopDummy = frameSearchRect.clone();
rectangle(frame, searchRect, CV_RGB(255, 0, 0), 1, 8, 0);
//normalize(LoopDummy, LoopDummy, 0, 255, NORM_MINMAX, CV_8UC1);
//imshow("Track", LoopDummy);
//waitKey(30);
images.push_back(LoopDummy);
Coordinate.push_back(make_pair(rowIndex, colindex));
}
}
答案 0 :(得分:0)
而不是这个
for (int rowindex = 0; rowindex <= frameWidth - roiw; rowindex += StepRow)
尝试这样的事情
for (int rowIndex = 0; rowIndex < frameWidth - roiw;
rowIndex = getNextIndex(rowIndex, frameWidth, roiw, StepRow))
其中函数getNextIndex
是这样的:
int getNextIndex(int currentIndex, int frameSize, int roi, int step)
{
int temp = min(currentIndex + step, frameSize - roi - 1);
return currentIndex != temp ? temp : frameSize;
}
请注意,我在循环的条件部分将<=
替换为<
。改变那一点对我来说是有道理的。在我的评论中,索引值应为0,5,6,而不是0,5,7。如果确实应该<=
,那么只需删除上面的- 1
部分。
答案 1 :(得分:0)
Dialecticus有problem covered,但我想稍微扩展一下。正如您所注意到的那样,问题会影响行和列,但我只会谈论宽度,因为高度处理是类似的。
循环迭代的数组或范围的某些部分,尤其是最后的部分,是循环的条件和/或增量不覆盖整个数组/范围并需要调整的典型症状。在您的情况下,要扫描整个图像宽度,您需要frameWidth - roiw
确切的StepRow
个数,即(frameWidth - roiw) % StepRow == 0
。我强烈怀疑你的情况并非如此。
例如,如果您的图片宽度为14像素,并且您感兴趣的区域宽度为8,那么您的步骤would be 4 pixels(我假设您的意思是roiw * 0.5
),则会发生这种情况:
迭代#3将无法通过rowindex <= frameWidth - roiw
测试并退出循环而不扫描最后2个像素。
我看到三个选项,每个选项都有其缺点:
免责声明:以下所有代码均未经过测试,可能包含拼写错误和逻辑错误。请相应地进行测试和调整。
更改最后一个区域的偏移量,使其适合图像的末尾。在这种情况下,最后rowindex
增量不会是StepRow
,而是最后一个扫描区域末尾与图像末尾之间的像素数。缺点是最后两个区域可能比它们之前的区域重叠 - 在我们的例子中,区域1将覆盖像素0:7,区域2 - 4:11和区域3 - 6:13。
为此,您可以修改循环增量以检查这是否是最后一次迭代(请考虑如何将其写得更漂亮,我只是使用三元运算符来使更改更小):
for (int rowindex = 0;
/* Note that a region of (roiw) pixels ending at (frameWidth - 1) should start
at (frameWidth - roiw), so the <= operator should be correct. To verify that,
check the single-region case where rowindex == 0 and frameWidth == roiw */
rowindex <= frameWidth - roiw;
rowindex += ((rowindex + roiw + StepRow <= frameWidth) ?
StepRow :
(frameWidth - (rowindex + roiw))))
将最后一个区域的大小固定到图像的末尾。缺点是你的最后一个区域比之前的区域小 - 在我们的例子中,区域1和2的大小为8,而区域3的大小为6像素。
为此,您可以在构建cvRect
时进行检查,看是否需要更小。您还应该以某种方式更改循环条件,以便在这种情况下实际输入它:
/* (StepRow - 1) should make sure that enter the loop is entered when the
last unscanned region has a width between 1 and stepRow, inclusive */
for (int rowindex = 0; rowindex <= frameWidth - roiw + (StepRow - 1); rowindex += StepRow)
/* ... column loop ... */
{
if (rowindex > frameWidth - roiw)
{
roiw = frameWidth - rowindex;
}
searchRect = cvRect(rowindex, colindex, roiw, roih)
使用变化步骤,使您的区域宽度相等,并尽可能相等地重叠。在我们的例子中,三个区域将重叠相同,位于像素0:7,3:11和6:14,但显然在大多数情况下都不会这样。
为此,您可以计算您希望对当前步骤执行的迭代次数,然后将该数字除以帧和ROI宽度之间的差异,这将为您提供分数步骤。由于像素偏移是一个整数,要构造cvRect
,您需要一个整数值。我建议保留并递增rowindex
并将步长作为分数并在cvRect
构造函数中使用之前转换为int - 这样,您的索引将尽可能均匀地移动。
请注意,当float值非常接近int时,我使用了epsilon值(希望)避免在float-to-int转换中舍入错误。有关该技术的示例和说明,请参阅this blog post and comments。但是,请记住,代码未经过测试,可能仍存在舍入错误,尤其是在int值很大的情况下!
/* To see how these calculations work out, experiment with
roiw == 8, StepRow == 4 and frameWidth == 14, 15, 16, 17 */
/* N.B.: Does not cover the case when frameWidth < roiw! */
int stepRowCount = (frameWidth - roiw + (StepRow - 1)) / StepRow + 1;
float step = ((float)(frameWidth - roiw)) / (stepRowCount - 1);
float eps = 0.005;
for (float rowindex = 0.0; (int)(rowindex + eps) <= frameWidth - roiw; rowindex += StepRow)
/* ... column loop ... */
{ searchRect = cvRect((int)(rowindex + eps), colindex, roiw, roih);
PS:迭代图像宽度的索引不应该被称为 colindex ,反之亦然,因为在1920x1080图像中,你有1920列和1080行(因此像 1080p < / em>的)?