测量图像中痕迹的平均厚度
computer-vision
image
image-processing
language-agnostic
5
0

问题是:我有许多由不同厚度的迹线组成的二进制图像。下面有两个图像来说明问题:

第一张图片-尺寸:711 x 643 px

711 x 643示例图像

第二张图片-尺寸:930 x 951 px

替代文字

我需要测量图像中迹线的平均厚度(以像素为单位)。实际上,图像中迹线的平均厚度在某种程度上是主观的。因此,我需要的是一种与走线半径相关的度量,如下图所示:

替代文字

笔记

  • 由于度量不需要非常精确,因此我愿意以精度为代价。换句话说,速度是解决此问题的重要因素。

  • 痕迹中可能有交叉点。

  • 迹线厚度可能不是恒定的,但是可以进行平均测量(即使最大迹线厚度也是可以接受的)。

  • 轨迹将永远比宽度更长。

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

自问问题以来已经三年了:)按照@nikie的程序进行操作,这是笔触宽度的matlab实现。

 clc;
 clear;
 close all;


I = imread('3Zs7m.png');
X = im2bw(I,0.8);

subplottight(2,2,1);
imshow(X);

Dist=bwdist(X);

subplottight(2,2,2);
imshow(Dist,[]);

RegionMax=imregionalmax(Dist);

[x, y] = find(RegionMax ~= 0);
subplottight(2,2,3);
imshow(RegionMax);

List(1:size(x))=0;
for i = 1:size(x) 
List(i)=Dist(x(i),y(i));
end

fprintf('Stroke Width = %u \n',mean(List));
收藏
评论

我建议这个算法:

  1. 对图像应用距离变换,以便将所有背景像素均设置为0,将所有前景像素均设置为距背景的距离
  2. 在距离变换图像中找到局部最大值。这些是直线中间的点。将其像素值(即与背景的距离)图像放入列表中
  3. 计算该列表的中位数或平均值
收藏
评论

@nikie的回答给我留下了深刻的印象,并尝试了一下...

我简化算法只是为了获得最大值而不是平均值,因此逃避了局部最大值检测算法。我认为,如果笔触良好,就足够了(尽管对于自相交的线条来说可能并不准确)。

Mathematica中的程序是:

m = Import["http://imgur.com/3Zs7m.png"]   (* Get image from web*)
s = Abs[ImageData[m] - 1];                 (* Invert colors to detect background *)
k = DistanceTransform[Image[s]]            (* White Pxs converted to distance to black*)
k // ImageAdjust                           (* Show the image *)
Max[ImageData[k]]                          (* Get the max stroke width *)

产生的结果是

替代文字

数值(28.46 px X 2)非常适合我的测量值56 px(尽管您的值为100px:*)

编辑-实现完整算法

好吧……不是寻找局部最大值,而是找到距离变换的固定点。几乎,但不是完全不同于同一件事:)

m = Import["http://imgur.com/3Zs7m.png"];   (*Get image from web*)
s = Abs[ImageData[m] - 1];         (*Invert colors to detect background*)
k = DistanceTransform[Image[s]];   (*White Pxs converted to distance to black*)
Print["Distance to Background*"]
k // ImageAdjust                   (*Show the image*)
Print["Local Maxima"]
weights = 
    Binarize[FixedPoint[ImageAdjust@DistanceTransform[Image[#], .4] &,s]]  
Print["Stroke Width =", 
     2 Mean[Select[Flatten[ImageData[k]] Flatten[ImageData[weights]], # != 0 &]]]

替代文字

您可能会看到,结果与使用简化算法获得的前一个结果非常相似。

收藏
评论

这里 。一个简单的方法!

3.1 估算笔宽

可以从前景的面积A和周长L轻松估算出笔的粗细

T = A/(L/2)

本质上,我们将前景重塑为矩形并测量了最长边的长度。笔的更强建模,例如,圆盘产生圆形末端,可能允许更高的精度,但是光栅化误差会损害其重要性。

尽管精度不是主要问题,但我们确实需要考虑偏见和奇异之处。

因此,我们应该使用考虑“圆度”的函数来计算面积A和周长L。在MATLAB中

A = bwarea(.)  
L = bwarea(bwperim(.; 8))

由于我手边没有MATLAB,因此我在Mathematica中编写了一个小程序:

m = Binarize[Import["http://imgur.com/3Zs7m.png"]] (* Get Image *)
k = Binarize[MorphologicalPerimeter[m]]            (* Get Perimeter *)
p = N[2 Count[ImageData[m], Except[1], 2]/ 
    Count[ImageData[k], Except[0], 2]]             (* Calculate *)

输出为36 Px ...

周边图片如下

替代文字

HTH!

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号