如何使用Python OpenCV创建这种桶形/径向变形?

w8biq8rn  于 2023-05-29  发布在  Python
关注(0)|答案(3)|浏览(510)

我正在用python / opencv编写一个定制的虚拟现实耳机。我需要能够扭曲的图像,以创建“桶形失真”/“径向失真”的效果。
一些图像来解释:

我已经有了想要使用并向用户显示的source_image,并且已经将它们并排放置。现在我只需要像out = cv2.createBarrelDistortion(source_image, params)这样的东西。(我不介意调整一些参数,比如失真中心、失真大小等,这样我就可以让它看起来适合我得到的任何定制镜头。)
任何帮助非常感谢!

kninwzqo

kninwzqo1#

下面是如何在Python Wand 0.5.9中实现的
http://docs.wand-py.org/en/0.5.9/index.html
输入:

from wand.image import Image
import numpy as np
import cv2

with Image(filename='checks.png') as img:
    print(img.size)
    img.virtual_pixel = 'transparent'
    img.distort('barrel', (0.2, 0.0, 0.0, 1.0))
    img.save(filename='checks_barrel.png')
    # convert to opencv/numpy array format
    img_opencv = np.array(img)

# display result with opencv
cv2.imshow("BARREL", img_opencv)
cv2.waitKey(0)

结果:

请参阅https://imagemagick.org/Usage/distorts/#barrel以获取相同的示例和参数讨论。
参见https://hackaday.io/project/12384-autofan-automated-control-of-air-flow/log/41862-correcting-for-lens-distortions了解Python/OpenCV方法。

4ktjp1zp

4ktjp1zp2#

我将使用scipy,但仅用于插值:

import numpy as np
from matplotlib import pyplot as plt

import scipy.ndimage

....

#img: input image

# adjust k_1 and k_2 to achieve the required distortion
k_1 = 0.2
k_2 = 0.05

#img = imread("...")

h,w = [99,100] # img size

x,y = np.meshgrid(np.float32(np.arange(w)),np.float32(np.arange(h))) # meshgrid for interpolation mapping

# center and scale the grid for radius calculation (distance from center of image)
x_c = w/2 
y_c = h/2 
x = x - x_c
y = y - y_c
x = x/x_c
y = y/y_c

radius = np.sqrt(x**2 + y**2) # distance from the center of image

m_r = 1 + k_1*radius + k_2*radius**2 # radial distortion model

# apply the model 
x= x * m_r 
y = y * m_r

# reset all the shifting
x= x*x_c + x_c
y = y*y_c + y_c

distorted = scipy.ndimage.map_coordinates(img, [y.ravel(),x.ravel()])
distorted.resize(img.shape)

....
我们使用的是一个简单的模型,m_r因子乘以每个x,y,当它将点移得更远时,会给出一个拉伸。最后对畸变点进行插值得到图像。

vzgqcmou

vzgqcmou3#

我们可以用Sankalp Bhamare的Barrel实现中的PILImageOps.deform()替换scipy.ndimage.map_coordinates(),以获得相同的期望失真:

from PIL import ImageOps

class BarrelDeformer:

    def transform(self, x, y):
        # center and scale the grid for radius calculation (distance from center of image)
        x_c, y_c = w / 2, h / 2 
        x = (x - x_c) / x_c
        y = (y - y_c) / y_c
        radius = np.sqrt(x**2 + y**2) # distance from the center of image
        m_r = 1 + k_1*radius + k_2*radius**2 # radial distortion model
        # apply the model 
        x, y = x * m_r, y * m_r
        # reset all the shifting
        x, y = x*x_c + x_c, y*y_c + y_c
        return x, y

    def transform_rectangle(self, x0, y0, x1, y1):
        return (*self.transform(x0, y0),
                *self.transform(x0, y1),
                *self.transform(x1, y1),
                *self.transform(x1, y0),
                )

    def getmesh(self, img):
        self.w, self.h = img.size
        gridspace = 20
        target_grid = []
        for x in range(0, self.w, gridspace):
            for y in range(0, self.h, gridspace):
                target_grid.append((x, y, x + gridspace, y + gridspace))
        source_grid = [self.transform_rectangle(*rect) for rect in target_grid]
        return [t for t in zip(target_grid, source_grid)]
    
# adjust k_1 and k_2 to achieve the required distortion
k_1 = 0.2
k_2 = 0.05
im = Image.open('house.png')
im.putalpha(255)
w, h = im.size
im_deformed = ImageOps.deform(im, BarrelDeformer())
plt.figure(figsize=(12,5))
plt.imshow(np.hstack((np.array(im), np.array(im_deformed)))), plt.axis('off')
plt.title('The original and the deformed image', size=20)
plt.show()

相关问题