使用Python OpenCV捏缩/凸出变形

问题描述

我想使用Python OpenCV在图像上应用收缩/凸起过滤器。结果应为以下示例:

https://pixijs.io/pixi-filters/tools/screenshots/dist/bulge-pinch.gif

我已阅读以下应该是过滤器正确公式的stackoverflow帖子:Formulas for Barrel/Pincushion distortion

但是我正在努力在Python OpenCV中实现它。

我已经了解了将地图应用于滤镜的地图:Distortion effect using OpenCv-python

据我了解,代码可能如下所示:

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,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()

这是实现示例图像中呈现的失真的正确方法吗?非常感谢有关有用资源或示例的帮助。

解决方法

您可以在使用ImageMagick的Python魔杖中使用爆破和爆炸选项来做到这一点。

输入:

enter image description here

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)

放大:

enter image description here

爆炸:

enter image description here

,

熟悉ImageMagick源代码后,我找到了一种将公式应用于失真的方法。借助OpenCV remap函数,这是使图像变形的一种方式:

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,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()

与使用ImageMagick的 convert -implode 函数具有相同的效果。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...