Recorte dinámico de imágenes

1. Antecedentes

Tomando como ejemplo el modelo en cascada de dos niveles, el modelo de detección de objetivos de primer nivel se usa para detectar personas, y el modelo de detección de objetivos de segundo nivel se usa para detectar teléfonos móviles, walkie-talkies, etc. Luego, durante el proceso real de recopilación de datos, los dispositivos como los teléfonos móviles y los walkie-talkies no se encuentran en el marco de detección de personal de primer nivel, por lo que hay menos muestras para el entrenamiento del modelo de segundo nivel .

En la fase de entrenamiento del modelo de detección de objetivos secundarios, al muestrear datos, no solo debemos usar la imagen recortada del cuadro de detección de objetivos principal como entrada, sino que también debemos recortar dinámicamente la imagen original para incluir dispositivos como teléfonos móviles y walkie. -talkies para reducir la interferencia de fondo.
ingrese la imagen original
Área de marco de destino de primer nivelROI área de interés
Las tres imágenes anteriores son la imagen original, el área del marco de detección del objetivo de primer nivel y el área objetivo deseada durante el entrenamiento (es necesario incluir otros teléfonos móviles).

Idea básica: según el evento del mouse de opencv, dibuje un marco rectangular en la imagen original para obtener el área de interés y guárdelo.

2. Evento de ratón OpenCV

2.1 Establecer eventos de ratón

setMouseCallback(const String & 	winname,  #要设置鼠标事件的窗口名
				 MouseCallback 	onMouse,      #回调函数,当指定窗口产生鼠标事件时,调用的函数名
				 void* userdata = 0)          #传递给回调函数的可选参数

2.2 Prototipo de función de devolución de llamada

void MouseCallback(int event,        #鼠标基础事件
             int x, int y,           #鼠标在x轴y轴方向上的坐标值,窗口左上角为原点(0,0)
             int flags,              #flags的值代表鼠标拖拽事件和Ctrl、Shift、Alt按键事件的代号
             void *userdata)         #用户数据

2.3 Eventos de ratón

2.3.1 evento evento básico

Esto corresponde al primer evento de parámetro de la función de llamada. Cuando el mouse realiza la acción correspondiente, el evento se convertirá en el valor correspondiente.

enum
{
    
    
    CV_EVENT_MOUSEMOVE      =0,   //鼠标移动
    CV_EVENT_LBUTTONDOWN    =1,   //按下左键
    CV_EVENT_RBUTTONDOWN    =2,   //按下右键
    CV_EVENT_MBUTTONDOWN    =3,   //按下中键
    CV_EVENT_LBUTTONUP      =4,   //放开左键
    CV_EVENT_RBUTTONUP      =5,   //放开右键
    CV_EVENT_MBUTTONUP      =6,   //放开中键
    CV_EVENT_LBUTTONDBLCLK  =7,   //左键双击
    CV_EVENT_RBUTTONDBLCLK  =8,   //右键双击
    CV_EVENT_MBUTTONDBLCLK  =9,   //中键双击
    CV_EVENT_MOUSEWHEEL     =10,  //滚轮滚动
    CV_EVENT_MOUSEHWHEEL    =11   //横向滚轮滚动
};

2.3.2 evento de arrastre de bandera

Esto corresponde al cuarto parámetro de la función de devolución de llamada.Cuando hay un arrastre del mouse o una combinación de CTRL, shift y ALT, la bandera se convierte en el valor correspondiente.

 
enum
{
    
    
    CV_EVENT_FLAG_LBUTTON   =1,   //左键拖拽
    CV_EVENT_FLAG_RBUTTON   =2,   //右键拖拽
    CV_EVENT_FLAG_MBUTTON   =4,   //中键拖拽
    CV_EVENT_FLAG_CTRLKEY   =8,   //按住CTRL拖拽
    CV_EVENT_FLAG_SHIFTKEY  =16,  //按住Shift拖拽
    CV_EVENT_FLAG_ALTKEY    =32   //按住ALT拖拽
};
在这里插入代码片

3. Recorte dinámico de imágenes

El código de implementación específico es el siguiente:

import cv2
import os

ROOT = "data7"		# 原图路径

img_cnt = 0

def mouse_callback(event, x, y, flags, param):
    global img_data, point1, point2,g_rect, img_cnt
    img2 = img_data.copy()
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击,则在原图打点
        print("1-EVENT_LBUTTONDOWN")
        point1 = (x, y)
        cv2.circle(img2, point1, 10, (0, 255, 0), 5)
        cv2.imshow('image', img2)
 
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳,画框
        print("2-EVENT_FLAG_LBUTTON")
        cv2.rectangle(img2, point1, (x, y), (255, 0, 0), thickness=2)
        cv2.imshow('image', img2)
 
    elif event == cv2.EVENT_LBUTTONUP:  # 左键释放,显示
        print("3-EVENT_LBUTTONUP")
        point2 = (x, y)
        cv2.rectangle(img2, point1, point2, (0, 0, 255), thickness=2)
        cv2.imshow('image', img2)
        if point1!=point2:
            min_x = int(min(point1[0], point2[0]))
            min_y = int(min(point1[1], point2[1]))
            width = int(abs(point1[0] - point2[0]))
            height = int(abs(point1[1] - point2[1]))
            g_rect=[min_x,min_y,width,height]
            cut_img = img_data[min_y:min_y + height, min_x:min_x + width]   # 从原图上裁剪
            cv2.imwrite("crop_img_{}.jpg".format(img_cnt), cut_img)         # 图像文件保存
            print("save image.")
            img_cnt += 1


if __name__ == "__main__":
    img_lists = os.listdir(ROOT)

    cv2.namedWindow("image")
    cv2.setMouseCallback("image", mouse_callback)


    for img in img_lists:
        img_path = os.path.join(ROOT, img)
        if os.path.exists(img_path):
            print("file existed.")
        img_data = cv2.imread(img_path)

        cv2.imshow("image", img_data)
        k = cv2.waitKey(0)

        if k == ord('q'):
            break

cv2.destroyAllWindows()

Los pasos generales son los siguientes:

  1. Cree una nueva ventana y configure la función de devolución de llamada;
  2. Leer y mostrar datos de imágenes sin procesar;
  3. Capture los eventos del mouse de clic izquierdo, arrastre con clic izquierdo y liberación de clic izquierdo, y dibuje el marco de destino del área;
  4. Y guarde el objetivo del área;

4. Resumen

Este artículo presenta principalmente una solución para el caso del modelo en cascada de dos niveles cuando las muestras de entrenamiento del algoritmo de detección de objetivos de segundo nivel son pequeñas. A través del script anterior, el área de recorte artificial se puede visualizar y las muestras de entrenamiento se pueden guardar en reducir la interferencia de fondo.

Supongo que te gusta

Origin blog.csdn.net/hello_dear_you/article/details/130681226
Recomendado
Clasificación