自动检测彩色背景下的 B/W 图像。当局部阈值不起作用时我该怎么办?

Automatic detection of B/W image against colored background. What should I do when local thresholding doesn't work?

我有一个图像,它由一个黑白文档和一个异色背景组成。我需要自动检测图像中的文档。

我试过Otsu的方法和Local Thresholding方法,但都没有成功。此外,像 Canny 和 Sobel 这样的边缘检测器也不起作用。

谁能推荐一些自动检测文档的方法?

这是一个起始图片示例:

在使用各种阈值方法后,我能够得到以下输出:

接下来是一种自动全局方法,用于在彩色背景下隔离低色彩饱和度的区域(例如 b/w 页面)。当基于灰度转换图像的自适应阈值的其他方法失败时,这可能作为替代方法很好地工作。

首先,我们加载一个 RGB 图像 I,从 RGB 转换为 HSV,并隔离饱和通道:

I = imread('/path/to/image.jpg');
Ihsv = rgb2hsv(I);     % convert image to HSV
Isat = Ihsv(:,:,2);    % keep only saturation channel

一般来说,决定如何进行任何对象检测任务的第一步是检查像素值的分布。在这种情况下,这些值表示图像中每个点的颜色饱和度级别:

% Visualize saturation value distribution
imhist(Isat); box off

从这个直方图中,我们可以看到似乎至少有 3 个不同的峰值。鉴于我们的目标是一张黑白 sheet 的纸,我们希望在光谱的低端隔离饱和度值。这意味着我们想要找到一个阈值,将较低的 1-2 个峰值与较高的值分开。

一种自动执行此操作的方法是通过高斯混合建模 (GMM)。 GMM 可能会很慢,但由于您正在离线处理图像,我认为这不是问题。我们将在这里使用 Matlab 的 fitgmdist 函数并尝试将 3 个高斯分布拟合到饱和图像:

% Find threshold for calling ROI using GMM
n_gauss = 3;                         % number of Gaussians to fit
gmm_opt = statset('MaxIter', 1e3);   % max iterations to converge
gmmf = fitgmdist(Isat(:), n_gauss, 'Options', gmm_opt);

接下来,我们使用 GMM 拟合来 class 化每个像素并可视化我们的 GMM class化结果:

% Classify pixels using GMM
gmm_class = cluster(gmmf, Isat(:));

% Plot histogram, colored by class
hold on
bin_edges = linspace(0,1,256);
for j=1:n_gauss, histogram(Isat(gmm_class==j), bin_edges); end

在这个例子中,我们可以看到 GMM 最终将最左边的 2 个峰组合在一起(蓝色 class)并将较高的值分成两个 classes(黄色和红色) .注意:您的颜色可能不同,因为 GMM 对随机初始条件很敏感。对于我们在这里的使用,这可能没问题,但我们可以检查蓝色 class 是否确实捕获了我们想要通过可视化图像来隔离的对象,像素由 class 着色:

% Visualize classes as image
im_class = reshape(gmm_class ,size(Isat));
imagesc(im_class); axis image off

所以看起来我们对饱和度值的 GMM 分割使我们处于正确的范围内 - 将文档像素(蓝色)分组在一起。但是请注意,我们还有两个问题需要解决。首先,底部的大横条也包含在与文档相同的 class 中。其次,页面上打印的文本未包含在文档中 class。但别担心,我们可以通过在 GMM 分组图像上应用一些过滤器来解决这些问题。

首先,我们将隔离我们想要的 class,然后进行一些形态学操作以低通过滤并填充对象中的间隙。

Isat_bw = im_class == find(gmmf.mu == min(gmmf.mu)); %isolate desired class
opened = imopen(Isat_bw, strel('disk',3)); % morph open
closed = imclose(Isat_bw, strel('disk',50)); % morph close
imshow(closed)

接下来,我们将使用大小过滤器将文档 ROI 与底部的大对象隔离开来。我假设您的文档永远不会填满图像的整个宽度,并且不需要任何大于 sheet 纸张的固体物体。我们可以使用 regionprops 函数为我们提供有关我们检测到的对象的统计信息,在这种情况下,我们只需要 return 对象的长轴长度和相应的像素:

% Size filtering
props = regionprops(closed,'PixelIdxList','MajorAxisLength');
[~,ridx] = min([props.MajorAxisLength]);
output_im = zeros(numel(closed),1);
output_im(props(ridx).PixelIdxList) = 1;
output_im = reshape(output_im, size(closed));

% Display final mask
imshow(output_im)

最后,我们剩下 output_im - 对应于文档的单个实体对象的二进制掩码。如果这个特定大小的过滤规则在你的其他图像上效果不佳,应该可以为 regionprops 报告的其他特征(例如总面积、短轴长度等)找到一组值,这些值给出可靠的结果。

对原始图像和最终蒙版图像进行并排比较表明,这种方法为您的样本图像产生了相当不错的结果,但可能需要调整一些参数(如尺寸排除规则)如果其他图像的结果不太好。

% Display final image
image([I I.*uint8(output_im)]); axis image; axis off

最后一点:请注意 GMM 算法对随机初始条件很敏感,因此可能会随机失败或产生不良结果。因此,采取某种质量控制措施以确保检测到这些随机故障非常重要。一种可能性是使用 GMM 模型的后验概率来形成某种拒绝特定拟合的标准,但这超出了这个答案的范围。