我有一个STM32H7 MCU,具有1MB的RAM和1MB的ROM。我需要在最大尺寸为1280x1024的二进制图像数组上进行斑点检测算法。
我搜索了斑点检测算法,发现它们主要分为两类,LINK:
void setLabels(){
int m=2;
for(int y=0; y<height; y++){
for(int x=0; x<width; x++){
if(getPixel(x,y) == 1) compLabel(x,y,m++);
}
}
}
void compLabel(int i, int j,int m){
if(getPixel(i,j)==1){
setPixel(i,j,m); //assign label
compLabel(i-1,j-1,m);
compLabel(i-1,j,m);
compLabel(i-1,j+1,m);
compLabel(i,j-1,m);
compLabel(i,j+1,m);
compLabel(i+1,j-1,m);
compLabel(i+1,j,m);
compLabel(i+1,j+1,m);
}
}
第一种算法的缺点是它对原始像素周围的所有像素都使用递归调用。由于堆栈有限,恐怕会在STM32上引起硬故障错误。 第二种算法的缺点是,它需要大量内存来存储标签图像。例如,最大分辨率为1280x1024,最大标签数量255(无标签为0),图像标签大小为1.25MB。比我们现有的更多。
我正在寻找有关如何进行的建议。如何在不占用大量内存的情况下获取图像中所有斑点的中心坐标和面积信息?任何帮助表示赞赏。我认为第二个算法不在图片中,因为没有可用的内存。
答案 0 :(得分:0)
首先,您必须使用缩放内核遍历图像,才能将图像缩放回可以处理的图像。 4:1或9:1是好的可能性。否则您将不得不获得更多的RAM。因为否则这种情况似乎是行不通的。位访问并不是真的很快,并且会降低您的效率,我什至不认为您需要那么大的图像。 (至少这是我在视觉系统方面的经验)
然后,您可以将像素存储在直unsigned char
数组中,该数组可以用您命名的第一个方法标记。它不一定是递归过程。您还可以确定是否将某个Blob重新标记为另一个Blob,并设置一个标志以再次执行此操作。
这样就可以使外部可见函数具有一个while
循环,该循环将不断调用您的标签函数而不会创建大堆栈。
然后通过遍历图像并为每个标记的blob计数一个像素的实例来完成区域确定。
可以通过计算斑点的moments然后计算center of mass来找到某个斑点的中心。这是一个相当沉重的数学运算,因此不要气,,虽然这是一个苹果公司,但它是一个很好的解决方案。
(小提示:您可以从OpenCV中获取C ++代码并浏览their code来了解它的完成方式)