Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 自适应扫描线填充以检测离散对象_Python_Image Processing_Image Segmentation - Fatal编程技术网

Python 自适应扫描线填充以检测离散对象

Python 自适应扫描线填充以检测离散对象,python,image-processing,image-segmentation,Python,Image Processing,Image Segmentation,我试图在Python中检测颜色足够接近的连续区域。我独立地偶然发现了8路递归泛光填充算法(当发现的RGB颜色和所需RGB颜色之间的欧几里德距离超过阈值时终止),该算法在小规模下效果很好,但会在200万像素图像上导致堆栈溢出 堆栈溢出和维基百科点到扫描线填充作为答案,但我发现的每一个解释都是在C++中或关于填充具有已知顶点的多边形。有人能给我一个很好的伪代码来解释类似于递归洪水填充的情况吗 由于缺乏正式的数学知识(我在上高中),我在研究图像分割方面遇到了困难。如果对K-Means或类似的东西有一个

我试图在Python中检测颜色足够接近的连续区域。我独立地偶然发现了8路递归泛光填充算法(当发现的RGB颜色和所需RGB颜色之间的欧几里德距离超过阈值时终止),该算法在小规模下效果很好,但会在200万像素图像上导致堆栈溢出

堆栈溢出和维基百科点到扫描线填充作为答案,但我发现的每一个解释都是在C++中或关于填充具有已知顶点的多边形。有人能给我一个很好的伪代码来解释类似于递归洪水填充的情况吗


由于缺乏正式的数学知识(我在上高中),我在研究图像分割方面遇到了困难。如果对K-Means或类似的东西有一个简单的英语解释,那也太好了。OpenCV看起来很有希望,但看起来我得到的只是一个彩色的扁平图像;我所关心的是对象x,y处的像素列表。

扫描线整体填充的思想如下

  • 您将获得初始点(种子)(x,y)
  • 尽可能向左移动,直到像素(x-1,y)不被填充或达到x=0为止
  • 到达的x将是扫描线的起点;保持两个标志“查找上方洞穴”和“查找下方洞穴”,这两个标志都初始化为true
  • 这是扫描线循环的开始。检查上面的像素(x,y-1),如果要填充,现在考虑到上面看标志和像素,有4种情况:
    • 如果“向上看”为真,并且要填充像素,则发现一个“新洞穴”,将(x,y-1)存储在“待办事项列表”中,并将“向上看”标记为假
    • 如果“上面看”为假,并且像素不需要填充,则当前洞穴已完成,您需要寻找另一个洞穴,因此只需将“上面看”标记为真
    • 在其他情况下(上面看是真的,像素不被填充,或者上面看是假的,像素被填充),你们什么也不做
  • 使用“look Down”(向下看)标志和像素颜色(x,y+1)重复相同的推理
  • 绘制像素(x,y)并移动到(x+1,y),从(5)开始重复,除非移动到的像素不会被绘制
  • 如果“待办事项列表”中有任何内容,请将其挑选出来,并使用在待办事项列表中找到的坐标(x,y)返回(1)
  • 这是用于4连接洪水填充的版本。对于8连接填充,启动扫描线时,还需要检查(x-1,y-1)和(x-1,y+1)处的洞穴,并且需要检查扫描线末端的洞穴(x+1,y-1)和(x+1,y+1)(如果相应的标志为真)

    在扫描线上移动时,您要做的是将图片中的绿点添加到您的待办事项列表中:

    请注意,种子的数量不会是“最小的”(例如,示例中的前两个“以上种子”将在同一个洞穴中结束,因此实际上只需要其中一个)。不过,存储它们所需的堆栈量通常比逐像素递归方法所需的堆栈量小得多

    限制所需内存量的另一种可能方法是使用边界绘制算法:

  • 将初始种子(x,y)放入
    current\u active
    列表并绘制它
  • 将下一个激活的
    列表初始化为空
  • 对于
    current\u active
    列表中的每个像素,检查需要绘制的相邻像素:当您找到一个像素时,将其绘制并添加到
    next\u active
    列表中
  • 完成后,将
    current\u active
    列表设置为
    next\u active
    列表,并从2开始重复,除非列表为空

  • 您可以在中看到这两种算法的示例。

    Wow!谢谢你提供的信息。扫描线现在终于有意义了。实际上,我对“前沿”算法更感兴趣,它似乎是我所做的迭代等价物。为什么Python很容易处理30000多个项目列表,但当我尝试递归深度超过10000时失败了?我实际上使用了您的“frontier”方法,因为它似乎最接近原始想法,而且速度非常快。仍然有趣的是,为什么它比递归方法快得多,尽管…@jacobbaer:CPython不处理无限递归,因为它依赖于解释器中的C堆栈,并且C堆栈上的限制有时非常低。您可以使用
    sys.setrecursionlimit
    提高python限制,但是如果将其设置得太高,您只会使python本身崩溃,而不会得到异常。还要注意,Python不处理尾部调用优化,纯函数式编程视图也没有得到真正认可。递归当然可以,但深度递归(例如使用递归遍历链表)是个坏主意。@6502如何检查您是否已经归档了一行,这样您就不会多次上下检查像素,或者检查多个像素是不可避免的。填充扫描线时,您会看到“上方”(即y-1)每次你看到一个新的光圈,你都会放置一个种子,但只有一个,直到你看到天花板再次关闭。假设向上看,你看到
    1100001111100011111011111
    你只需要在第三、第十二和第二十位置放置一个种子。当然,可能不需要放置种子,因为多个孔可能是同一个洞穴的一部分,但如果不进行全局搜索,您将无法知道。