我正在使用Raspberry Pi Zero,Python 3脚本和OpenCV。 我正在尝试创建单个像素连续路径,以在图像中描绘“硬”表面与“软”表面: 我要结束的图像是“纯白色背景上的红色线条(在JPG下方)”(叠加在原始图像上只是为了显示其位置)。我希望能够在所需路径的大约10个像素内获得相对平滑的结果:
到目前为止,我已经相信我应该可以使用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()
我还可以使用其他分水岭/流程选项,或者如果分水岭不是解决此问题的最佳方法,那么可以添加/使用其他什么方法呢?
(编辑:至于执行时间,我在Raspberry Pi Zero 0上需要1-2秒)
(编辑7/3/2018#1:可能有助于进一步定义算法规则以简化过程的条件。
(结束更多)