from scipy import interpolate import matplotlib.pyplot as plt import numpy as np import cv2 a=np.arange(1,9) filename = 'image_file_0.tiff' img = cv2.imread(filename) x = np.array([389, 392, 325, 211, 92,103,194,310]) y = np.array([184,281,365,401,333,188,127,126]) x = np.r_[x, x[0]] y = np.r_[y, y[0]] tck, u = interpolate.splprep([x, y], s=0, per=True) xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck) fig, ax = plt.subplots(1, 1) ax.plot(xi, yi, '-b') plt.imshow(img) plt.show()
Quiero transformar los valores de píxel de la región exterior o interior después de formar una curva cerrada arbitraria en la imagen. ¿Cómo lo hago?
Puedes hacerlo usando la función cv2.fillpoly . Usando esta imagen por ejemplo:
Podemos obtener la forma que queremos enmascarar usando:
from scipy import interpolate import matplotlib.pyplot as plt import numpy as np import cv2 a=np.arange(1,9) filename = 'image_file_0.tiff' img = cv2.imread('image_left.png', cv2.IMREAD_COLOR) x = np.array([289, 292, 125, 111, 40, 80, 94,210]) y = np.array([84 , 181, 265, 241,133, 88, 27, 40]) x = np.r_[x, x[0]] y = np.r_[y, y[0]] tck, u = interpolate.splprep([x, y], s=0, per=True) xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck) plt.imshow(img[:,:,[2,1,0]]) plt.scatter(xi, yi) plt.show()Ahora el enmascaramiento se puede hacer usando:
contour = np.array([[xii, yii] for xii, yii in zip(xi.astype(int), yi.astype(int))]) mask = np.zeros_like(img) cv2.fillPoly(mask, pts=[contour], color=(255, 255, 255)) masked_img = cv2.bitwise_and(img, mask)Usando la máscara invertida, manipula los píxeles externos como desee:
mask = np.ones_like(img)*255 cv2.fillPoly(mask, pts=[contour], color=(0,0,0)) masked_img = cv2.bitwise_and(img, mask)Esto resulta en:
Aquí hay otra forma de hacerlo usando cv2.drawContours() . La idea es tomar los puntos de contorno aproximados, suavizarlos, dibujar este contorno en una máscara, luego cv2.bitwise_and() o bitwise inverso, y extraer las regiones deseadas.
Imagen de entrada -> Máscara generada


Resultado -> Resultado invertido


import numpy as np import cv2 from scipy import interpolate # Load image, make blank mask, define rough contour points image = cv2.imread('1.jpg') mask = np.zeros(image.shape, dtype=np.uint8) x = np.array([192, 225, 531, 900, 500]) y = np.array([154, 281, 665, 821, 37]) x = np.r_[x, x[0]] y = np.r_[y, y[0]] # Smooth contours tck, u = interpolate.splprep([x, y], s=0, per=True) x_new, y_new = interpolate.splev(np.linspace(0, 1, 1000), tck) smooth_contour = np.array([[[int(i[0]), int(i[1])]] for i in zip(x_new, y_new)]) # Draw contour onto blank mask in white cv2.drawContours(mask, [smooth_contour], 0, (255,255,255), -1) result1 = cv2.bitwise_and(image, mask) result2 = cv2.bitwise_and(image, 255 - mask) cv2.imshow('image', image) cv2.imshow('mask', mask) cv2.imshow('result1', result1) cv2.imshow('result2', result2) cv2.waitKey()