文档

大块处理大图像

这个例子展示了如何通过将图像划分为块来对TIFF图像执行边缘检测。在处理大型图像时,正常的图像处理技术有时会失效。图像可能太大而无法加载到内存中,或者它们可能加载到内存中,但又太大而无法处理。

为了避免这些问题,您可以增量地处理大型映像:读取、处理,最后将结果写入磁盘,每次一个区域。的blockproc函数可以帮助您完成这个过程。使用blockproc,指定图像、块大小和函数句柄。blockproc然后将输入图像分成指定大小的块,使用函数句柄一次处理一个块,然后将结果组装成输出图像。blockproc将输出返回到内存或磁盘上的新文件。

首先,考虑不进行块处理的边缘检测结果。本例使用一个小图像cameraman.tif来说明概念,但是块处理通常对大图像更有用。

file_name =“cameraman.tif”;I = imread(file_name);normal_edges =边缘(I,“精明”);imshow (I)标题(原始图像的)

图imshow(normal_edges)“常规边缘检测”)

现在使用块处理尝试相同的任务。的blockproc函数内置了对TIFF图像的支持,因此您不必将万博1manbetx文件完全读入内存imread.相反,使用字符串filename作为输入来调用函数。blockproc每次读取一个块,使此工作流程非常适合非常大的图像。

当处理大图片时,你通常会使用“Destination”参数来指定要放入的文件blockproc将输出图像写入。但是,在本例中,您将把结果返回给内存中的一个变量。

这个例子使用的块大小为[50 50]。一般来说,选择更大的块大小会产生更好的性能blockproc.对于文件到文件的工作流来说尤其如此,因为在这些工作流中,访问磁盘将导致显著的性能损失。适当的块大小取决于可用的机器资源,但每个维度应该在数千像素的范围内。

可以使用匿名函数定义函数句柄。的函数传递一个结构体作为输入,一个“块结构体”,有几个%字段包含块数据以及其他相关信息。函数应返回已处理的块数据。edgeFun = @(block_struct)“精明”);Block_size = [50 50];block_edges = blockproc(file_name,block_size,edgeFun);图imshow(block_edges)“块处理-最简单的语法”)

请注意来自块处理的重要工件。确定一个像素是否是边缘像素需要来自邻近像素的信息。这意味着每个块不能与周围的像素完全分开处理。要解决此问题,请使用blockproc参数“BorderSize”指定每个块周围的垂直和水平边界。必要的'BorderSize'取决于正在执行的任务。

border = [10 10];block_edges = blockproc(file_name,block_size,edgeFun,“BorderSize”, border_size);图imshow(block_edges)“块处理-块边界”)

这些块现在每边都有10个像素的图像数据进行处理。这看起来更好,但结果仍然与原来的内存中的结果有很大不同。原因是Canny边缘检测器使用基于完整图像直方图计算的阈值。自blockproc函数调用边缘函数,Canny算法使用的是不完全直方图,因此在整个图像中使用不同的阈值。

当块处理图像时,理解这些类型的算法约束是很重要的。有些函数不会直接转换为适用于所有语法的块处理。在这种情况下,边缘函数允许您传入一个固定的阈值作为输入参数,而不是计算它。的三参数语法修改函数句柄边缘,从而消除函数的一个“全局”约束。经过反复试验,发现0.09的阈值可以得到很好的结果。

Thresh = 0.09;edgeFun = @(block_struct)“精明”、打);block_edges = blockproc(file_name,block_size,edgeFun,“BorderSize”, border_size);图imshow(block_edges)“块处理-边界和固定阈值”)

结果现在与内存中的原始结果紧密匹配。您可以在边界上看到一些附加的工件。这是由于Canny边缘检测器使用不同的填充方法。目前,blockproc仅支持沿图万博1manbetx像边界的零填充。

这个话题有用吗?