我有一个带有 1MB RAM 和 1MB ROM 的 STM32H7 MCU。我需要在最大尺寸为 1280x1024 的二进制图像数组上制定斑点检测算法。
我搜索了blob检测算法,发现它们主要分为2类,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,最大分辨率为 1280x1024。标签数量 255(0 表示无标签),图像标签大小为 1.25MB。比我们可用的多得多。
我正在寻求一些有关如何进行的建议。如何在不占用太多内存的情况下获取图像中所有斑点的中心坐标和面积信息?任何帮助表示赞赏。我认为第二种算法不适用,因为没有可用的内存。
首先必须使用缩放内核检查图像,以将图像缩放回能够处理的大小。 4:1 或 9:1 都是不错的选择。或者你将不得不获得更多的内存。因为否则这种情况似乎是行不通的。位访问并不是很快,会降低你的效率,我什至不认为你需要那么大的图像。 (至少这是我对视觉系统的经验)
然后,您可以将像素存储在直接
unsigned char
数组中,该数组可以使用您命名的第一个方法进行标记。它不一定是一个递归过程。您还可以确定一个 Blob 是否已重新标记为另一个 Blob,并设置一个标志以再次执行此操作。
这使得外部可见的函数可以有一个 while
循环,它可以不断调用您的标签函数,而无需创建大堆栈。
然后通过检查图像并计算每个标记斑点的像素实例来确定区域。
可以通过计算斑点的矩,然后计算质心来找到某个斑点的中心。这是一些相当繁重的数学,所以不要灰心,虽然它是一个很难咬的苹果,但它是一个很好的解决方案。
(小提示:您可以从 OpenCV 获取 C++ 代码并查看他们的代码以了解它是如何完成的)