如何使用轨迹栏进行交互式图像二值化?

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.namedWindowcv2.createTrackbarcv2.getTrackbarPos,以便我可以设置radiusamountkernel 的值,膨胀,腐蚀等,通过使用以下函数。

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 进行修订。只有一个问题,如果我想应用腐蚀或膨胀左右,我应该在我的代码中哪里使用它?在sharpenThreshold 之间或divisionsharpen 之间? 对于您的实际问题,这更像是一个语义问题,参见。您链接的原始问题。老实说,我还没有评论过,所以我很抱歉,我不能在这里给出任何建议。 哦,好的!还有一件事,如何更改namedWindow 的大小。我使用了不同的标志,但是当我使用全屏时,我无法调整为更小的尺寸。此外,当我使用相同的窗口显示图像和跟踪栏时,我的图像尺寸会很奇怪,因为我的图像尺寸不同,无法放入窗口。 是的,在使用轨迹栏时这很烦人,但高级 GUI API 仅用于快速原型设计。您可以尝试cv2.resizeWindow,但根据您的系统,某些标志可能有效,而另一些则无效。不幸的是,就是这样。 所以你的意思是说没有办法恢复那个小尺寸的面板?无论我使用哪个标志,它都会是全尺寸的?可以举个例子吗?

以上是关于如何使用轨迹栏进行交互式图像二值化?的主要内容,如果未能解决你的问题,请参考以下文章

二值化处理与边缘检测

如何用C语言实现对图像的二值化?

matlab怎么二值化

图像灰度化、二值化理解

图像二值化后里面有白点,怎么去除

对图像进行二值化的处理方法,求源代码,最好是C++/C或者OPENCV