OpenCV分水岭-用于修改代码以获得更好结果的选项-否则将满足我的需求

时间:2018-07-02 21:57:25

标签: python-3.x opencv raspberry-pi computer-vision watershed

我正在使用Raspberry Pi Zero,Python 3脚本和OpenCV。 我正在尝试创建单个像素连续路径,以在图像中描绘“硬”表面与“软”表面: Original 我要结束的图像是“纯白色背景上的红色线条(在JPG下方)”(叠加在原始图像上只是为了显示其位置)。我希望能够在所需路径的大约10个像素内获得相对平滑的结果: Desired-overlay

到目前为止,我已经相信我应该可以使用cv.watershed作为实现此目标的主要功能,但是到目前为止效果还不是很好。 为了简化我的OpenCV学习曲线,我修改了watershed.py示例。
在使用分水岭之前,我先进行了150像素半径的高斯模糊处理,这使我获得了迄今为止最好的效果。 然后,我放置两个分水岭标记,在图像的每一侧放置一个,并尝试使分水岭定义我想要的边框。

以下是使用分水岭的Python脚本(很抱歉,使用了不正确的代码段,但代码示例插入无效):

#!/usr/bin/env python

'''
Watershed segmentation
=========
This program demonstrates the watershed segmentation algorithm
in OpenCV: watershed().
Usage
-----
watershed.py [image filename]
Keys
----
  1-7   - switch marker color
  SPACE - update segmentation
  r     - reset
  a     - toggle autoupdate
  ESC   - exit
'''


# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2 as cv

class Sketcher:
    def __init__(self, windowname, dests, colors_func):
        self.prev_pt = None
        self.windowname = windowname
        self.dests = dests
        self.colors_func = colors_func
        self.dirty = False
        self.show()
        cv.setMouseCallback(self.windowname, self.on_mouse)

    def show(self):
        cv.imshow(self.windowname, self.dests[0])

    def on_mouse(self, event, x, y, flags, param):
        pt = (x, y)
        if event == cv.EVENT_LBUTTONDOWN:
            self.prev_pt = pt
        elif event == cv.EVENT_LBUTTONUP:
            self.prev_pt = None

        if self.prev_pt and flags & cv.EVENT_FLAG_LBUTTON:
            for dst, color in zip(self.dests, self.colors_func()):
                cv.line(dst, self.prev_pt, pt, color, 5)
            self.dirty = True
            self.prev_pt = pt
            self.show()


class App:
    def __init__(self, fn):
        self.img = cv.imread(fn)
        if self.img is None:
            raise Exception('Failed to load image file: %s' % fn)

        h, w = self.img.shape[:2]
        self.markers = np.zeros((h, w), np.int32)
        self.markers_vis = self.img.copy()
        self.cur_marker = 1
        self.colors = np.int32( list(np.ndindex(2, 2, 2)) ) * 255

        self.auto_update = True
        self.sketch = Sketcher('img', [self.markers_vis, self.markers], self.get_colors)

    def get_colors(self):
        return list(map(int, self.colors[self.cur_marker])), self.cur_marker

    def watershed(self):
        m = self.markers.copy()
        cv.watershed(self.img, m)
        overlay = self.colors[np.maximum(m, 0)]
        oim = cv.imread('1.JPG')
        vis = cv.addWeighted(oim, 0.5, overlay, 0.5, 0.0, dtype=cv.CV_8UC3)
        cv.imshow('watershed', vis)

    def run(self):
        while cv.getWindowProperty('img', 0) != -1 or cv.getWindowProperty('watershed', 0) != -1:
            ch = cv.waitKey(50)
            if ch == 27:
                break
            if ch >= ord('1') and ch <= ord('7'):
                self.cur_marker = ch - ord('0')
                print('marker: ', self.cur_marker)
            if ch == ord(' ') or (self.sketch.dirty and self.auto_update):
                self.watershed()
                self.sketch.dirty = False
            if ch in [ord('a'), ord('A')]:
                self.auto_update = not self.auto_update
                print('auto_update if', ['off', 'on'][self.auto_update])
            if ch in [ord('r'), ord('R')]:
                self.markers[:] = 0
                self.markers_vis[:] = self.img
                self.sketch.show()
        cv.destroyAllWindows()


if __name__ == '__main__':
    import sys
    try:
        fn = sys.argv[1]
    except:
        fn = '1-gb150.JPG'
    print(__doc__)
    App(fn).run()

这是到目前为止我所见过的最好的分水岭: Watershed results

我还可以使用其他分水岭/流程选项,或者如果分水岭不是解决此问题的最佳方法,那么可以添加/使用其他什么方法呢?

(编辑:至于执行时间,我在Raspberry Pi Zero 0上需要1-2秒)

(编辑7/3/2018#1:可能有助于进一步定义算法规则以简化过程的条件。

  1. 我理想的道路永远不会是孤岛。
  2. 我希望的路径可以简化为进入一个图像边缘并离开另一图像边缘的线,同时沿路径采用“最直的”路径。图像序列始终可以在该状态下开始。
  3. 也许到了任何角落,算法都可以停止并寻求帮助。 (即处理遇到的图像具有大于90度角的图像)。
  4. 图像系列将始终在前一图像确定的所需线上有一些点,可以用作新图像中“边缘跟随”算法的起始像素(当草长大时,边缘跟随变得困难但我可以先除草)。

(编辑:我需要在其上使用算法的更多硬/软表面图像): enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

(结束更多)

0 个答案:

没有答案