En el último tutorial, presentamos la función de usar el lápiz del mouse. En este tutorial, hablaremos sobre las operaciones básicas del procesamiento de imágenes OpenCV.
Lo que necesitamos introducir en este tutorial es:
· Ver los valores de píxeles de la imagen y modificarlos
· Ver las propiedades de la imagen
· Ver la región de interés (ROI)
· Dividir y fusionar la imagen
Todas las operaciones de este tutorial están básicamente relacionadas con Numpy, no con OpenCV. Para usar OpenCV para escribir código mejor optimizado, se requiere una gran cantidad de conocimientos de Numpy.
Ver y modificar valores de píxeles
Si queremos ver el valor de píxel de un determinado píxel en una imagen, primero debemos localizar y calibrar sus coordenadas. Primero veamos una imagen en color (sigue siendo nuestro gato, este tutorial es nuestro protagonista):
Ahora quiero ver el valor de píxel de una determinada coordenada, ingresamos el código en pycharm:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
#获取像素值
px = img[200,200]
print(px)
El código es para ver el valor de píxel en las coordenadas de la imagen (200, 200), veamos el resultado:
En el tutorial anterior hablamos de que OpenCV lee imágenes no de canales RGB, sino de canales BGR, luego la salida del programa [178, 189, 186] corresponde a los píxeles BGR, podemos verificar:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
#获取像素值
px = img[200,200]
B = img[200,200,0]
G = img[200,200,1]
R = img[200,200,2]
print(px,B,G,R)
Ahora asumimos que si la imagen no está en color, sino en una imagen en escala de grises en blanco y negro, ¿cómo se generará? Experimente primero:
todavía usamos el código justo ahora para experimentar (siempre que la imagen haya sido en escala de grises, que se discutirá más adelante), el efecto:
puede ver que los píxeles de BGR son los mismos, llegamos a una conclusión: para escala de grises En una imagen, el valor del píxel de salida es esencialmente su valor de intensidad de brillo, el rango de valores está entre 0-255, cuando es 0, es todo negro, de lo contrario es blanco.
A continuación, modifiquemos el valor del píxel, asignemos el valor del píxel de la coordenada especificada con una matriz:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat1.jpg")
#获取像素值
px = img[200,200]
print(px)
img[200,200] = [225,225,225]
print(img[200,200])
Ver la salida:
Como puede ver, el valor de píxel inicial va seguido del valor de píxel modificado.
En términos generales, una matriz suele seleccionar un área determinada, como las primeras filas o las últimas columnas. Para acceder a un determinado píxel, los métodos de matriz Numpy, array.item () y array.itemset () tienen un mejor efecto. Pero devuelve un escalar. Entonces, si queremos acceder a todos los valores B, G, R, necesitamos llamar a array.item () por separado, veamos el código (aún tomando las coordenadas 200, 200 como ejemplo):
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
#获取像素值
px = img[200,200]
print(px)
print(img.item(200,200,0))
Usamos item para generar el valor B del píxel, que es el valor del píxel azul:
El experimento muestra que el efecto es el mismo que antes.
Para la asignación de las coordenadas especificadas, podemos usar la función de conjunto de elementos para tener una precisión de un determinado píxel. Por ejemplo, ahora solo cambio el valor del píxel azul:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
#获取像素值
px = img[200,200]
print(px)
print(img.item(200,200,0))
img.itemset((200,200,0),100)
print(img.item(200,200,0))
Se puede ver que la asignación del canal de color especificado es completamente posible.
Ver propiedades de la imagen
Ahora estudiaremos los distintos atributos de la imagen. Los atributos de la imagen incluyen el número de filas, columnas y canales, el tipo de datos de la imagen, el número de píxeles, etc.
Para una imagen, usamos forma para devolver el número de filas, columnas y el número de canales de color:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
print(img.shape)
El tercer valor de la salida representa el número de elemento de los tres canales del BGR de la imagen, que es 3. Ahora experimentamos con imágenes en escala de grises:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(img.shape)
La imagen en escala de grises se explicará en un tutorial posterior, aquí se usa como un experimento:
puede ver que si la imagen es en escala de grises, la tupla devuelta solo contiene el número de filas y columnas, por lo que esto es para verificar si la imagen cargada es La escala de grises también es un buen método para colorear.
El número total de píxeles de la imagen actual se puede devolver por tamaño:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
print(img.size)
El tipo de datos de la imagen se puede obtener mediante dtype:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
print(img.dtype)
El formato predeterminado de la función imread para leer la imagen es uint8, por lo que todas las devoluciones están en este formato. En el futuro, cuando aprendamos el marco de aprendizaje profundo, encontraremos que cuando se usa el formato de datos de imagen de uint8 para el entrenamiento de modelos, la normalización de datos (etapa de preprocesamiento) dará como resultado una pérdida de precisión y, finalmente, una disminución en la precisión de segmentación. Por supuesto, esto es algo posterior, no lo mencionaremos ahora.
Si queremos modificar el formato de la imagen, necesitamos usar la función astype, y ahora modificar la imagen al formato float32 (las imágenes en este formato se usan ampliamente en el entrenamiento de modelos de aprendizaje profundo):
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg").astype(np.float32)
print(img.dtype)
dtype es muy importante al depurar, porque una gran cantidad de errores en el código OpenCV-Python son causados por tipos de datos no válidos, y a menudo encontraremos estos problemas en el aprendizaje futuro.
ROI de la imagen
La selección de un área específica en la imagen se llama ROI, que en realidad es una operación en las coordenadas xy de la imagen. Veamos un ejemplo:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
husky = img[1:240,60:270]
cv2.imshow("img",husky)
cv2.waitKey(0)
cv2.destroyAllWindows()
La esencia es equivalente a interceptar una cierta parte de la imagen. Ahora hagamos algunas operaciones interesantes para cubrir la parte interceptada a otras partes de la imagen. La esencia es equivalente a la modificación de píxeles mencionada anteriormente:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
husky = img[1:240,60:270]
img[61:300,270:480] = husky
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Dividir y fusionar canales de imágenes
A veces necesitamos operar por separado en las imágenes de los canales B, G y R. En este caso, la imagen BGR debe dividirse en canales individuales. Necesita usar la función de división y la función de combinación, sus funciones son separación y combinación respectivamente:
b, g, r = cv2.split (img) #Canal de imagen dividido
img = cv2.merge ((b, g, r))
Esta operación puede separar los tres canales BGR, de modo que se pueda operar un determinado canal. Por ejemplo, ahora configuramos todos los píxeles R en 0:
view plaincopy to clipboardprint?
import cv2
import numpy as np
img = cv2.imread("cat.jpg")
b,g,r = cv2.split(img) #拆分图像通道
img[:,:,2] = 0
r = img[:,:,2]
img = cv2.merge((b,g,r))
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
r es el canal R, vea el efecto:
Después de quitar el canal rojo, nuestro gato se puso un poco verde. Por supuesto, también puede experimentar con otros canales.
Relleno del borde de la imagen
Si desea crear un borde alrededor de la imagen (como un marco de fotos), puede usar la función cv2.copyMakeBorder (). Tiene más aplicaciones en operaciones de convolución (muy importante), relleno de ceros, etc. Esta función toma los siguientes parámetros:
cv2.copyMakeBorder (src, top, bottom, left, right, borderType [, dst [, value]])
· Imagen de entrada src
· Arriba, abajo, izquierda, derecha: el ancho del borde en píxeles en la dirección correspondiente
· Valor: cv2.BORDER_CONSTANT, cv2.BORDER_REFLECT, cv2.BORDER_REFLECT_101 o cv2.BORDER_DEFAULT, cv2.BORDER_REPLICATE, cv2.BORDER_WRAP
cv2.BORDER_defLECT_101 o cv2.BORDER_defLECT_101 o cv2.BORDER con cambios leves como se muestra arriba, pero con los mismos cambios que se muestran arriba en | gfedcba
cv.BORDER_REPLICATE: el último píxel se copia durante todo el proceso, como: aaaaaa | abcdefgh | hhhhhhh
El intercambio de píxeles de dirección simétrica cv.BORDER_WRAP es como: cdefgh | abcdefgh | abcdefg así.
Veamos el código:
view plaincopy to clipboardprint?
import cv2
from matplotlib import pyplot as plt
BLUE = [255,0,0]
img1 = cv2.imread('cat.jpg')
replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()
Efecto experimental:
Los experimentos en los cinco parámetros pueden ver diferencias obvias. Por supuesto, para facilitar la comparación y visualización de imágenes, usamos la biblioteca matplotlib, pero esto pertenece al conocimiento de Python, por lo que no los presentaré aquí. También puede modificar el código y usar OpenCV para generar otros parámetros.
Vea la página de resumen del artículo https://blog.csdn.net/weixin_44237705/article/details/107864965
Se puede intercambiar más información técnica de openvino en el grupo ~