El canal de imagen de entrada predeterminado de resnet es de 3 canales, y el modelo de preentrenamiento también es de 3 canales. Si desea que la entrada sea una imagen en escala de grises de un solo canal, ¿cómo modificarla? Es relativamente sencillo, solo es necesario modificar el canal de entrada de la primera convolución. Al observar la función de inicialización de resnet, puede ver que la primera convolución al principio es de 3 canales y se cambia a un solo canal. [1] Modificar la definición de la función resnet
# self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
复制代码
[2] Modificar la carga del modelo pre-entrenado y no importar los pesos de la primera capa convolucional. Referencia: github.com/ShaiLYU/re…
# if pretrained:
# state_dict = model_zoo.load_url(model_urls['resnet18'])
# for key in list(state_dict.keys() ):
# if "conv1" in key : del state_dict[key]
# model.load_state_dict(state_dict, False)
复制代码
[3] Operación de normalización de preprocesamiento Originalmente leído en la imagen en color, habrá datos tridimensionales HWC, los 3 canales de imagen se normalizan por separado y, al mismo tiempo, agregar una dimensión puede tener datos BCHW en el tensor, mientras que la escala de grises la imagen solo tiene datos HW de dos dimensiones, el canal C debe agregarse por separado y los datos normalizados también deben modificarse
def load_image(self, image_path):
# self.RGB_MEAN = np.array([122.67891434, 116.66876762, 104.00698793])
self.RGB_MEAN = 122.67891434
# img = cv2.imread(image_path, cv2.IMREAD_COLOR).astype('float32')
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE).astype('float32')
height, width = img.shape[:2]
if height > width:
img = cv2.copyMakeBorder(img, 0, 0, 0, height - width, cv2.BORDER_CONSTANT, value=(255, 255, 255))
else:
img = cv2.copyMakeBorder(img, 0, width - height, 0, 0, cv2.BORDER_CONSTANT, value=(255, 255, 255))
original_shape = img.shape[:2]
img = self.resize_image_cn(img)
img -= self.RGB_MEAN
img /= 255.
img = np.expand_dims(img, axis=-1)
img = torch.from_numpy(img).permute(2, 0, 1).float().unsqueeze(0)
return img, original_shape
def resize_image_cn(self, img, img_side=1280):
height, width, _ = img.shape
if height > img_side:
new_height = 1280
new_width = 1280
else:
new_height = int(math.ceil(height / 32) * 32)
new_width = int(math.ceil(new_height / height * width / 32) * 32)
resized_img = cv2.resize(img, (new_width, new_height))
return resized_img
复制代码
imagen de 3 canales
def load_image(self, image_path):
img = cv2.imread(image_path, cv2.IMREAD_COLOR).astype('float32')
height, width, _ = img.shape
if height > width:
img = cv2.copyMakeBorder(img, 0, 0, 0, height - width, cv2.BORDER_CONSTANT, value=(255, 255, 255))
else:
img = cv2.copyMakeBorder(img, 0, width - height, 0, 0, cv2.BORDER_CONSTANT, value=(255, 255, 255))
original_shape = img.shape[:2]
img = self.resize_image_cn(img)
img -= self.RGB_MEAN
img /= 255.
img = torch.from_numpy(img).permute(2, 0, 1).float().unsqueeze(0)
return img, original_shape
复制代码
Pensando: el cambio inicial a la entrada de imagen en escala de grises es reducir el tamaño del modelo, pero de hecho, la imagen se cambia a una entrada de imagen de un solo canal, solo se modifica la primera convolución y el tamaño del archivo del modelo básicamente lo hace No cambiará mucho, se reducirá mucho. Por el contrario, para adaptarse a esta modificación, es necesario modificar el uso de varias funciones (carga de datos, preprocesamiento de imágenes, carga de modelos, definición de funciones de modelos), y al volver a usar otras escenas, si la escena del mapa de color no puede ser adaptado, comparar Es engorroso y poco práctico, por lo que no se recomienda este método, y es bueno cargar la entrada de imagen de 3 canales de forma predeterminada. En cuanto a cómo reducir el modelo y acelerar la inferencia, puede usar una poda cuantitativa más madura y otras operaciones.