【问题标题】:Matplotlib RectangleSelector keeps saving old valuesMatplotlib RectangleSelector 不断保存旧值
【发布时间】:2019-10-13 15:49:19
【问题描述】:

我正在尝试为图像制作边界框工具。我希望该工具首先让我使用矩形选择器绘制边界框,然后在调整边界框之后。如果我按“w”,我希望将边界框坐标保存在 python 列表中。这是我的代码:

def line_select_callback(clk, rls):
    global tl_list
    global br_list
    global object_list
    global class_list
    plt.connect('key_press_event', set_class)    
    tx = int(clk.xdata)
    ty = int(clk.ydata)
    bx = int(rls.xdata)
    by = int(rls.ydata)

    plt.connect('key_press_event', lambda event: set_final(event, tx, ty, bx, by))


def toggle_selector(event):
    toggle_selector.RS.set_active(True)

def set_class(event):
    global clas

    if event.key == '1':
        clas = '0'
        print('class set to 0')
    elif event.key == '2':
        print('class set to 1')
        clas = '1'

def set_final(event, tx, ty, bx, by):
    global object_list
    global class_list

    if event.key == 'w':
        tl_list.append((tx, ty))
        br_list.append((bx, by))
        class_list.append(clas)

if __name__ == '__main__':
    print('Default class set to 0')
    for n, image_file in enumerate(os.scandir(image_folder)):
        img = image_file
        fig, ax = plt.subplots(1)
        image = cv2.imread(image_file.path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        ax.imshow(image)

        toggle_selector.RS = RectangleSelector(ax, line_select_callback,
                                                drawtype='box', useblit=False,
                                                button=[1], minspanx=5, minspany=5,
                                                spancoords='pixels', interactive=True )

        bbox = plt.connect('key_press_event', toggle_selector)
        key = plt.connect('key_press_event', onkeypress)
        plt.show()

问题是。当我保存新的边界框时,旧的框也会被保存。假设我在图像上绘制了 3 个框。保存的坐标如下:

{296,181,417,373,0} {235,178,447,370,0} {296,181,417,373,0} {235,178,447,370,0} {77,125,207,319,0} {296,181,417,373,0 }

第一个盒子保存3次,第二个盒子保存2次,最后一个盒子保存1次。如何解决?

【问题讨论】:

  • 您在程序中使用了 opencv。您应该考虑使用cv2.selectROI。此功能允许您选择矩形。我认为这更容易使用。
  • Here 就是一个例子。它解释了 C++ 和 python 示例。
  • 谢谢@Aditya,我不知道。
  • 这很混乱。最好只连接一个按键事件。完成后断开连接。
  • 感谢@ImportanceOfBeingErnest。我已经修复并发布了解决方案。

标签: python matplotlib plot computer-vision


【解决方案1】:

找到了一个简单的解决方法。完成边界框调整后,按“n”保存当前边界框并继续在同一图像上绘制新边界框。为图像制作边界框后,按“q”加载下一张图像。以下代码可以修改为YOLO等项目的标注工具。

import os
import matplotlib.pyplot as plt
import cv2
from matplotlib.widgets import RectangleSelector
import matplotlib.patches as patches

Xs = []
Ys = []
breaker = False
tx=0
ty=0
bx=0
by=0

p_tx=0
p_ty=0
p_bx=0
p_by=0

# constants
image_folder = 'images'

def line_select_callback(clk, rls):
    global tx,ty,bx,by
    tx = int(clk.xdata)
    ty = int(clk.ydata)
    bx = int(rls.xdata)
    by = int(rls.ydata)


def onkeypress(event):
    global tx,ty,bx,by, Xs, Ys, p_tx, p_ty, p_bx, p_by
    if event.key == 'n':            
        if (p_tx != tx) or (p_ty != ty) or (p_bx != bx) or (p_by != by):
            Xs.append((tx, bx))
            Ys.append((ty, by))
            mystr=""
            mystr += " " + str(tx)+","+str(ty)+","+str(bx)+","+str(by)+" "
            print(mystr)
            p_tx=tx
            p_ty=ty
            p_bx=bx
            p_by=by
            plt.close()


def toggle_selector(event):
    toggle_selector.RS.set_active(True)

def break_loop(event):
    global breaker
    if event.key == 'q':
        breaker = True

if __name__ == '__main__':
    for n, image_file in enumerate(os.scandir(image_folder)):        
        while(True):
            img = image_file
            fig, ax = plt.subplots(1)
            image = cv2.imread(image_file.path)
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            ax.imshow(image)

            for i in range(len(Xs)):
                tl_x, br_x= Xs[i]
                tl_y , br_y = Ys[i]
                rect = patches.Rectangle((tl_x,tl_y), abs(br_x - tl_x), abs(tl_y - br_y),linewidth=1,edgecolor='r',facecolor='none')
                ax.add_patch(rect)

            toggle_selector.RS = RectangleSelector(ax, line_select_callback,
                                                    drawtype='box', useblit=False,
                                                    button=[1], minspanx=5, minspany=5,
                                                    spancoords='pixels', interactive=True)

            bbox = plt.connect('key_press_event', toggle_selector)
            plt.connect('key_press_event', onkeypress)
            loopBreaker = plt.connect('key_press_event', break_loop)
            if breaker:
                break
            plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多