OpenCV Watershed - варианты изменения кода для получения лучших результатов - в противном случае, что будет работать для моих нужд - PullRequest
0 голосов
/ 03 июля 2018

Я использую Raspberry Pi Zero, скрипт Python 3 и OpenCV. Я пытаюсь создать однопиксельный непрерывный путь, который очерчивает «твердую» поверхность от «мягкой» поверхности на изображениях, как это: Original Изображение, которое я хочу получить в итоге, это «КРАСНАЯ линия (на изображении ниже в формате JPG) на сплошном белом фоне» (наложена на оригинал, чтобы показать его местоположение). Я надеюсь, что смогу получить относительно плавный результат в пределах 10 пикселей от моего желаемого пути: Desired-overlay

До сих пор я пришел к выводу, что должен иметь возможность использовать cv.watershed в качестве основной функции для достижения этой цели, но результаты пока не так хороши. Чтобы упростить мою кривую обучения OpenCV, я изменил пример watershed.py.
Перед тем, как использовать водораздел, я делаю Gausian Blurr с радиусом 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

Какие еще варианты водораздела / процесса я могу использовать, или, если водораздел не является лучшим подходом для этой проблемы, какой другой подход можно добавить / использовать вместо этого?

(Изменить: На время выполнения мне понадобится 1-2 секунды на Raspberry Pi Zero)

(Ред. 3/7/2018 # 1: Условия, которые могут помочь в дальнейшем определении правил алгоритма для упрощения процесса.

  1. Мой желаемый путь никогда не был бы островами.
  2. Мой желаемый путь может быть уменьшен до линий, которые входят в один край изображения и покидают другой край изображения, выбирая при этом «самый прямой» путь. Последовательность изображений всегда может начинаться в этом состоянии.
  3. Возможно, если будет достигнут какой-либо угол, алгоритм может остановиться и попросить помощи. (т. е. для обработки изображения, имеющего угол> 90 градусов).
  4. Ряд изображений всегда будет иметь некоторую точку на желаемой линии, которая была определена из предыдущего изображения, которая могла бы использоваться в качестве начального пикселя для алгоритма 'отслеживания кромок' в новом изображении (отслеживание кромок становится затруднительным, когда трава растет через край, но я мог бы сначала съесть траву).

(Edit: более твердые / мягкие изображения поверхности, на которых мне нужно использовать алгоритм): 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

(конец больше)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...