如何使用轨迹栏进行交互式图像二值化?
Posted
技术标签:
【中文标题】如何使用轨迹栏进行交互式图像二值化?【英文标题】:How to do interactive image binarization using trackbars? 【发布时间】:2021-03-05 06:56:05 【问题描述】:我有一个代码,它使用 Otsu 阈值为我提供二进制图像。我正在为 U-Net 制作数据集,并且我想尝试不同的算法(全局和本地),以便保存“最佳”图像。下面是我的图像二值化代码。
import cv2
import numpy as np
import skimage.filters as filters
img = cv2.imread('math.png') # read the image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # convert to gray
smooth = cv2.GaussianBlur(gray, (95,95), 0) # blur
division = cv2.divide(gray, smooth, scale=255) # divide gray by morphology image
# Add Morphology here. Dilation, Erosion, Opening, Closing or so.
sharp = filters.unsharp_mask(division, radius=1.5, amount=1.5, multichannel=False, preserve_range=False) # sharpen using unsharp masking
sharp = (255*sharp).clip(0,255).astype(np.uint8)
thresh = cv2.threshold(sharp, 0, 255, cv2.THRESH_OTSU )[1] # threshold
我在更广泛的领域得到了相当不错的结果,但我想使用cv2.namedWindow
、cv2.createTrackbar
、cv2.getTrackbarPos
,以便我可以设置radius
、amount
、kernel
的值,膨胀,腐蚀等,通过使用以下函数。
cv2.namedWindow('Tracking Window')
cv2.createTrackbar('param1','Tracking Window',0,255,dummy) # dummy is just a dummy function which returns None
param1 = cv2.getTrackbarPos('param1','Tracking Window')
我怎样才能得到所有这些。还有,按s
如何保存图片,按n
打开下一张图片?
Original Question was posted by me 6 months ago
【问题讨论】:
【参考方案1】:我的解决方案的代码比预期的要长,但它提供了一些花哨的操作可能性。首先,让我们看看实际的窗口:
有滑块
形态学操作(扩张、侵蚀、关闭、打开), 结构元素(矩形、椭圆、十字)和 内核大小(这里:限制在1 ... 21
范围内)。
窗口名称反映了前两个滑块的当前设置:
当按下 s 时,图像会结合当前设置保存:
Saved image as Erosion_Ellipsoid_SLEM_11.png.
按下 n 时,将选择列表中的下一个图像。
在任何时候,当按下 q 时,应用程序就会退出。它会在处理完列表中的所有图像后自动结束。
在交互部分之前和之后,您可以添加任何您想要的操作,参见。代码。
而且,这里是完整的代码:
import cv2
# Collect morphological operations
morphs = [cv2.MORPH_DILATE, cv2.MORPH_ERODE, cv2.MORPH_CLOSE, cv2.MORPH_OPEN]
# Collect some texts for later
morph_texts =
cv2.MORPH_DILATE: 'Dilation',
cv2.MORPH_ERODE: 'Erosion',
cv2.MORPH_CLOSE: 'Closing',
cv2.MORPH_OPEN: 'Opening'
# Collect structuring elements
slems = [cv2.MORPH_RECT, cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS]
# Collect some texts for later
slem_texts =
cv2.MORPH_RECT: 'Rectangular SLEM',
cv2.MORPH_ELLIPSE: 'Ellipsoid SLEM',
cv2.MORPH_CROSS: 'Cross SLEM'
# Collect images
images = [...]
# Set up maximum values for each slider
max_morph = len(morphs) - 1
max_slem = len(slems) - 1
max_ks = 21
# Set up initial values for each slider
morph = 0
slem = 0
ks = 1
# Set up initial working image
temp = None
# Set up initial window name
title_window = 'Interactive with '.format(morph_texts[morphs[morph]],
slem_texts[slems[slem]])
# Triggered when any slider is manipulated
def on_trackbar(unused):
global image, ks, morph, slem, temp, title_window
# Get current slider values
morph = cv2.getTrackbarPos('Operation', title_window)
slem = cv2.getTrackbarPos('SLEM', title_window)
ks = cv2.getTrackbarPos('Kernel size', title_window)
# Reset window name
cv2.setWindowTitle(title_window, 'Interactive with '.
format(morph_texts[morphs[morph]],
slem_texts[slems[slem]]))
# Get current morphological operation and structuring element
op = morphs[morph]
sl = cv2.getStructuringElement(slems[slem], (ks, ks))
# Actual morphological operation
temp = cv2.morphologyEx(image.copy(), op, sl)
# Show manipulated image with current settings
cv2.imshow(title_window, temp)
# Iterate images
for image in images:
# Here go your steps before the interactive part
# ...
image = cv2.threshold(cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY),
0, 255, cv2.THRESH_OTSU)[1]
# Here starts the interactive part
cv2.namedWindow(title_window)
cv2.createTrackbar('Operation', title_window, morph, max_morph, on_trackbar)
cv2.createTrackbar('SLEM', title_window, slem, max_slem, on_trackbar)
cv2.createTrackbar('Kernel size', title_window, ks, max_ks, on_trackbar)
cv2.setTrackbarMin('Kernel size', title_window, 1)
on_trackbar(0)
k = cv2.waitKey(0)
# Exit everytime on pressing q
while k != ord('q'):
# Save image on pressing s
if k == ord('s'):
# Here go your steps after the interactive part, but before saving
# ...
filename = ' .png'.\
format(morph_texts[morphs[morph]],
slem_texts[slems[slem]],
ks).replace(' ', '_')
cv2.imwrite(filename, temp)
print('Saved image as .'.format(filename))
# Go to next image on pressing n
elif k == ord('n'):
print('Next image')
break
# Continue if any other key was pressed
k = cv2.waitKey(0)
# Actual exiting
if k == ord('q'):
break
希望代码是不言自明的。如果没有,请不要犹豫,提出问题。您应该能够轻松添加您自己额外需要的每个滑块,例如对于filters.unsharp_mask
的东西。
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
OpenCV: 4.5.1
----------------------------------------
【讨论】:
非常感谢!其实都是我一个人做的。太多的工作。但是你这个人太花哨了。需要您 rcode 进行修订。只有一个问题,如果我想应用腐蚀或膨胀左右,我应该在我的代码中哪里使用它?在sharpen
和Threshold
之间或division
和sharpen
之间?
对于您的实际问题,这更像是一个语义问题,参见。您链接的原始问题。老实说,我还没有评论过,所以我很抱歉,我不能在这里给出任何建议。
哦,好的!还有一件事,如何更改namedWindow
的大小。我使用了不同的标志,但是当我使用全屏时,我无法调整为更小的尺寸。此外,当我使用相同的窗口显示图像和跟踪栏时,我的图像尺寸会很奇怪,因为我的图像尺寸不同,无法放入窗口。
是的,在使用轨迹栏时这很烦人,但高级 GUI API 仅用于快速原型设计。您可以尝试cv2.resizeWindow
,但根据您的系统,某些标志可能有效,而另一些则无效。不幸的是,就是这样。
所以你的意思是说没有办法恢复那个小尺寸的面板?无论我使用哪个标志,它都会是全尺寸的?可以举个例子吗?以上是关于如何使用轨迹栏进行交互式图像二值化?的主要内容,如果未能解决你的问题,请参考以下文章