[Aprendizaje profundo] Proyecto de reconocimiento facial basado en una red neuronal convolucional (tensorflow) (1)

Dirección del evento: Desafío de aprendizaje de 21 días de CSDN

prefacio

Después de una investigación de hace algún tiempo, desde la introducción de los dígitos escritos a mano de LeNet-5 hasta un estudio reciente sobre el reconocimiento del clima. Quiero hacer una gran votación, porque estoy involucrado en el desarrollo de C++/Qt y estoy familiarizado con Qt, así que quiero implementar un reconocimiento facial basado en la interfaz de Qt.

Si no está familiarizado con el concepto de redes neuronales convolucionales, puede consultar este artículo: ¿Qué hace realmente la convolución?
Si desea comprender el proceso de entrenamiento de las redes neuronales, o cómo construir un entorno, puede leer este artículo: Proceso de Formación y Construcción del Entorno

pd: Hace algún tiempo, algunos amigos respondieron que aunque podían entrenar normalmente, no entendían muchas funciones, así que les presentaré todas las funciones utilizadas aquí, para que no se extiendan demasiado.

la idea basica

Los pasos específicos son los siguientes:

  1. Primero necesito recopilar datos, mi idea es llamar a la cámara a través de OpenCV para recopilar fotos de rostros.
  2. Luego realice el preprocesamiento, principalmente para clasificar el conjunto de datos, el conjunto de entrenamiento, el conjunto de validación y el conjunto de prueba. Elija los parámetros apropiados, como la función de pérdida. Imagen en escala de grises, normalización, etc.
  3. Para comenzar a entrenar el modelo, cree pares clave-valor de etiqueta con anticipación.
  4. Pruebe el efecto de reconocimiento facial, capture la foto del rostro a través de OpenCV, luego preprocese la imagen y finalmente pásela al modelo, y luego imprima el resultado del reconocimiento en la pantalla en forma de texto, y realice un ciclo hasta que ingrese q para salir.

Acerca del medio ambiente

biblioteca Versión
pitón 3.7.0
tensorflow 2.1
OpenCV 3.4.2
pyQt 5.15.7

OpenCV

OpenCV es una biblioteca de visión por computadora multiplataforma lanzada bajo la licencia BSD (código abierto) y puede ejecutarse en los sistemas operativos Linux, Windows, Android y Mac OS. Es liviano y eficiente: consta de una serie de funciones C y una pequeña cantidad de clases C ++, proporciona interfaces para lenguajes como Python, Ruby y MATLAB, e implementa muchos algoritmos comunes en procesamiento de imágenes y computadora. visión.

OpenCV está escrito en lenguaje C++, y su interfaz principal también es lenguaje C++, pero aún conserva una gran cantidad de interfaces en lenguaje C. La biblioteca también tiene extensas interfaces de Python, Java y MATLAB/OCTAVE (versión 2.5). Las funciones de la interfaz API de estos lenguajes se pueden obtener a través de la documentación en línea. Ahora también brinda soporte para C#, Ch, Ruby.

Características de OpenCV

  1. Biblioteca de visión por computadora de código abierto escrita en C/C++;
  2. El propósito de uso es desarrollar aplicaciones en tiempo real;
  3. Independiente del sistema operativo, administrador de hardware y gráficos;
  4. Con módulos generales de carga, guardado y obtención de imágenes/vídeos;
  5. Kit de desarrollo de aplicaciones con bajo y alto nivel.

Características que tiene OpenCV

  1. Operaciones sobre datos de imagen, incluida la asignación, liberación, copia, configuración y transformación de datos;
  2. Entrada y salida de imágenes y videos;
  3. Programas algorítmicos con operaciones sobre matrices y vectores y álgebra lineal;
  4. Puede operar en varias estructuras de datos dinámicas;
  5. Tener capacidades básicas de procesamiento de imágenes digitales;
  6. Se pueden analizar varias estructuras;
  7. Calibración de la cámara;
  8. análisis de movimientos;
  9. identificación de objetivos;
  10. Tiene funcionalidad GUI básica.

Instalar OpenCV

Se recomienda usar Anaconda para instalar más fácilmente.

API clave

Método de importación:import cv2

Estoy leído

Función: leer archivo de imagen
Prototipo de función: imread (nombre de archivo, banderas)
introducción de parámetros :

parámetro ilustrar
ruta de archivo Lea la ruta completa a imge
banderas Bit indicador, el formato de la imagen leída {cv2.IMREAD_COLOR, cv2.IMREAD_GRAYSCALE, cv2.IMREAD_UNCHANGED}

Aquí hay una introducción detallada a los parámetros de las banderas:

bit de bandera ilustrar
cv2.IMREAD_COLOR El parámetro predeterminado, leído en una imagen en color, ignorar el canal alfa, puede ser reemplazado por 1 como parámetro real
cv2.IMREAD_GRAYSCALE Lea en una imagen en escala de grises, puede usar 0 como argumento en su lugar
cv2.IMREAD_UNCHANGED Como su nombre lo indica, lea la imagen completa, incluido el canal alfa, que puede reemplazarse por -1 como argumento

Nota: El canal alfa, también conocido como canal A, es un canal de escala de grises de 8 bits. Este canal utiliza una escala de grises de 256 niveles para registrar la información de transparencia en la imagen y define áreas transparentes, opacas y semitransparentes, donde el negro significa transparencia total, blanco significa opaco, gris significa translúcido

ventana llamada

Función ·: Crear una nueva ventana de visualización. Se puede especificar el tipo de ventana.
Prototipo de función: void nameWindow(const string& winname,int flags = WINDOW_AUTOSIZE);
Introducción de parámetros :

parámetro ilustrar
nombre ganador el nombre de la ventana
VENTANA_AUTOSIZE La identidad de la ventana, el valor predeterminado es WINDOW_AUTOSIZE

El segundo parámetro se explica en detalle aquí:

Clasificación de logotipos ilustrar
VENTANA_AUTOSIZE El tamaño de la ventana se adapta automáticamente al tamaño de la imagen y no se puede cambiar manualmente.
VENTANA_NORMAL El usuario puede cambiar el tamaño de esta ventana
VENTANA_OPENGL OpenGL es compatible cuando se crea la ventana

Ejemplo

Al usar cv2.imshow(), si la imagen es demasiado grande, estará incompleta y no se podrá ajustar. Por lo tanto cv2.imshow(), agregue tal declaración delante de él: cv2.namedWindow('image', 0), el marco de imagen obtenido se puede cambiar de tamaño por sí mismo, y se puede estirar y ajustar libremente.
Cabe señalar aquí que los nombres de las ventanas en namedWindow e imshow deben ser iguales, de lo contrario se crearán varias ventanas.
waitKey: Indica el tiempo de espera, en milisegundos. 0 significa seguir esperando.

import cv2
import sys

img = cv2.imread("C:\\Users\\Administrator\\Desktop\\9.jpg", 1)  # 参数1:图片路径。参数2:显示原图
cv2.namedWindow("aa", 0)
cv2.imshow("aa", img)
cv2.waitKey(0) # 0表示不自动退出  如5000表示等待5秒

resultado de la operación:
inserte la descripción de la imagen aquí

cv2.Captura de video(0)

El parámetro 0 significa que la primera cámara en la computadora se usa de forma predeterminada.Si necesita leer un video existente, el parámetro se cambia a la ruta donde se encuentra el video,
como

cap=cv2.VideoCapture('video.mp4')

Clasificador en cascada

Hay 4 clasificadores en cascada entrenados con características haar en data\haarcascades bajo OpenCV:

  1. haarcascade_frontalface_alt.xml
  2. haarcascade_frontalface_alt_tree.xml
  3. haarcascade_frontalface_alt2.xml
  4. haarcascade_frontalface_default.xml
    no analiza los clasificadores en cascada aquí, y los amigos interesados ​​irán y aprenderán más sobre ellos.

En este proyecto se utiliza el clasificador haarcascade_frontalface_alt2. Agregue un clasificador a través de la función CascadeClassifier.

classfier = cv2.CascadeClassifier("./model/haarcascade_frontalface_alt2.xml")

cap.isOpened()

Determina si el objeto de video se lee correctamente y devuelve True si el objeto de video se lee correctamente y False si falla.

ok, cuadro = cap.read()

Al leer un cuadro de datos, el valor de retorno ok es de tipo booleano, si se lee correctamente devolverá True, si falla la lectura o se lee el final del vídeo devolverá False. El cuadro es la imagen de cada cuadro, donde la imagen es una matriz tridimensional, es decir cuadro.forma = (640,480,3), y la imagen leída es el BGRformato.

cv2.cvtColor(marco, cv2.COLOR_BGR2GRAY)

Función: función de conversión de espacio de color, el primer parámetro es la imagen que se convertirá y el segundo parámetro es a qué formato convertir

Introducción al formato :

Formato ilustrar
cv2.COLOR_BGR2RGB Convertir formato BGR a formato RGB
cv2.COLOR_BGR2GRAY Convertir formato BGR a imagen en escala de grises

classfier.detectMultiScale

Función : detecta todas las caras en la imagen y guarda las coordenadas y el tamaño de cada cara en un vector (representado por un rectángulo)
Prototipo de función : void detectMultiScale(const Mat& image,CV_OUT vector & objetos,factor de escala doble = 1.1,int minNeighbors = 3, int flags = 0,Size minSize = Size(),Size maxSize = Size());

Introducción de parámetros :

parámetro ilustrar
imagen La imagen a detectar es generalmente una imagen en escala de grises para acelerar la velocidad de detección;
objetos El grupo de vectores de marco rectangular del objeto detectado;
factor de escala Indica el factor de escala de la ventana de búsqueda en dos escaneos consecutivos. El valor predeterminado es 1.1, es decir, cada ventana de búsqueda se expande un 10 % por turno;
minVecinos Indica el número mínimo de rectángulos adyacentes que constituyen el objetivo de detección (3 por defecto). Si el número de pequeños rectángulos que componen el objetivo de detección y menos de min_neighbors - 1 será excluido. Si min_neighbors es 0, la función devolverá todos los rectángulos candidatos detectados sin ninguna operación.Este valor de configuración se usa generalmente en el programa de combinación definido por el usuario de los resultados de detección;
banderas Use el valor predeterminado o use CV_HAAR_DO_CANNY_PRUNING.Si se establece en CV_HAAR_DO_CANNY_PRUNING, la función usará la detección de bordes Canny para excluir áreas con demasiados o muy pocos bordes, por lo que estas áreas generalmente no son las áreas donde se encuentran las caras;
minSize和maxSize Se utiliza para limitar el alcance del área objetivo obtenida.

cv2.rectángulo

Función : Dibuja un simple, espesor especificado o rectángulo relleno por dos vértices en la diagonal.
Aquí se utiliza principalmente para enmarcar la zona del rostro.
Prototipo de función : rectángulo vacío (Mat& img, Point pt1, Point pt2, const Scalar& color, int thick=1, int lineType=8, int shift=0)

Introducción de parámetros :

parámetro ilustrar
imagen imagen.
pt1 Un vértice del rectángulo.
pt2 Otro vértice en la diagonal del rectángulo.
color 线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。
thickness 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
line_type 线条的类型。见cvLine的描述
shift 坐标点的小数点位数。

框出人脸区域
通过 OpenCV 的 Harr 分类器检测人脸,并输出识别结果(x,y,w,h)。
图片坐标以左上角为原点;
(x,y)代表人脸区域左上角坐标;
w代表人脸区域的宽度(width);
h代表人脸区域的高度(height)。

x, y, w, h = faceRect  # 原图上框出需要保存的图
color = (0, 0, 255)  # 识别出人脸后要画的边框的颜色,RGB格式

# frame 是原图,(x - 10, y - 10) 是图片的左上角的那个点,(x + w + 10, y + h + 10)是图片右下角的点 color, 2 颜色和线的宽度
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)

imwrite

功能:用于将图像保存到指定的文件,可以为各种格式的图像。
函数原型:imwrite(const String & filename,InputArray img,const std::vector & params = std::vector<int>() )
参数介绍

参数 说明
filename 需要保存图像的文件名,要保存图片为哪种格式,就带什么后缀。
img 要保存的图像。
params 表示为特定格式保存的参数编码。

编码参数:

编码 说明
IMWRITE_JPEG_QUALITY Python :cv.IMWRITE_JPEG_QUALITY 对于JPEG,它可以是从0到100的质量(越高越好)。默认值为95。
IMWRITE_JPEG_PROGRESSIVE Python:cv.IMWRITE_JPEG_PROGRESSIVE 启用JPEG功能,0或1,默认为False。
IMWRITE_JPEG_OPTIMIZE Python:cv.IMWRITE_JPEG_OPTIMIZE 启用JPEG功能,0或1,默认为False。
IMWRITE_JPEG_RST_INTERVAL Python:cv.IMWRITE_JPEG_RST_INTERVAL JPEG重启间隔,0 - 65535,默认为0 - 无重启。
IMWRITE_JPEG_LUMA_QUALITY Python:cv.IMWRITE_JPEG_LUMA_QUALITY 单独的亮度质量等级,0 - 100,默认为0 - 不使用。
IMWRITE_JPEG_CHROMA_QUALITY Python:cv.IMWRITE_JPEG_CHROMA_QUALITY 单独的色度质量等级,0 - 100,默认为0 - 不使用。
IMWRITE_PNG_COMPRESSION Python:cv.IMWRITE_PNG_COMPRESSION 对于PNG,它可以是从0到9的压缩级别。值越高意味着更小的尺寸和更长的压缩时间。如果指定,则策略更改为IMWRITE_PNG_STRATEGY_DEFAULT(Z_DEFAULT_STRATEGY)。默认值为1(最佳速度设置)。
IMWRITE_PNG_STRATEGY Python:cv.IMWRITE_PNG_STRATEGY 其中一个品种:: ImwritePNGFlags,默认为IMWRITE_PNG_STRATEGY_RLE。
IMWRITE_PNG_BILEVEL Python:cv.IMWRITE_PNG_BILEVEL 二进制级别PNG,0或1,默认为0。
IMWRITE_PXM_BINARY Python:cv.IMWRITE_PXM_BINARY 对于PPM,PGM或PBM,它可以是二进制格式标志,0或1.默认值为1。
IMWRITE_WEBP_QUALITY Python:cv.IMWRITE_WEBP_QUALITY 覆盖EXR存储类型(默认为FLOAT(FP32))对于WEBP,它可以是1到100的质量(越高越好)。默认情况下(不带任何参数),如果质量高于100,则使用无损压缩。
IMWRITE_PAM_TUPLETYPE Python:cv.IMWRITE_PAM_TUPLETYPE 对于PAM,将TUPLETYPE字段设置为为格式定义的相应字符串值。
IMWRITE_TIFF_RESUNIT Python:cv.IMWRITE_TIFF_RESUNIT 对于TIFF,用于指定要设置的DPI分辨率单位; 请参阅libtiff文档以获取有效值。
IMWRITE_TIFF_XDPI Python:cv.IMWRITE_TIFF_XDPI 对于TIFF,用于指定X方向DPI。
IMWRITE_TIFF_YDPI Python:cv.IMWRITE_TIFF_YDPI 对于TIFF,用于指定Y方向DPI。
IMWRITE_TIFF_COMPRESSION Python:cv.IMWRITE_TIFF_COMPRESSION 对于TIFF,用于指定图像压缩方案。请参阅libtiff以获取与压缩格式对应的整数常量。注意,对于深度为CV_32F的图像,仅使用libtiff的SGILOG压缩方案。对于其他支持的深度,可以通过此标志指定压缩方案; LZW压缩是默认值。
IMWRITE_JPEG2000_COMPRESSION_X1000 Python:cv.IMWRITE_JPEG2000_COMPRESSION_X1000 对于JPEG2000,用于指定目标压缩率(乘以1000)。该值可以是0到1000.默认值是1000。

rectangle

功能:是在图像上绘制一个简单的矩形
函数原型:cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])

参数介绍

参数 说明
img 图片路径
pt1 和 pt2 Representan la esquina superior izquierda y la esquina inferior derecha del rectángulo, respectivamente, y el eje de coordenadas x es horizontal y el eje de coordenadas y es vertical. (Cuando x o y de la coordenada pt1 es mayor que x o y de la coordenada pt2, los parámetros pt1 y pt2 representan las esquinas inferior izquierda y superior derecha del rectángulo respectivamente, y tanto pt1 como pt2 deben ser números enteros)
color El color del borde del rectángulo debe tenerse en cuenta que los tres (0, 0, 255) aquí corresponden a BGR respectivamente
espesor Si el grosor del borde del rectángulo es negativo, como CV_FILLED, significa que se debe llenar todo el rectángulo.
tipo de línea Canal de algoritmo
cambio Número de lugares decimales en las coordenadas del punto

cv2.FONT_HERSHEY_SIMPLEX

Jaja, esto es principalmente para mostrar cuántas imágenes de rostros se capturan actualmente, de modo que cuando esté parado allí y sea fotografiado, tenga una buena idea y no tenga que esperar con una mancha de ojos negros.

cv2.putText

Función : agregar texto a la imagen
Prototipo de función : cputText (img, text, org, fontFace, fontScale, color, thick=Ninguno, lineType=Ninguno, bottomLeftOrigin=Ninguno):

Introducción de parámetros :

parámetro ilustrar
imagen imagen
texto texto para agregar
organización La posición donde se agrega el texto a la imagen.
Perfil delantero tipo de fuente
fontScale tamaño de fuente
color color de fuente
grosorPeso de fuente

palabra()

Función: Devuelve el valor ascii de un carácter. Aquí para entrada q finaliza activa.

código

# coding: utf-8

import cv2
import sys

def catch_usb_video(window_name, camera_idx):
    '''使用cv2.imshow()的时候,如果图片太大,会显示不全并且无法调整。
    因此在cv2.imshow()的前面加上这样的一个语句:cv2.namedWindow('image', 0),
    得到的图像框就可以自行调整大小,可以拉伸进行自由调整。'''
    cv2.namedWindow(window_name, 0)

    # 视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
    cap = cv2.VideoCapture(camera_idx)

    # 告诉OpenCV使用人脸识别分类器  级联分类器
    '''
    Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为三类:边缘特征、线性特征、中心特征和对角线特征。
    '''
    classfier = cv2.CascadeClassifier("./model/haarcascade_frontalface_alt2.xml")
    # 识别出人脸后要画的边框的颜色,RGB格式
    color = (0, 0, 255)
    num = 0
    while cap.isOpened():
        ok, frame = cap.read()  # 读取一帧数据
        if not ok:
            break
            # 将当前帧转换成灰度图像
        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
        faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
        #  faceRects = [405 237 222 222]
        if len(faceRects) > 0:  # 大于0则检测到人脸
            for faceRect in faceRects:  # 单独框出每一张人脸
                # 在原图上框出需要保存的图
                x, y, w, h = faceRect
                cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
                # 将当前帧保存为图片
                # frame 是原图,(x - 10, y - 10) 是图片的左上角的那个点,(x + w + 10, y + h + 10)是图片右下角的点
                # color, 2 颜色和线的宽度
                img_name = '%s/%d.jpg' % ('./deep_learning/zhangmeng', num)
                image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
                cv2.imwrite(img_name, image)
                num += 1
                if num > (500):  # 如果超过指定最大保存数量退出循环
                    break
            # 画出矩形框
            cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
            # 显示当前捕捉到了多少人脸图片了,这样站在那里被拍摄时心里有个数,不用两眼一抹黑傻等着
            font = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(frame, 'num:%d' % (num), (x + 30, y + 30), font, 1, (255, 0, 255), 4)
            # 超过指定最大保存数量结束程序
        if num > (500):
            break
        # 显示图像
        cv2.imshow(window_name, frame)
        c = cv2.waitKey(1)
        if c & 0xFF == ord('q'):
            break
    # 释放摄像头并销毁所有窗口
    cap.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    catch_usb_video("face", 0)

resultado de la operación

Un amigo mío protagonizó una prueba de identificación
inserte la descripción de la imagen aquí

Aquí también puede ver que las imágenes se guardan normalmente.
inserte la descripción de la imagen aquí

Resumir

Así que el primer paso está hecho aquí. En este momento, la mayor dificultad que siento es entender algunas funciones de la API relacionadas con OpenCV. No hay otras tecnologías excesivas diseñadas.

Supongo que te gusta

Origin blog.csdn.net/qq_45254369/article/details/126376276
Recomendado
Clasificación