Procesamiento de imágenes OpenCV

Procesamiento De Imagenes Opencv



Vamos a estudiar los métodos de procesamiento de imágenes en este artículo. Examinaremos algunos temas fundamentales pero críticos en la visión artificial y el aprendizaje automático. Estas técnicas fundamentales de procesamiento de imágenes pueden resolver problemas complejos, como conjuntos de datos. Como resultado, hay seis pasos fundamentales en el procesamiento de imágenes, que se enumeran a continuación:
  1. Traducción de imágenes
  2. Rotacion de imagen
  3. Aritmética de imágenes
  4. Volteo de imagen
  5. Recorte de imagen
  6. Cambio de tamaño de imagen

Ahora, explicaremos en detalle todos los temas de procesamiento de imágenes mencionados anteriormente.

1. Traducción de imágenes

La traducción de imágenes es un método de procesamiento de imágenes que nos ayuda a mover la imagen a lo largo de los ejes x e y. Podemos mover la imagen hacia arriba, abajo, derecha, izquierda o cualquier combinación.







Podemos definir la Matriz de Traducción con el símbolo M, y podemos representarla en forma matemática, como se muestra a continuación:





Podemos entender el concepto de la imagen de traducción a través de este programa.





código pitón: Mantendremos el nombre del siguiente programa como translate.py .

# importar paquetes requeridos

importar entumecido como p.ej.

importar análisis de argumentos

importar imutil

importar cv2

# implementamos el analizador de argumentos

ap_obj = análisis de argumentos Analizador de argumentos ( )

ap_obj. añadir_argumento ( '-k' , '--imagen' , requerido = Verdadero ,

ayudar = 'ubicación del archivo de imagen' )

argumentos = cuyo ( ap_obj. parse_args ( ) )

# cargar la imagen y mostrar en la pantalla

imagen = cv2. Estoy leído ( argumentos [ 'imagen' ] )

cv2. immostrar ( 'Imagen original' , imagen )

# La traducción de la imagen es una matriz NumPy que se muestra a continuación:

# [[1, 0, turnoX], [0, 1, turnoY]]

# Vamos a utilizar la matriz NumPy anterior para desplazar las imágenes a lo largo de la

# Direcciones del eje x y del eje y. Para esto, simplemente tenemos que pasar los valores de los píxeles.

# En este programa moveremos la imagen 30 pixeles a la derecha

# y 70 píxeles hacia la parte inferior.

traducción_mat = p.ej. flotar32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

traducción_imagen = cv2. deformación ( imagen , traducción_mat ,

( imagen. forma [ 1 ] , imagen. forma [ 0 ] ) )

cv2. immostrar ( 'Traducción de imágenes hacia abajo y hacia la derecha' , traducción_imagen )

# ahora, vamos a usar la matriz NumPy anterior para desplazar las imágenes a lo largo de la

# Direcciones del eje x (izquierda) y del eje y (arriba).

# Aquí, vamos a mover las imágenes 50 píxeles a la izquierda

# y 90 píxeles hacia arriba.

traducción_mat = p.ej. flotar32 ( [ [ 1 , 0 , - 50 ] , [ 0 , 1 , - 90 ] ] )

traducción_imagen = cv2. deformación ( imagen , traducción_mat ,

( imagen. forma [ 1 ] , imagen. forma [ 0 ] ) )

cv2. immostrar ( 'Traducción de imágenes arriba y a la izquierda' , traducción_imagen )

cv2. esperarClave ( 0 )

Líneas 1 a 5: Estamos importando todos los paquetes necesarios para este programa, como OpenCV, argparser y NumPy. Tenga en cuenta que hay otra biblioteca que es imutils. Este no es un paquete de OpenCV. Esta es solo una biblioteca que mostrará fácilmente el mismo procesamiento de imagen.



La biblioteca imutils no se incluirá automáticamente cuando instalemos OpenCV. Entonces, para instalar los imutils, tenemos que usar el siguiente método:

pip instalar imutils

Líneas 8 a 15: Creamos nuestro agrparser y cargamos nuestra imagen.

Líneas 24 a 25: Esta sección del programa es donde ocurre la traducción. La matriz de traducción nos dice cuántos píxeles se moverá la imagen hacia arriba o hacia abajo o hacia la izquierda o hacia la derecha. Debido a que OpenCV requiere que el valor de la matriz esté en una matriz de coma flotante, la matriz de traducción toma valores en matrices de coma flotante.

La primera fila de la matriz de traducción se ve así:

Esta fila de la matriz es para el eje x. El valor de t X decidirá si la imagen se desplazará hacia el lado izquierdo o derecho. Si pasamos un valor negativo, significa que la imagen se desplazará hacia el lado izquierdo, y si el valor es positivo, significa que la imagen se desplazará hacia el lado derecho.

Ahora definiremos la segunda fila de la matriz de la siguiente manera:

Esta fila de la matriz es para el eje y. El valor de t y decidirá si la imagen se desplazará hacia arriba o hacia abajo. Si pasamos un valor negativo, significa que la imagen se desplazará hacia arriba, y si el valor es positivo, significa que la imagen se desplazará hacia abajo.

En el programa anterior en la línea 24, definimos el t X = 30 y la t y = 70. Entonces movemos la imagen 30 píxeles hacia el lado derecho y 70 píxeles hacia abajo.

Pero el proceso de traducción de la imagen principal tiene lugar en la línea 25, donde definimos la matriz de traducción cv2.warpAffine . En esta función, estamos pasando tres parámetros: el primer parámetro es la imagen, el segundo parámetro es la matriz de traducción y el tercer parámetro es la dimensión de la imagen.

Línea 27: La línea 27 mostrará el resultado en la salida.

Ahora, implementaremos otra matriz de traducción para la izquierda y la parte superior. Para ello, tenemos que definir los valores en negativo.

Línea 33 a 34: En el programa anterior en la línea 33, definimos el t X = -50 y la t y = -90. Entonces movemos la imagen 50 píxeles hacia el lado izquierdo y 90 píxeles hacia arriba. Pero el proceso principal de traducción de la imagen tiene lugar en la línea 34, donde definimos la matriz de traducción cv2.warpAffine .

línea 36 : La línea 36 mostrará el resultado como se muestra en la salida.

Para ejecutar el código anterior, tenemos que dar la ruta de la imagen como se indica a continuación.

Producción: python translate.py –imagen ardilla.jpg

Ahora, implementaremos el mismo programa de traducción de imágenes usando el imutil biblioteca. Esta biblioteca es muy fácil de usar para el procesamiento de imágenes. En esta biblioteca, no tenemos que pensar en el cv2.warpAffine porque esta biblioteca se encargará de esto. Así que implementemos este programa de traducción de imágenes usando la biblioteca imutils.

código pitón: Mantendremos el nombre del siguiente programa como translate_imutils.py .

# importar los paquetes necesarios

importar entumecido como p.ej.

importar análisis de argumentos

importar imutil

importar cv2

# Esta función implementa la traducción de imágenes y

# devuelve la imagen traducida a la función de llamada.

definitivamente traducir ( imagen , X , y ) :

traducción_matriz = p.ej. flotar32 ( [ [ 1 , 0 , X ] , [ 0 , 1 , y ] ] )

traducción_imagen = cv2. deformación ( imagen , traducción_matriz ,

( imagen. forma [ 1 ] , imagen. forma [ 0 ] ) )

devolver traducción_imagen

# construir el analizador de argumentos y analizar los argumentos

ap = análisis de argumentos Analizador de argumentos ( )

Ap. añadir_argumento ( '-i' , '--imagen' , requerido = Verdadero , ayudar = 'Camino a la imagen' )

argumentos = cuyo ( Ap. parse_args ( ) )

# carga la imagen y la muestra en la pantalla

imagen = cv2. Estoy leído ( argumentos [ 'imagen' ] )

cv2. immostrar ( 'Imagen original' , imagen )

traducción_imagen = imutil traducir ( imagen , 10 , 70 )

cv2. immostrar ( 'Traducción de imagen a la derecha y al revés' ,

traducción_imagen )

cv2. esperarClave ( 0 )

Líneas 9 a 13: Esta sección del programa es donde ocurre la traducción. La matriz de traducción nos informa cuántos píxeles se moverá la imagen hacia arriba o hacia abajo o hacia la izquierda o hacia la derecha.

Estas líneas ya han sido explicadas, pero ahora vamos a construir una función llamada translate() y enviarle tres parámetros distintos. La imagen en sí sirve como primer parámetro. Los valores x e y de la matriz de traducción corresponden al segundo y tercer parámetro.

Nota : No es necesario definir esta función de traducción dentro del programa porque ya está incluida en el paquete de la biblioteca imutils. Lo he usado dentro del programa en aras de una explicación sencilla. Podemos llamar a esta función directamente con imutils, como se muestra en la línea 24.

Línea 24: El programa anterior mostrará que en la línea 24, definimos tx = 10 y ty = 70. Entonces estamos moviendo la imagen 10 píxeles hacia el lado derecho y 70 píxeles hacia abajo.

En este programa, no nos importan las funciones cv2.warpAffine porque ya están dentro del paquete de la biblioteca imutils.

Para ejecutar el código anterior, tenemos que dar la ruta de la imagen, como se indica a continuación:

Producción:

imutils de python. pía --imagen ardilla. jpg

2. Rotación de imagen

En la lección anterior, analizamos cómo traducir (es decir, desplazar) una imagen hacia arriba, hacia abajo, hacia la izquierda y hacia la derecha (o cualquier combinación). A continuación, analizaremos la rotación en relación con el procesamiento de imágenes.

Una imagen se gira un ángulo, theta, en un proceso conocido como rotación. El ángulo por el que estamos rotando la imagen estará representado por theta. Además, posteriormente proporcionaré la función de conveniencia de rotación para simplificar la rotación de imágenes.

Similar a la traslación, y tal vez no sea sorprendente, la rotación por un ángulo, theta se determina construyendo una matriz M en el siguiente formato:

Esta matriz puede rotar un vector theta grados (en sentido antihorario) alrededor del origen dado (x, y)-plano cartesiano. Normalmente, en este escenario, el origen sería el centro de la imagen, pero en realidad, podríamos designar cualquier punto aleatorio (x, y) como nuestro centro de rotación.

A continuación, se crea la imagen rotada R a partir de la imagen original I usando una sencilla multiplicación de matrices: R = IM

OpenCV, por otro lado, también ofrece la capacidad de (1) escalar (es decir, cambiar el tamaño) de una imagen y (2) ofrecer un centro de rotación arbitrario para realizar la rotación.

Nuestra matriz de rotación modificada M se muestra a continuación:

Comencemos abriendo y generando un nuevo archivo llamado rotate.py :

# importando los paquetes requeridos

importar entumecido como p.ej.

importar análisis de argumentos

importar imutil

importar cv2

# creando el objeto argumentparser y analizando el argumento

apobj = análisis de argumentos Analizador de argumentos ( )

apobj. añadir_argumento ( '-k' , '--imagen' , requerido = Verdadero , ayudar = 'ruta de la imagen' )

argumentos = cuyo ( apobj. parse_args ( ) )

imagen = cv2. Estoy leído ( argumentos [ 'imagen' ] )

cv2. immostrar ( 'Imagen original' , imagen )

# Calcula el centro de la imagen usando las dimensiones de la imagen.

( altura , ancho ) = imagen. forma [ : 2 ]

( centroX , centroY ) = ( ancho / 2 , altura / 2 )

# Ahora, usando cv2, rotaremos la imagen 55 grados para

# determina la matriz de rotación usando getRotationMatrix2D()

matriz de rotación = cv2. getRotationMatrix2D ( ( centroX , centroY ) , 55 , 1.0 )

imagen rotada = cv2. deformación ( imagen , matriz de rotación , ( ancho , altura ) )

cv2. immostrar ( 'Rotó la imagen 55 grados' , imagen rotada )

cv2. esperarClave ( 0 )

# La imagen ahora girará -85 grados.

matriz de rotación = cv2. getRotationMatrix2D ( ( centroX , centroY ) , - 85 , 1.0 )

imagen rotada = cv2. deformación ( imagen , matriz de rotación , ( ancho , altura ) )

cv2. immostrar ( 'Rotó la imagen -85 grados' , imagen rotada )

cv2. esperarClave ( 0 )

Líneas 1 a 5: Estamos importando todos los paquetes necesarios para este programa, como OpenCV, argparser y NumPy. Tenga en cuenta que hay otra biblioteca que es imutils. Este no es un paquete de OpenCV. Esta es solo una biblioteca que se utilizará para mostrar fácilmente el mismo procesamiento de imágenes.

La biblioteca imutils no se incluirá automáticamente cuando instalemos OpenCV. OpenCV instala los imutils. Tenemos que usar el siguiente método:

pip instalar imutils

Líneas 8 a 14: Creamos nuestro agrparser y cargamos nuestra imagen. En este argparser, usamos solo un argumento de imagen, que nos dirá la ruta de la imagen que usaremos en este programa para demostrar la rotación.

Al rotar una imagen, debemos definir el punto de pivote de la rotación. La mayoría de las veces, querrá rotar una imagen sobre su centro, pero OpenCV le permite elegir cualquier punto aleatorio en su lugar. Simplemente giremos la imagen alrededor de su centro.

Líneas 17 a 18 tome el ancho y el alto de la imagen, respectivamente, y luego divida cada dimensión por dos para establecer el centro de la imagen.

Construimos una matriz para rotar una imagen de la misma manera que definimos una matriz para trasladar una imagen. Solo llamaremos al cv2.getRotationMatrix2D función en la Línea 22 en lugar de crear manualmente la matriz usando NumPy (que puede ser un poco engorroso).

Él cv2.getRotationMatrix2D La función requiere tres parámetros. La primera entrada es el ángulo de rotación deseado (en este caso, el centro de la imagen). Luego, theta se usa para especificar cuántos grados (en sentido contrario a las agujas del reloj) rotaremos la imagen. Aquí, rotaremos la imagen 45 grados. La última opción está relacionada con el tamaño de la imagen.

Independientemente del hecho de que aún no hemos discutido la escala de una imagen, puede proporcionar un número de punto flotante aquí con 1.0 que indica que la imagen debe usarse en sus proporciones originales. Sin embargo, si escribió un valor de 2,0, la imagen duplicaría su tamaño. Un número de 0,5 reduce así el tamaño de la imagen.

Línea 22 a 23: Después de recibir nuestra matriz de rotación M del cv2.getRotationMatrix2D rotamos nuestra imagen usando la función cv2.warpAffine técnica en la Línea 23. La primera entrada de la función es la imagen que queremos rotar. Luego se definen el ancho y el alto de nuestra imagen de salida, junto con nuestra matriz de rotación M. En la línea 23, la imagen se rota 55 grados.

Puede notar que nuestra imagen ha sido rotada.

Líneas 28 a 30 constituyen la segunda rotación. Las líneas 22 y 23 del código son idénticas, excepto que esta vez rotamos -85 grados en lugar de 55.

Simplemente hemos rotado una imagen alrededor de su centro hasta este punto. ¿Y si quisiéramos rotar la imagen alrededor de un punto aleatorio?

Comencemos abriendo y generando un nuevo archivo llamado rotate.py:

# importando los paquetes requeridos

importar entumecido como p.ej.

importar análisis de argumentos

importar imutil

importar cv2

# creando el objeto argumentparser y analizando el argumento

ap_obj = análisis de argumentos Analizador de argumentos ( )

ap_obj. añadir_argumento ( '-k' , '--imagen' , requerido = Verdadero , ayudar = 'ruta de la imagen' )

argumento = cuyo ( ap_obj. parse_args ( ) )

# carga la imagen y la muestra en la pantalla

imagen = cv2. Estoy leído ( argumento [ 'imagen' ] )

cv2. immostrar ( 'Imagen original' , imagen )

# Calcula el centro de la imagen usando las dimensiones de la imagen.

( altura , ancho ) = imagen. forma [ : 2 ]

( centroX , centroY ) = ( ancho / 2 , altura / 2 )

# Ahora, usando cv2, rotaremos la imagen 55 grados para

# determina la matriz de rotación usando getRotationMatrix2D()

matriz de rotación = cv2. getRotationMatrix2D ( ( centroX , centroY ) , 55 , 1.0 )

imagen rotada = cv2. deformación ( imagen , matriz de rotación , ( ancho , altura ) )

cv2. immostrar ( 'Rotó la imagen 55 grados' , imagen rotada )

cv2. esperarClave ( 0 )

# La imagen ahora girará -85 grados.

matriz de rotación = cv2. getRotationMatrix2D ( ( centroX , centroY ) , - 85 , 1.0 )

imagen rotada = cv2. deformación ( imagen , matriz de rotación , ( ancho , altura ) )

cv2. immostrar ( 'Rotó la imagen -85 grados' , imagen rotada )

cv2. esperarClave ( 0 )

# rotación de la imagen desde algún punto arbitrario, no desde el centro

matriz de rotación = cv2. getRotationMatrix2D ( ( centroX - 40 , centroY - 40 ) , 55 , 1.0 )

imagen rotada = cv2. deformación ( imagen , matriz de rotación , ( ancho , altura ) )

cv2. immostrar ( 'Rotación de imágenes desde puntos arbitrarios' , imagen rotada )

cv2. esperarClave ( 0 )

Línea 34 a 35: Ahora, este código debería parecer bastante común para rotar un objeto. Para girar la imagen alrededor de un punto 40 píxeles a la izquierda y 40 píxeles por encima de su centro, le indicamos al cv2.getRotationMatrix2D función para prestar atención a su primer parámetro.

La imagen que se produce cuando aplicamos esta rotación se muestra a continuación:

Podemos ver claramente que el centro de la rotación es ahora la coordenada (x, y), que está 40 píxeles a la izquierda y 40 píxeles por encima del centro calculado de la imagen.

3. Aritmética de imágenes

De hecho, la aritmética de imágenes es solo una suma de matrices con algunas restricciones adicionales sobre los tipos de datos que veremos más adelante.

Tomemos un momento para repasar algunos fundamentos del álgebra lineal.

Considere combinar las siguientes dos matrices:

¿Qué resultado produciría la suma de matrices? La respuesta simple es la suma de las entradas de la matriz, elemento por elemento:

Bastante simple, ¿verdad?

Todos entendemos las operaciones fundamentales de suma y resta en este momento. Sin embargo, debemos tener en cuenta las restricciones impuestas por nuestro espacio de color y tipo de datos al trabajar con imágenes.

Los píxeles en las imágenes RGB, por ejemplo, se encuentran entre [0, 255]. ¿Qué sucede si intentamos sumar 10 a un píxel con una intensidad de 250 mientras lo miramos?

Llegaríamos a un valor de 260 si aplicáramos principios aritméticos estándar. 260 no es un valor válido, ya que las imágenes RGB se representan como enteros sin signo de 8 bits.

Entonces, ¿qué debería ocurrir? ¿Deberíamos realizar una verificación para asegurarnos de que ningún píxel esté más allá del rango de [0, 255], recortando cada píxel para que tenga un valor entre 0 y 255?

¿O 'envolvemos' y realizamos una operación de módulo? De acuerdo con las reglas del módulo, sumar 10 a 255 solo daría como resultado un valor de 9.

¿Cómo deben manejarse las sumas y restas a las imágenes más allá del rango de [0, 255]?

La verdad es que no existe una técnica correcta o incorrecta; todo depende de cómo esté trabajando con sus píxeles y de lo que espera lograr.

Pero recuerda que hay diferencias entre la suma en OpenCV y la suma en NumPy. NumPy realizará la aritmética del módulo y el 'envolvente'. Por el contrario, OpenCV ejecutará el recorte y se asegurará de que los valores de los píxeles nunca abandonen el rango [0, 255].

Comencemos por crear un nuevo archivo llamado arithmetic.py y abriéndolo:

# python arithmetic.py --image ardilla.jpg

# importando los paquetes requeridos

importar entumecido como p.ej.

importar análisis de argumentos

importar imutil

importar cv2

# creando el objeto argumentparser y analizando el argumento

apObj = análisis de argumentos Analizador de argumentos ( )

apObj. añadir_argumento ( '-k' , '--imagen' , requerido = Verdadero , ayudar = 'ruta de la imagen' )

argumentos = cuyo ( apObj. parse_args ( ) )

imagen = cv2. Estoy leído ( argumentos [ 'imagen' ] )

cv2. immostrar ( 'Imagen original' , imagen )

'''

Los valores de nuestros píxeles estarán en el rango [0, 255]

ya que las imágenes son matrices NumPy, que se almacenan como enteros de 8 bits sin signo.

Al usar funciones como cv2.add y cv2.subtract, los valores se recortarán

a este rango incluso si se suman o se restan de fuera de la

[0, 255] rango. Aquí hay una ilustración:

'''


imprimir ( 'máximo de 255: {}' . formato ( calle ( cv2. agregar ( p.ej. uint8 ( [ 201 ] ) ,

p.ej. uint8 ( [ 100 ] ) ) ) ) )

imprimir ( 'mínimo de 0: {}' . formato ( calle ( cv2. sustraer ( p.ej. uint8 ( [ 60 ] ) ,

p.ej. uint8 ( [ 100 ] ) ) ) ) )

'''

Al hacer operaciones aritméticas con estas matrices usando NumPy,

el valor se envolverá en lugar de ser recortado al

[0, 255]rango. Al usar imágenes, es esencial mantener este

en mente.

'''


imprimir ( 'envolver alrededor: {}' . formato ( calle ( p.ej. uint8 ( [ 201 ] ) + p. ej. uint8 ( [ 100 ] ) ) ) )

imprimir ( 'envolver alrededor: {}' . formato ( calle ( p.ej. uint8 ( [ 60 ] ) - p.ej. uint8 ( [ 100 ] ) ) ) )

'''

Multipliquemos el brillo de cada píxel de nuestra imagen por 101.

Para hacer esto, generamos una matriz NumPy del mismo tamaño que nuestra matriz,

lleno de unos, y multiplíquelo por 101 para producir una matriz llena

con 101 Finalmente, fusionamos las dos imágenes.

Notarás que la imagen ahora es 'más brillante'.

'''


Matriz = p.ej. unos ( imagen. forma , tipo de d = 'uint8' ) * 101

imagen_añadida = cv2. agregar ( imagen , Matriz )

cv2. immostrar ( 'Resultado de imagen añadida' , imagen_añadida )

#De manera similar, podemos oscurecer nuestra imagen tomando

# 60 lejos de todos los píxeles.

Matriz = p.ej. unos ( imagen. forma , tipo de d = 'uint8' ) * 60

imagen_restada = cv2. sustraer ( imagen , Matriz )

cv2. immostrar ( 'Resultado de la imagen restada' , imagen_restada )

cv2. esperarClave ( 0 )

Líneas 1 a 16 se utilizará para llevar a cabo nuestro proceso normal, que implica importar nuestros paquetes, configurar nuestro analizador de argumentos y cargar nuestra imagen.

¿Recuerda cómo discutí anteriormente la distinción entre OpenCV y la adición de NumPy? Ahora que lo hemos cubierto a fondo, veamos un caso específico para asegurarnos de que lo comprendemos.

Dos matrices NumPy de enteros sin signo de 8 bits se definen en línea 26 . Un valor de 201 es el único elemento en la primera matriz. Aunque solo hay un miembro en la segunda matriz, tiene un valor de 100. Luego, los valores se agregan mediante la función cv2.add de OpenCV.

¿Cuál anticipas que será el resultado?

De acuerdo con los principios aritméticos convencionales, la respuesta debería ser 301. Pero recuerda que estamos tratando con números enteros sin signo de 8 bits, que solo pueden estar en el rango [0, 255]. Debido a que estamos utilizando el método cv2.add, OpenCV maneja el recorte y asegura que la suma solo arroje un resultado máximo de 255.

La primera línea de la lista a continuación muestra el resultado de ejecutar este código:

aritmética. pía

máximo de 255 : [ [ 255 ] ]

De hecho, la suma produjo un número de 255.

Siguiendo esto, línea 26 usa cv2.subtract para realizar una resta. Una vez más, definimos dos matrices NumPy de enteros sin signo de 8 bits con un solo elemento en cada una. El valor de la primera matriz es 60, mientras que el valor de la segunda matriz es 100.

Nuestra aritmética dicta que la resta debería resultar en un valor de -40, pero OpenCV maneja el recorte por nosotros una vez más. Descubrimos que el valor se ha recortado a 0. Nuestro resultado a continuación demuestra esto:

aritmética. pía

mínimo de 0 : [ [ 0 ] ]

Usando cv2, reste 100 de 60 reste, produciendo el valor 0.

Pero, ¿qué sucede si utilizamos NumPy en lugar de OpenCV para realizar los cálculos?

Líneas 38 y 39 Haz frente a esta cuestión.

En primer lugar, se definen dos matrices NumPy de enteros sin signo de 8 bits con un solo elemento cada una. El valor de la primera matriz es 201, mientras que el valor de la segunda matriz es 100. Nuestra suma se recortaría y se devolvería un valor de 255 si usáramos la función cv2.add.

NumPy, por otro lado, 'envuelve' y hace aritmética de módulo en lugar de recorte. NumPy vuelve a cero una vez que se alcanza un valor de 255 y luego continúa contando hasta que se alcanzan los 100 pasos. Esto se confirma con la primera línea de salida, que se muestra a continuación:

aritmética. pía
envolver alrededor: [ 45 ]

Luego, se definen dos matrices NumPy más, una con un valor de 50 y la otra con 100. Esta resta sería recortada por el método cv2.subtract para devolver un resultado de 0. Pero somos conscientes de que en lugar de recortar, NumPy ejecuta módulo aritmético. En cambio, los procedimientos de módulo se ajustan y comienzan a contar hacia atrás desde 255 una vez que se llega a 0 durante la resta. Podemos ver esto en el siguiente resultado:

aritmética. pía

envolver alrededor: [ 207 ]

Una vez más, nuestra salida de terminal demuestra la distinción entre recortar y envolver:

Es crucial tener en cuenta el resultado deseado al realizar aritmética de enteros. ¿Desea recortar cualquier valor fuera del rango [0, 255]? Utilice las técnicas aritméticas de imágenes integradas de OpenCV después de eso.

¿Desea que los valores se ajusten si están fuera del rango de [0, 255] y las operaciones aritméticas de módulo? Luego, las matrices NumPy simplemente se suman y se restan como de costumbre.

línea 48 define una matriz NumPy unidimensional con las mismas dimensiones que nuestra imagen. Una vez más, nos aseguramos de que nuestro tipo de datos sean enteros sin signo de 8 bits. Simplemente multiplicamos nuestra matriz de valores de un dígito por 101 para llenarla con valores de 101 en lugar de 1. Finalmente, usamos la función cv2.add para agregar nuestra matriz de 100 a la imagen original. Esto aumenta la intensidad de cada píxel en 101 y, al mismo tiempo, garantiza que cualquier valor que intente superar 255 se recorte al rango [0, 255].

Observe cómo la imagen es notablemente más brillante y parece más “desteñida” que la original. Esto se debe a que estamos impulsando los píxeles hacia colores más brillantes al aumentar su intensidad de píxeles en 101.

Para restar 60 de la intensidad de cada píxel de la imagen, primero establecemos una segunda matriz NumPy en la línea 54 que se llena con los 60.

Los resultados de esta resta se representan en la siguiente imagen:

Los elementos que nos rodean aparecen significativamente más oscuros que antes. Esto se debe a que al restar 60 de cada píxel, estamos moviendo los píxeles en el espacio de color RGB a las regiones más oscuras.

4. Cambio de imagen

Similar a la rotación, voltear una imagen sobre su eje x o y es otra opción que ofrece OpenCV. Incluso si las operaciones de volteo no se utilizan con tanta frecuencia, conocerlas es increíblemente beneficioso por varias razones que quizás no vea de inmediato.

Estamos desarrollando un clasificador de aprendizaje automático para una pequeña empresa emergente que busca identificar rostros en imágenes. Para que nuestro sistema 'aprenda' qué es una cara, necesitaríamos algún tipo de conjunto de datos con caras de muestra. Desafortunadamente, la compañía solo nos ha proporcionado un pequeño conjunto de datos de 40 caras y no podemos recopilar más información.

¿Qué hacemos entonces?

Dado que una cara sigue siendo una cara, ya sea que esté reflejada o no, podemos voltear horizontalmente cada imagen de una cara y usar las versiones reflejadas como datos de entrenamiento adicionales.

Este ejemplo puede parecer estúpido y artificial, pero no lo es. Voltear es una estrategia deliberada utilizada por fuertes algoritmos de aprendizaje profundo para producir más datos durante la fase de entrenamiento.

De lo anterior queda claro que los métodos de procesamiento de imágenes que aprende en este módulo sirven como base para sistemas de visión por computadora más grandes.

Objetivos:

Utilizando la cv2.flip función, aprenderá cómo voltear una imagen tanto horizontal como verticalmente en esta sesión.

Voltear es la siguiente manipulación de imágenes que estudiaremos. Los ejes x e y de una imagen se pueden voltear o incluso ambos. Antes de sumergirnos en la codificación, es mejor mirar primero los resultados de un cambio de imagen. Vea una imagen que ha sido volteada horizontalmente en la siguiente imagen:


Tome nota de cómo nuestra imagen original está a la izquierda y cómo la imagen se ha reflejado horizontalmente a la derecha.

Comencemos por crear un nuevo archivo llamado flipping.py .

Has visto un ejemplo de un cambio de imagen, así que examinemos el código:

# python volteando.py --image quirrel.jpg

# importando los paquetes requeridos

importar análisis de argumentos

importar cv2

# creando el objeto del analizador de argumentos y analizando el argumento

apObj = análisis de argumentos Analizador de argumentos ( )

apObj. añadir_argumento ( '-i' , '--imagen' , requerido = Verdadero , ayudar = 'ruta de la imagen' )

argumento = cuyo ( apObj. parse_args ( ) )

imagen = cv2. Estoy leído ( argumento [ 'imagen' ] )

cv2. immostrar ( 'Original' , imagen )

# voltear horizontalmente la imagen

imagen volteada = cv2. dar la vuelta ( imagen , 1 )

cv2. immostrar ( 'Imagen volteada horizontalmente' , imagen volteada )

# voltear verticalmente la imagen

imagen volteada = cv2. dar la vuelta ( imagen , 0 )

cv2. immostrar ( 'Imagen volteada verticalmente' , imagen volteada )

# volteo de imagen a lo largo de ambos ejes

imagen volteada = cv2. dar la vuelta ( imagen , - 1 )

cv2. immostrar ( 'Volteado horizontal y verticalmente' , imagen volteada )

cv2. esperarClave ( 0 )

Los pasos que tomamos para importar nuestros paquetes, analizar nuestras entradas y cargar nuestra imagen desde el disco se manejan en l inés 1 a 12 .

Llamando a la función cv2.flip en línea 15 , es simple voltear una imagen horizontalmente. La imagen que buscamos voltear y un código o indicador específico que especifica cómo voltear la imagen son los dos argumentos necesarios para el método cv2.flip.

Un valor de código de inversión de 1 significa que rotaremos la imagen alrededor del eje y para voltearla horizontalmente ( Línea 15 ). Si especificamos un código de inversión de 0, deseamos rotar la imagen sobre el eje x ( línea 19 ). Un código flip negativo ( línea 23 ) gira la imagen en ambos ejes.

Uno de los ejemplos más fáciles en este tema es voltear una imagen, que es básico.

A continuación, analizaremos el recorte de imágenes y el uso de segmentos de matriz NumPy para extraer partes específicas de la imagen.

5. Recorte de imagen

Recortar, como su nombre lo indica, es el proceso de elegir y eliminar la Región de interés (o simplemente ROI), que es el área de la imagen que nos interesa.

El rostro tendría que ser recortado de una imagen para una aplicación de detección de rostros. Además, si estuviéramos creando una secuencia de comandos de Python para encontrar perros en las imágenes, es posible que deseemos recortar el perro de la imagen cuando lo ubiquemos.

Objetivos: Nuestro objetivo principal es familiarizarse y sentirse cómodo usando el corte de matrices NumPy para recortar áreas de una imagen.

recorte : Cuando recortamos una imagen, nuestro objetivo es eliminar los elementos exteriores que no nos interesan. El proceso de elegir nuestro ROI a menudo se denomina elegir nuestra región de interés.

Crear un nuevo archivo llamado crop.py , ábralo y agregue el siguiente código:

# python cultivo.py

# importando los paquetes requeridos

importar cv2

# carga de imagen y visualización en la pantalla

imagen = cv2. Estoy leído ( 'ardilla.jpg' )

imprimir ( imagen. forma )

cv2. immostrar ( 'Original' , imagen )

# Los segmentos de matriz NumPy se utilizan para recortar rápidamente una imagen

# vamos a recortar la cara de ardilla de la imagen

cara de ardilla = imagen [ 35 : 90 , 35 : 100 ]

cv2. immostrar ( 'cara de ardilla' , cara de ardilla )

cv2. esperarClave ( 0 )

# Y ahora, aquí vamos a recortar todo el cuerpo

# de la ardilla

cuerpo de ardilla = imagen [ 35 : 148 , 23 : 143 ]

cv2. immostrar ( 'Cuerpo de ardilla' , cuerpo de ardilla )

cv2. esperarClave ( 0 )

Mostraremos el recorte en Python y OpenCV usando una imagen que cargamos desde el disco en Líneas 5 y 6 .

Imagen original que vamos a recortar.

Usando solo técnicas básicas de recorte, nuestro objetivo es separar la cara y el cuerpo de la ardilla del área circundante.

Usaremos nuestro conocimiento previo de la imagen y proporcionaremos manualmente los segmentos de matriz NumPy de donde se encuentran el cuerpo y la cara. En condiciones normales, generalmente emplearíamos algoritmos de aprendizaje automático y visión por computadora para reconocer la cara y el cuerpo en la imagen. Pero mantengamos las cosas claras por el momento y evitemos emplear cualquier modelo de detección.

Podemos identificar la cara en la imagen con solo una línea de código. línea 13 , Para extraer una porción rectangular de la imagen, comenzando en (35, 35), proporcionamos segmentos de matriz NumPy (90, 100). Puede parecer confuso que alimentemos el recorte con los índices en el orden de altura primero y ancho segundo que hacemos, pero tenga en cuenta que OpenCV almacena imágenes como matrices NumPy. Como resultado, debemos proporcionar los valores para el eje y antes que el eje x.

NumPy requiere los siguientes cuatro índices para llevar a cabo nuestro recorte:

Inicio y: La coordenada y al principio. Para este ejemplo, comenzamos en y=35.

Fin y: La coordenada y al final. Nuestro cultivo se detendrá cuando y = 90.

Inicio x: La coordenada x inicial del corte. El cultivo se inicia en x=35.

Fin x: La coordenada del eje x final del corte. En x=100, nuestro segmento está terminado.

De manera similar, recortamos las regiones (23, 35) y (143, 148) de la imagen original para extraer el cuerpo completo de la imagen en línea 19 .

Puede observar que la imagen se ha recortado para mostrar solo el cuerpo y la cara.

6. Cambio de tamaño de imagen

El proceso de aumentar o disminuir el ancho y alto de una imagen se conoce como escalar o simplemente cambiar el tamaño. La relación de aspecto, que es la proporción entre el ancho y la altura de una imagen, debe tenerse en cuenta al cambiar el tamaño de una imagen. Descuidar la relación de aspecto puede dar como resultado imágenes escaladas que aparecen comprimidas y distorsionadas:

Nuestra imagen inicial está a la izquierda. A la derecha, verá dos imágenes que se han escalado sin mantener la relación de aspecto, distorsionando la proporción del ancho de la imagen con respecto a la altura. Al cambiar el tamaño de sus imágenes, generalmente debe considerar la relación de aspecto.

La técnica de interpolación utilizada por nuestro algoritmo de cambio de tamaño también debe considerar el objetivo de la función de interpolación de utilizar estos vecindarios de píxeles para aumentar o disminuir el tamaño de la imagen.

En general, reducir el tamaño de la imagen es mucho más efectivo. Esto se debe a que eliminar píxeles de una imagen es todo lo que necesita hacer la función de interpolación. Por otro lado, el método de interpolación necesitaría 'llenar los espacios' entre píxeles que no existían previamente si se aumentara el tamaño de la imagen.

Tenemos nuestra imagen original a la izquierda. La imagen se ha reducido a la mitad de su tamaño original en el centro, pero aparte de eso, no ha habido pérdida de la 'calidad' de la imagen. Sin embargo, el tamaño de la imagen se ha mejorado considerablemente a la derecha. Ahora aparece 'ampliado' y 'pixelado'.

Como dije anteriormente, normalmente querrá reducir el tamaño de una imagen en lugar de aumentarlo. Al reducir el tamaño de la imagen, analizamos menos píxeles y tenemos que lidiar con menos 'ruido', lo que hace que los algoritmos de procesamiento de imágenes sean más rápidos y precisos.

La traslación y la rotación son las dos transformaciones de imagen abordadas hasta ahora. Ahora examinaremos cómo cambiar el tamaño de una imagen.

Como era de esperar, cambiaremos el tamaño de nuestras imágenes utilizando el método cv2.resize. Como indiqué anteriormente, debemos considerar la relación de aspecto de la imagen al utilizar este método. Pero antes de profundizar demasiado en los detalles, permítame darle una ilustración:

# python resize.py --image ardilla.jpg

# importando los paquetes requeridos

importar análisis de argumentos

importar cv2

# creando el objeto del analizador de argumentos y analizando el argumento

apObj = análisis de argumentos Analizador de argumentos ( )

apObj. añadir_argumento ( '-k' , '--imagen' , requerido = Verdadero , ayudar = 'ruta de la imagen' )

argumentos = cuyo ( apObj. parse_args ( ) )

# carga la imagen y la muestra en la pantalla

imagen = cv2. Estoy leído ( argumentos [ 'imagen' ] )

cv2. immostrar ( 'Original' , imagen )

# Para evitar que la imagen aparezca torcida, la relación de aspecto

# debe ser considerado o deformado; por lo tanto, averiguamos qué

# la relación de la nueva imagen con respecto a la imagen actual.

# Hagamos que el ancho de nuestra nueva imagen sea de 160 píxeles.

aspecto = 160.0 / imagen. forma [ 1 ]

dimensión = ( 160 , En t ( imagen. forma [ 0 ] * aspecto ) )

# esta línea mostrará las operaciones de cambio de tamaño reales

imagen redimensionada = cv2. cambiar el tamaño ( imagen , dimensión , interpolación = cv2. INTER_AREA )

cv2. immostrar ( 'Ancho de imagen redimensionado' , imagen redimensionada )

# ¿Y si quisiéramos cambiar la altura de la imagen? - utilizando la

# mismo principio, podemos calcular la relación de aspecto basada

# en altura en lugar de ancho. Hagamos el escalado

# altura de la imagen 70 píxeles.

aspecto = 70.0 / imagen. forma [ 0 ]

dimensión = ( En t ( imagen. forma [ 1 ] * aspecto ) , 70 )

# realizar el cambio de tamaño

imagen redimensionada = cv2. cambiar el tamaño ( imagen , dimensión , interpolación = cv2. INTER_AREA )

cv2. immostrar ( 'Altura de la imagen redimensionada' , imagen redimensionada )

cv2. esperarClave ( 0 )

Líneas 1-14 , Después de importar nuestros paquetes y configurar nuestro analizador de argumentos, cargaremos y mostraremos nuestra imagen.

Líneas 20 y 21: La codificación correspondiente comienza en estas líneas . La relación de aspecto de la imagen debe tenerse en cuenta al cambiar su tamaño. La proporción entre el ancho y el alto de la imagen se conoce como relación de aspecto.

Anchura altura es la relación de aspecto.

Si no tenemos en cuenta la relación de aspecto, los resultados de nuestro cambio de tamaño se distorsionarán.

Sobre línea 20 , se realiza el cálculo de la relación redimensionada. Proporcionamos el ancho de nuestra nueva imagen como 160 píxeles en esta línea de código. Simplemente definimos nuestra proporción (relación de aspecto) como el nuevo ancho (160 píxeles) dividido por el ancho anterior, al que accedemos mediante image, para calcular la proporción entre la nueva altura y la altura anterior. forma[1].

Las nuevas dimensiones de la imagen en línea 21 se puede calcular ahora que conocemos nuestra proporción. Una vez más, la nueva imagen tendrá un ancho de 160 píxeles. Después de multiplicar la altura anterior por nuestra proporción y convertir el resultado en un número entero, se calcula la altura. Podemos mantener la relación de aspecto original de la imagen realizando esta operación.

línea 24 es donde la imagen realmente cambia de tamaño. La imagen que queremos cambiar de tamaño es el primer argumento, y el segundo son las dimensiones que calculamos para la nueva imagen. Nuestro método de interpolación, que es el algoritmo para cambiar el tamaño de la imagen real, es el último parámetro.

Finalmente, en línea 25 , mostramos nuestra imagen escalada.

Redefinimos nuestra relación (aspectratio) en línea 31 . La altura de nuestra nueva imagen será de 70 píxeles. Dividimos 70 por la altura original para obtener la nueva relación altura-altura original.

A continuación, establecemos las dimensiones de la nueva imagen. La nueva imagen tendrá una altura de 70 píxeles, que ya se conoce. Una vez más, podemos mantener la relación de aspecto original de la imagen multiplicando el ancho anterior por la relación para producir el nuevo ancho.

A continuación, se cambia el tamaño de la imagen en línea 35 , y se muestra en Línea 36.

Aquí, podemos ver que hemos reducido el ancho y el alto de nuestra imagen original manteniendo la relación de aspecto. Nuestra imagen aparecería distorsionada si no se mantuviera la relación de aspecto.

Conclusión

En este blog, hemos estudiado los diferentes conceptos básicos de procesamiento de imágenes. Hemos visto la traducción de imágenes con la ayuda del paquete OpenCV. Hemos visto los métodos para mover la imagen hacia arriba, abajo, derecha e izquierda. Estos métodos son muy útiles cuando creamos un conjunto de datos de imágenes similares para dar como un conjunto de datos de entrenamiento, por lo que la máquina verá imágenes diferentes incluso si son iguales. Este artículo también le enseñó cómo rotar una imagen alrededor de cualquier punto en el espacio cartesiano usando una matriz de rotación. Luego descubrió cómo OpenCV rota imágenes usando esta matriz y vio un par de ilustraciones de imágenes giratorias.

En esta sección se examinaron las dos operaciones aritméticas de imagen fundamentales (pero significativas) de suma y resta. Como puede ver, sumar y restar matrices fundamentales es todo lo que implican las operaciones aritméticas de imágenes.

Además, usamos OpenCV y NumPy para investigar las peculiaridades de la aritmética de imágenes. Estas restricciones deben tenerse en cuenta, o corre el riesgo de obtener resultados inesperados al ejecutar operaciones aritméticas en sus imágenes.

Es importante recordar que aunque NumPy realiza una operación de módulo y 'se ajusta', los valores de corte de suma y resta de OpenCV más allá del rango [0, 255] para encajar dentro del rango. Al desarrollar sus propias aplicaciones de visión por computadora, recordar esto lo ayudará a evitar la caza de errores engañosos.

La inversión de imágenes es, sin duda, una de las ideas más sencillas que exploraremos en este curso. Flipping se emplea con frecuencia en el aprendizaje automático para generar más muestras de datos de entrenamiento, lo que da como resultado clasificadores de imágenes más potentes y confiables.

También aprendimos a usar OpenCV para cambiar el tamaño de una imagen. Es crucial considerar tanto el método de interpolación que está empleando como la relación de aspecto de su imagen original al cambiar el tamaño de una para que el resultado no parezca distorsionado.

Finalmente, es crucial recordar que si la calidad de la imagen es un problema, siempre es mejor cambiar de una imagen más grande a una más pequeña. En la mayoría de los casos, ampliar una imagen crea artefactos y degrada su calidad.