首页 > 解决方案 > 使用 Python OpenCV 的挤压/膨胀变形

问题描述

我想使用 Python OpenCV 在图像上应用捏合/凸出过滤器。结果应该是这个例子的某种形式:

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

我已阅读以下 stackoverflow 帖子,它应该是过滤器的正确公式:桶形/枕形失真的公式

但我正在努力在 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, 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()

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

标签: pythonopencvfilterdistortion

解决方案


在熟悉了 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, 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()

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


推荐阅读