Distorsion pincée / bombée à l'aide de Python OpenCV
Je souhaite appliquer un filtre pincement / renflement sur une image à l'aide de Python OpenCV. Le résultat devrait être une sorte de cet exemple:
https://pixijs.io/pixi-filters/tools/screenshots/dist/bulge-pinch.gif
J'ai lu le post de stackoverflow suivant qui devrait être la formule correcte pour le filtre: Formules pour la distorsion Barrel / Pincushion
Mais j'ai du mal à implémenter cela dans Python OpenCV.
J'ai lu sur les cartes pour appliquer un filtre sur une image: e ff et de distorsion en utilisant OpenCv-python
Quant à ma compréhension, le code pourrait ressembler à ceci:
import numpy as np
import cv2 as cv
f_img = 'example.jpg'
im_cv = cv.imread(f_img)
# grab the dimensions of the image
(h, w, _) = im_cv.shape
# set up the x and y maps as float32
flex_x = np.zeros((h, w), np.float32)
flex_y = np.zeros((h, w), np.float32)
# create map with the barrel pincushion distortion formula
for y in range(h):
for x in range(w):
flex_x[y, x] = APPLY FORMULA TO X
flex_y[y, x] = APPLY FORMULA TO Y
# do the remap this is where the magic happens
dst = cv.remap(im_cv, flex_x, flex_y, cv.INTER_LINEAR)
cv.imshow('src', im_cv)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()
Est-ce la bonne façon d'obtenir la distorsion présentée dans l'image d'exemple? Toute aide concernant des ressources utiles ou de préférence des exemples est très appréciée.
Réponses
Vous pouvez le faire en utilisant les options d'implosion et d'explosion dans Python Wand, qui utilise ImageMagick.
Contribution:
from wand.image import Image
import numpy as np
import cv2
with Image(filename='zelda1.jpg') as img:
img.virtual_pixel = 'black'
img.implode(0.5)
img.save(filename='zelda1_implode.jpg')
# convert to opencv/numpy array format
img_implode_opencv = np.array(img)
img_implode_opencv = cv2.cvtColor(img_implode_opencv, cv2.COLOR_RGB2BGR)
with Image(filename='zelda1.jpg') as img:
img.virtual_pixel = 'black'
img.implode(-0.5 )
img.save(filename='zelda1_explode.jpg')
# convert to opencv/numpy array format
img_explode_opencv = np.array(img)
img_explode_opencv = cv2.cvtColor(img_explode_opencv, cv2.COLOR_RGB2BGR)
# display result with opencv
cv2.imshow("IMPLODE", img_implode_opencv)
cv2.imshow("EXPLODE", img_explode_opencv)
cv2.waitKey(0)
Imploser:
Exploser:
Après m'être familiarisé avec le code source d'ImageMagick, j'ai trouvé un moyen d'appliquer la formule de distorsion. Avec l'aide de la fonction de remappage OpenCV , c'est un moyen de déformer une image:
import numpy as np
import cv2 as cv
f_img = 'example.jpg'
im_cv = cv.imread(f_img)
# grab the dimensions of the image
(h, w, _) = im_cv.shape
# set up the x and y maps as float32
flex_x = np.zeros((h, w), np.float32)
flex_y = np.zeros((h, w), np.float32)
# create map with the barrel pincushion distortion formula
for y in range(h):
delta_y = scale_y * (y - center_y)
for x in range(w):
# determine if pixel is within an ellipse
delta_x = scale_x * (x - center_x)
distance = delta_x * delta_x + delta_y * delta_y
if distance >= (radius * radius):
flex_x[y, x] = x
flex_y[y, x] = y
else:
factor = 1.0
if distance > 0.0:
factor = math.pow(math.sin(math.pi * math.sqrt(distance) / radius / 2), -amount)
flex_x[y, x] = factor * delta_x / scale_x + center_x
flex_y[y, x] = factor * delta_y / scale_y + center_y
# do the remap this is where the magic happens
dst = cv.remap(im_cv, flex_x, flex_y, cv.INTER_LINEAR)
cv.imshow('src', im_cv)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()
Cela a le même effet que l'utilisation de la fonction convert -implode d'ImageMagick.