A2A’d …
Solo he trabajado en OpenCV recientemente … ha pasado un tiempo desde que codifiqué seriamente en MATLAB. También abordo el reconocimiento de imágenes desde un fondo de minería de datos / ML … así que solo puedo sugerir un enfoque en estos dominios. Un verdadero experto en OCR probablemente le dará una mejor respuesta.
Mi técnica general es:
- ¿Será la Universidad de Gotemburgo un buen lugar para estudiar el procesamiento del lenguaje natural con CLASP en camino?
- ¿Qué temas de matemáticas recomienda Conner Davis a alguien interesado en el aprendizaje automático teórico para aprender en su tiempo libre?
- ¿Se están utilizando redes neuronales profundas para crear estrategias de fondos de cobertura / HFT?
- ¿Cuál es el código de aprendizaje automático más pequeño que se podría escribir en Java?
- Si ya hemos conocido una función, ¿podemos generar una red neuronal para la inferencia, sin pasar por el proceso de capacitación que consume tiempo y energía?
1.) Preproceso
2.) Extraer características
3.) Clasificar
–
Preprocesamiento
Estandarice las imágenes por escala y ubicación. Por ejemplo:
Ahora, creo que tienes una opción aquí. Puede extraer características en este punto O puede probar una idea más nueva con respecto al preprocesamiento de imágenes y luego extraer características. Analicemos primero esta nueva idea. Algunas personas muy inteligentes han sugerido distorsionar su conjunto de entrenamiento antes de intentar clasificar los personajes. La idea se presenta aquí: Página en arxiv.org.
Básicamente, creas copias distorsionadas de cada dígito en tu conjunto de entrenamiento de esta manera:
Agregar ruido aleatorio o “jitter” a la imagen es lo mismo que agregar regularización L2 (también conocida como disminución de peso) a su clasificador, que en mi experiencia, aumenta la solidez de la clasificación. Supongo que introducir la rotación en el conjunto de entrenamiento hace que su clasificador sea más robusto para las imágenes rotadas. (Por supuesto, simplemente puede escribir código para normalizar sus datos para la rotación, pero he tenido mejores resultados al agregar estas imágenes distorsionadas a mi conjunto de entrenamiento). He pegado un código Python (probablemente malo) a continuación para normalizar y luego distorsionar las imágenes de entrenamiento abajo.
–
EXTRACCIÓN DE CARACTERÍSTICAS
Ya sea que decida aumentar su conjunto de entrenamiento con imágenes distorsionadas o no, es probable que desee extraer características de las imágenes antes de intentar clasificarlas.
OpenCV ofrece varias técnicas de extracción de características:
Detección de características y descripción
También puede probar técnicas de descomposición de matriz como PCA y NMF para la extracción de características. Estos se implementan en la biblioteca de aprendizaje Python scikit que funciona bastante bien con Python OpenCV.
2.5. Descomposición de señales en componentes (problemas de factorización matricial)
–
CLASIFICACION DE IMAGEN
Ahora que sus imágenes han sido preprocesadas y convertidas en un número manejable de entradas de intervalo mediante extracción de características, puede usar una técnica de aprendizaje supervisado para clasificar sus imágenes.
OpenCV contiene muchas buenas técnicas de clasificación supervisadas:
Aprendizaje automático
ml. Aprendizaje automático
Así aprende scikit:
1. Aprendizaje supervisado
Si quieres probar técnicas de clasificación de aprendizaje profundo, busca en Theano:
Bienvenido – Documentación de Theano 0.6
Personalmente, soy fanático de las redes neuronales de SAS. Han sido ampliamente utilizados en la industria durante décadas. Son muy escalables, mucho más que MATLAB, robustos y confiables. También son muy caros, pero la mayoría de las grandes instituciones de investigación y corporativas otorgan licencias a SAS. (SAS también es mi empleador …).
Tengo un código vinculado a este documento para construir redes neuronales profundas en SAS: Página en sas.com
–
EJEMPLO DE CÓDIGO DE PREPROCESO
### IMPORTACIONES ############################################## ######################
importar os
importar cv2
importar csv
importar numpy
matemáticas de importación
### ARGS OPERACIONALES ############################################# ##############
### MODO DEPURACIÓN: IMPRIME EL NÚMERO DE IMÁGENES ESPECIFICADAS POR BEDUG_CUTOFF
DEPURACIÓN = Falso
DEBUG_CUTOFF = 10
### MODO DE TREN
TREN = Verdadero # AGREGA ETIQUETAS A LA PRIMERA COLUMNA
NORMALIZE_ONLY = False # NO AGREGA REGISTROS DISTORTADOS
### IO LOCATION – FILE_IN AND FILE_OUT DEBE ESTAR EN DIR
DIR = ‘C: / Ruta / a / digitsData’
FILE_IN = ‘train.csv’
FILE_OUT = ‘train_augmented.csv’
### NÚMEROS MÁGICOS GLOBALES PARA IMÁGENES … LO SÉ, OK … #########################
INPUT_SIZE = (28, 28) # TAMAÑO DE LA IMAGEN DE ENTRADA, 2-TUPLE
OUT_SIZE = (27, 27) # TAMAÑO DE LA IMAGEN DE SALIDA, 2-TUPLE
NORM_SIZE = (21, 21) # TAMAÑO FINAL DE LA CAJA DE LÍMITES PARA IMÁGENES NORMALIZADAS, 2-TUPLE, <OUT_SIZE
NORM_EXPAND_SIZE = int ((27-NORM_SIZE [0]) / 2)
LARGE_SIZE = (25,25) # TAMAÑO FINAL DE LA CAJA DE LÍMITES PARA IMÁGENES AMPLIADAS, 2-TUPLE, <OUT_SIZE
LARGE_EXPAND_SIZE = int ((27-LARGE_SIZE [0]) / 2)
RAND_PERCENT = .15 # INYECCIÓN DE RUIDO, <1.0
RAND_THRESHOLD = int (OUT_SIZE [0] * OUT_SIZE [0] * RAND_PERCENT)
GRADO = 15 # GRADO DE ROTACIÓN
### MÁS COMPLICADO …
# CONVERTIR UN NÚMERO 1, 7 U OTRO SKINNY EN UN CUADRADO DURANTE LA NORMALIZACIÓN ES DUMB
# EVITE HACERLO, NO VUELVA A AJUSTAR LOS NÚMEROS CUYA DEJÓ MÁS PÍXELES SE ENCUENTRA
# EN UN ÍNDICE> = A SKINNY_THRESHOLD
SKINNY_THRESHOLD = 10
# DIFÍCIL DE VER (Y POR LO TANTO PRUEBA) LA CAJA DE LÍMITES SIN ESTO, 0-255
TO_BLACK_THRESHOLD = 50
### ESCRIBIR IMAGEN PARA GRABAR ########################################### ###########
def write_image_to_record (src, out_csv, row_label = Ninguno):
out = numpy.array (src) .flatten ()
if (row_label! = None): out = numpy.insert (out, 0, row_label)
out_csv.writerow (fuera)
### NORMALIZAR ESCALA ############################################# ###############
def normalize_scale (src, out_size = OUT_SIZE, norm_size = NORM_SIZE, \
norm_expand_size = NORM_EXPAND_SIZE, skinny_threshold = SKINNY_THRESHOLD, \
to_black_threshold = TO_BLACK_THRESHOLD):
src [src <to_black_threshold] = 0
bottom, top = numpy.min (numpy.nonzero (src) [0]), numpy.max (numpy.nonzero (src) [0])
izquierda, derecha = numpy.min (numpy.nonzero (src.T) [0]), numpy.max (numpy.nonzero (src.T) [0])
bounding_box = src [abajo: arriba + 1, izquierda: derecha + 1]
if (left> = skinny_threshold): skinny = True
más: flaco = Falso
si es delgado: devuelve cv2.resize (src, (out_size))
más:
norma = cv2.resize (bounding_box, (norm_size))
return cv2.copyMakeBorder (norm, norm_expand_size, norm_expand_size, norm_expand_size, norm_expand_size, 0)
### RUIDO DE INYECCIÓN ############################################# ##################
def inject_noise (src, out_size = OUT_SIZE, rand_threshold = RAND_THRESHOLD):
ruido = numpy.copy (src) # COPIA PROFUNDA NECESARIA
ruido [numpy.random.randint (out_size [0] -1, tamaño = rand_threshold), numpy.random.randint (out_size [0] -1, tamaño = rand_threshold)] = 0
ruido de retorno
### AMPLIAR ############################################## ######################
def enlarge (src, skinny_threshold = SKINNY_THRESHOLD, input_size = INPUT_SIZE, \
out_size = OUT_SIZE, large_size = LARGE_SIZE, large_expand_size = LARGE_EXPAND_SIZE):
bottom, top = numpy.min (numpy.nonzero (src) [0]), numpy.max (numpy.nonzero (src) [0])
izquierda, derecha = numpy.min (numpy.nonzero (src.T) [0]), numpy.max (numpy.nonzero (src.T) [0])
bounding_box = src [abajo: arriba + 1, izquierda: derecha + 1]
if (left> = skinny_threshold): skinny = True
más: flaco = Falso
si (flaco):
tall_bounding_box = src [bottom-1: top + 2, 0: input_size [0] -1]
return cv2.resize (tall_bounding_box, (out_size))
más:
large = cv2.resize (bounding_box, large_size)
return cv2.copyMakeBorder (large, large_expand_size, large_expand_size, large_expand_size, large_expand_size, 0)
### ROTAR (Y TRADUCIR) ########################################## ###########
def rotate_about_center (src, angle, scale = 1.):
w = src.shape [1]
h = src.shape [0]
rangle = numpy.deg2rad (ángulo) # ANGLE IN RADS
# CALCULAR NUEVAS DIMENSIONES DE IMAGEN
nw = (abs (numpy.sin (rangle) * h) + abs (numpy.cos (rangle) * w)) * scale
nh = (abs (numpy.cos (rangle) * h) + abs (numpy.sin (rangle) * w)) * escala
# OBTENER MATRIZ DE ROTACIÓN
rot_mat = cv2.getRotationMatrix2D ((nw * 0.5, nh * 0.5), ángulo, escala)
# CENTROS ANTIGUOS Y NUEVOS COMBINADOS CON ROTACIÓN
rot_move = numpy.dot (rot_mat, numpy.array ([(nw-w) * 0.5, (nh-h) * 0.5,0]))
# ACTUALIZAR TRADUCCIÓN
rot_mat [0,2] + = rot_move [0]
rot_mat [1,2] + = rot_move [1]
return cv2.warpAffine (src, rot_mat, (int (math.ceil (nw)), int (math.ceil (nh))), flags = cv2.INTER_LANCZOS4)
def main ():
### IO
file_in = open (DIR + ‘/’ + FILE_IN, ‘rb’)
im_in_csv = csv.reader (file_in, dialect = ‘excel’)
file_out = open (DIR + ‘/’ + FILE_OUT, ‘wb’)
im_out_csv = csv.writer (file_out, dialect = ‘excel’)
para i, fila en enumerate (im_in_csv):
si i> 0: # ROW 0 ES SOLO ETIQUETAS
imprimir ‘Procesando imagen’ + str (i) + ‘…’
### GUARDAR ETIQUETA Y LEER LA FILA EN LA IMAGEN
row_array = numpy.asarray (fila)
row_array = row_array.astype (numpy.float32)
row_label = Ninguno
si (TREN):
row_label = row_array [0]
img = numpy.reshape (row_array [1:], (INPUT_SIZE))
más:
img = numpy.reshape (row_array, (INPUT_SIZE))
#if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘raw’ + str (i) + ‘.jpg’, img)
### NORMALIZAR ESCALA
norma = normalizar_escala (img)
write_image_to_record (norma, im_out_csv, row_label)
if (DEPURACIÓN): cv2.imwrite (DIR + ‘/’ + ‘norm’ + str (i) + ‘.jpg’, norm)
if (NORMALIZE_ONLY): continuar
si (TREN):
ruido = ruido_inyectar (norma)
write_image_to_record (noise, im_out_csv, row_label)
if (DEPURACIÓN): cv2.imwrite (DIR + ‘/’ + ‘noise’ + str (i) + ‘.jpg’, noise)
grande = agrandar (norma)
#if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘large’ + str (i) + ‘.jpg’, large)
ruido_grande = agrandar (ruido)
#if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘large_noise’ + str (i) + ‘.jpg’, large_noise)
# rotar + grados
plus = cv2.resize (rotate_about_center (grande, GRADO), OUT_SIZE)
write_image_to_record (plus, im_out_csv, row_label)
if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘rotate_p’ + str (DEGREE) + ‘_’ + str (i) + ‘.jpg’, más)
plus_noise = cv2.resize (rotate_about_center (large_noise, DEGREE), OUT_SIZE)
write_image_to_record (plus_noise, im_out_csv, row_label)
if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘rotate_noise_p’ + str (DEGREE) + ‘_’ + str (i) + ‘.jpg’, plus_noise)
# rotar – grados
menos = cv2.resize (rotate_about_center (grande, -DEGREE), (OUT_SIZE))
write_image_to_record (minus, im_out_csv, row_label)
if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘rotate_m’ + str (DEGREE) + ‘_’ + str (i) + ‘.jpg’, menos)
menos ruido = cv2.resize (rotate_about_center (large_noise, -DEGREE), (OUT_SIZE))
write_image_to_record (minus_noise, im_out_csv, row_label)
if (DEBUG): cv2.imwrite (DIR + ‘/’ + ‘rotate_noise_m’ + str (DEGREE) + ‘_’ + str (i) + ‘.jpg’, minus_noise)
si (DEPURACIÓN):
if (i> = DEBUG_CUTOFF):
descanso
más: im_out_csv.writerow (fila [0: OUT_SIZE [0] * OUT_SIZE [0] +1]) # ESCRIBE ETIQUETAS DE LA FILA
file_in.close ()
file_out.close ()
imprimir ‘Listo’
if __name__ == “__main__”:
principal()