reescalar - reducir tamaño de imagen python
superponer una imagen más pequeña en una imagen más grande python OpenCv (4)
Basado en la excelente respuesta anterior de fireant, aquí está la mezcla alfa, pero un poco más humana legible. Puede que necesites cambiar 1.0-alpha
y alpha
dependiendo de la dirección en la que te estás fusionando (la mía se intercambia con la respuesta de fireant).
o* == s_img.*
b* == b_img.*
for c in range(0,3):
alpha = s_img[oy:oy+height, ox:ox+width, 3] / 255.0
color = s_img[oy:oy+height, ox:ox+width, c] * (1.0-alpha)
beta = l_img[by:by+height, bx:bx+width, c] * (alpha)
l_img[by:by+height, bx:bx+width, c] = color + beta
Hola, estoy creando un programa que reemplaza una cara en una imagen con la cara de otra persona. Sin embargo, estoy atascado en tratar de insertar la nueva cara en la imagen original y más grande. Investigué ROI y addWeight (necesita que las imágenes sean del mismo tamaño) pero no he encontrado una manera de hacerlo en Python. Cualquier consejo es genial. Soy nuevo en opencv.
Estoy usando las siguientes imágenes de prueba:
smaller_image:
larger_image:
Aquí está mi Código hasta ahora ... un mezclador de otras muestras:
import cv2
import cv2.cv as cv
import sys
import numpy
def detect(img, cascade):
rects = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=3, minSize=(10, 10), flags = cv.CV_HAAR_SCALE_IMAGE)
if len(rects) == 0:
return []
rects[:,2:] += rects[:,:2]
return rects
def draw_rects(img, rects, color):
for x1, y1, x2, y2 in rects:
cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)
if __name__ == ''__main__'':
if len(sys.argv) != 2: ## Check for error in usage syntax
print "Usage : python faces.py <image_file>"
else:
img = cv2.imread(sys.argv[1],cv2.CV_LOAD_IMAGE_COLOR) ## Read image file
if (img == None):
print "Could not open or find the image"
else:
cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")
gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)
gray = cv2.equalizeHist(gray)
rects = detect(gray, cascade)
## Extract face coordinates
x1 = rects[0][3]
y1 = rects[0][0]
x2 = rects[0][4]
y2 = rects[0][5]
y=y2-y1
x=x2-x1
## Extract face ROI
faceROI = gray[x1:x2, y1:y2]
## Show face ROI
cv2.imshow(''Display face ROI'', faceROI)
small = cv2.imread("average_face.png",cv2.CV_LOAD_IMAGE_COLOR)
print "here"
small=cv2.resize(small, (x, y))
cv2.namedWindow(''Display image'') ## create window for display
cv2.imshow(''Display image'', small) ## Show image in the window
print "size of image: ", img.shape ## print size of image
cv2.waitKey(1000)
Si alguien, como yo, obtiene el error:
ValueError: el destino de la asignación es de solo lectura
cuando intente escribir en la imagen de destino usando cualquiera de estas respuestas anteriores.
Una solución rápida y sucia es establecer el indicador ESCRIBIR en verdadero:
img.setflags(write=1)
Una forma simple de lograr lo que quieres:
import cv2
s_img = cv2.imread("smaller_image.png")
l_img = cv2.imread("larger_image.jpg")
x_offset=y_offset=50
l_img[y_offset:y_offset+s_img.shape[0], x_offset:x_offset+s_img.shape[1]] = s_img
Actualizar
Supongo que también querrás ocuparte del canal alfa. Aquí hay una manera rápida y sucia de hacerlo:
s_img = cv2.imread("smaller_image.png", -1)
y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s
for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])
Utilizando la idea de @ fireant, escribí una función para manejar superposiciones. Esto funciona bien para cualquier argumento de posición (incluidas las posiciones negativas).
def overlay_image_alpha(img, img_overlay, pos, alpha_mask):
"""Overlay img_overlay on top of img at the position specified by
pos and blend using alpha_mask.
Alpha mask must contain values within the range [0, 1] and be the
same size as img_overlay.
"""
x, y = pos
# Image ranges
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
# Overlay ranges
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
# Exit if nothing to do
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
return
channels = img.shape[2]
alpha = alpha_mask[y1o:y2o, x1o:x2o]
alpha_inv = 1.0 - alpha
for c in range(channels):
img[y1:y2, x1:x2, c] = (alpha * img_overlay[y1o:y2o, x1o:x2o, c] +
alpha_inv * img[y1:y2, x1:x2, c])
El uso es:
overlay_image_alpha(img_large,
img_small[:, :, 0:3],
(x, y),
img_small[:, :, 3] / 255.0)