我正在尝试实现Learning OpenCV一书中概述的码本前景检测算法。
该算法仅针对图片的每个像素描述了基于码本的方法。所以我采用了想到的最简单的方法——拥有一组码本,每个像素一个,很像 IplImage 的矩阵结构。数组的长度等于图像中的像素数。
我写了以下两个循环来学习背景和分割前景。它利用了我对 src 图像内部矩阵结构的有限理解,并使用指针算法来遍历像素。
void foreground(IplImage* src, IplImage* dst, codeBook* c, int* minMod, int* maxMod){
int height = src->height;
int width = src->width;
uchar* srcCurrent = (uchar*) src->imageData;
uchar* srcRowHead = srcCurrent;
int srcChannels = src->nChannels;
int srcRowWidth = src->widthStep;
uchar* dstCurrent = (uchar*) dst->imageData;
uchar* dstRowHead = dstCurrent;
// dst has 1 channel
int dstRowWidth = dst->widthStep;
for(int row = 0; row < height; row++){
for(int column = 0; column < width; column++){
(*dstCurrent) = find_foreground(srcCurrent, (*c), srcChannels, minMod, maxMod);
dstCurrent++;
c++;
srcCurrent += srcChannels;
}
srcCurrent = srcRowHead + srcRowWidth;
srcRowHead = srcCurrent;
dstCurrent = dstRowHead + dstRowWidth;
dstRowHead = dstCurrent;
}
}
void background(IplImage* src, codeBook* c, unsigned* learnBounds){
int height = src->height;
int width = src->width;
uchar* srcCurrent = (uchar*) src->imageData;
uchar* srcRowHead = srcCurrent;
int srcChannels = src->nChannels;
int srcRowWidth = src->widthStep;
for(int row = 0; row < height; row++){
for(int column = 0; column < width; column++){
update_codebook(srcCurrent, c[row*column], learnBounds, srcChannels);
srcCurrent += srcChannels;
}
srcCurrent = srcRowHead + srcRowWidth;
srcRowHead = srcCurrent;
}
}
该程序有效,但非常缓慢。有什么明显的东西在减慢速度吗?还是简单实现中的固有问题?我有什么办法可以加快速度吗?每个码本都没有按特定顺序排序,因此处理每个像素确实需要线性时间。因此,将背景样本加倍,程序对每个像素的运行速度减慢 2,然后将其放大像素数。但就实现而言,我看不到任何清晰、合乎逻辑的方式来对代码元素条目进行排序。
我知道在 opencv 示例中有相同算法的示例实现。然而,这种结构似乎要复杂得多。我希望更多地了解这种方法背后的原因,我知道我可以为现实生活中的应用程序修改示例。
谢谢