【问题标题】:Check for areas that are too thin in an image检查图像中太薄的区域
【发布时间】:2015-04-01 06:11:43
【问题描述】:

我正在尝试验证用于雕刻机的黑白图像(更多是剪贴画图像,而不是照片)。
我需要考虑的主要事情之一是区域的大小(或线条的宽度),因为机器无法处理太细的线条 - 所以我需要找到比给定阈值更薄的区域。

以这张图片为例:

竖琴弦可能太细而无法雕刻。

我正在阅读有关 Matlab 和 OpenCV 的信息,但图像处理是我第一次学习的领域。

我是一名 Java / C# 开发人员,因此使用其中一种语言完成实现对我来说是最好的,但任何方向都将不胜感激。

【问题讨论】:

  • 欢迎来到 Stack Overflow。不幸的是,您似乎一次要求太多。最好从一些简单的练习开始你的工作,并且在你学习图像处理时问一些更直接的问题(包括关于你遇到问题的代码和解释)。
  • 我认为这个问题实际上是比较好的。 OP 发布了一个可以以抽象的计算机视觉方式回答的问题,并且指向适当算法或方法的指针将有资格作为答案。

标签: python matlab opencv image-processing computer-vision


【解决方案1】:

使用 使用图像morphological operations 的解决方案:

定义允许区域的最小厚度,例如minThick=4

BW = imread('http://i.stack.imgur.com/oXKep.jpg'); 
BW = BW(:,:,1) < 128; %// convert image to binary mask
se = strel('disk', minTick/2, 0); %// define a disk element   
eBW = imerode( BW, se ); %// "chop" half thickness from mask
deBW = imdilate( eBW, se ); %// dilate the eroded mask

侵蚀和扩张应该使比minThick更厚的区域保持不变,但它会去除薄的区域

invalidArea = BW & ~deBW; %// pixels that are in BW but not in deBW

结果为:

您可以在链接文档中阅读更多关于 imdilateimerode 的信息。

【讨论】:

  • 这是一个很棒的(!)示例 - 我一定会看看它。如何在现实世界的应用程序(Java/C#/Python 等)中实现这个 matlab 程序?
  • @JamesBlack 因为我们只使用非常基本的操作,例如erodedilate,所以在其他编程语言中找到它们的等价物应该没有问题:例如,opencvscipy.. .
  • @Shai - 你能否对开口 (imopen) 执行相同的操作,因为开口与腐蚀后膨胀相同? +1 顺便说一句。
  • @rayryeng 我试图坚持这里的基础知识,并使答案尽可能简单明了。你是对的,它也可以通过其他方式完成
  • @Shai - 只是好奇 :) 谢谢你的回答。
【解决方案2】:

这主要是为了自包含,但这是 @Shai 在 Python 中执行的等效代码。我使用了 Python 中的 numpyOpenCV 包。在 Python 中执行此操作的等效代码如下:

import numpy as np # Import numpy package
import cv2 # Import OpenCV package

orig = cv2.imread('oXKep.jpg') # Read in image from disk
BW = orig[:,:,2] < 128 # Threshold below 128 to invert image
minThick = 5 # Define minimum thickness
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (minThick,minThick)) # define a disk element
finalBW = 255*cv2.morphologyEx(BW.astype('uint8'), cv2.MORPH_OPEN, se) # "chop" half thickness from mask and dilate the eroded mask

# Find invalid area
invalidArea = 255*np.logical_and(BW, np.logical_not(finalBW)).astype('uint8') 

# Show original image
cv2.imshow('Original', orig)

# Show opened result
cv2.imshow('Final', finalBW)

# Show invalid lines
cv2.imshow('Invalid Area', invalidArea)

# Wait for user input then close windows
cv2.waitKey(0)
cv2.destroyAllWindows()

我需要指出的一些错综复杂的地方:

  1. OpenCV 的imread 函数读取颜色通道以相对于 MATLAB 的相反顺序。具体来说,通道是按蓝-绿-红顺序读入的。这意味着第一个通道是蓝色的,第二个通道是绿色的,第三个通道是红色的。在 MATLAB 中,这些以正确的 RGB 顺序读取。因为这是一个灰度图像,RGB 分量是相同的,所以你使用哪个通道并不重要。但是为了和 Shai 的方法一致,红色通道是被访问的,所以我们需要通过 OpenCV 访问图像的最后一个通道。
  2. MATLAB 中结构编号为 0 的disk 结构元素本质上是菱形。但是,由于 OpenCV 没有内置这种结构元素,而且我想生成尽可能少的代码来让事情顺利进行,所以我可以使用的最接近的东西是椭圆形结构元素。
  3. 为了使结构元素对称,您需要确保大小是奇数,因此我将 Shai 示例中的大小从 4 更改为 5。
  4. 为了使用 OpenCV Python 显示图像,图像必须至少是无符号 8 位整数类型。不支持使用 OpenCV 显示的二进制图像,因此我人为地制作了二进制图像 uint8 并在显示之前将值乘以 255。
  5. 您可以使用形态开运算将腐蚀和膨胀运算合并为一个运算。开放旨在删除细线或断开连接细但保持原始更大对象形状的对象。这是首先侵蚀的点,以便您可以删除这些线,但您会根据区域缩小对象,然后再扩大,以便您可以将形状恢复到其原始大小(大部分)。我通过cv2.morphologyEx 执行形态开放来利用这一点。

这是我得到的:

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-02-22
  • 2017-10-13
  • 1970-01-01
  • 2011-03-19
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多