简体   繁体   中英

Distortion effect using OpenCv-python

我想创建像螺旋,舒展,鱼眼,楔子状的水下和雪这样的其他效应失真效果的网站使用CV2库的蟒蛇。

I figured out fisheye distortion.

In OpenCV version 3.0 and above it is possible to perform it using cv2.fisheye.undistortImage() . I have the code in python if you need.

This is what I got for the following input image:

Input Image:

在此处输入图片说明

Distorted image:

在此处输入图片说明

The function accepts a matrix, which upon modification yield different distortions of the image.

UPDATE

In order to add a snowfall effect you can add some noise like Poisson noise.

Here is half of an answer. The cv2.remap function uses maps to choose a pixel from the source for each pixel in the destination. alkasm's answer to this: How do I use OpenCV's remap function? does a great job of defining the process, but glosses over the usefulness of those maps. If you can get creative in the maps, you can make any effect you want. Here is what I came up with.

The program starts by loading the image and resizing it. This is a convenience for a smaller screen. Then the empty maps are created.

The maps need to be the same dimensions as the image that is being processed, but with a depth of 1. If the resized original is 633 x 400 x 3, the maps both need to be 633 x 400.

When the remapping is done, cv2.remap will used the value at each coordinate in the maps to determine which pixel in the original to use in the destination. For each x,y in the destination, dest[x,y] = src[map1[x,y],map2[x,y]].

The simplest mapping would be if for every (x,y), map1(x,y)=x and map2(x,y)=y. This creates a 1-to-1 map, and the destination would match the source. In this example, a small offset is added to each value. The cosine function in the offset creates both positive and negative shifts, creating waves in the final image.

Note that creating the maps is slow, but the cv2.remap is fast. Once you have created the map, the cv2.remap is fast enough to be applied to frames of video.

    import numpy as np            #create waves
    import cv2
    import math

    # read in image and resize down to width of 400
    # load your image file here
    image = cv2.imread("20191114_154534.jpg")

    r = 400.0 / image.shape[1]
    dim = (400, int(image.shape[0] * r))

    # Perform the resizing of the image
    resized = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)

    # Grab the dimensions of the image and calculate the center
    # of the image  (center not needed at this time)
    (h, w, c) = resized.shape
    center = (w // 2, h // 2)

    # 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 simple maps with a modified assignment
    # the math modifier creates ripples.  increase the divisor for less waves, 
    # increase the multiplier for greater movement
    # this is where the magic is assembled
    for y in range(h):
        for x in range(w):
            flex_x[y,x] = x + math.cos(x/15) * 15
            flex_y[y,x] = y + math.cos(y/30) * 25


    # do the remap  this is where the magic happens      
    dst = cv2.remap(resized,flex_x,flex_y,cv2.INTER_LINEAR)


    #show the results and wait for a key
    cv2.imshow("Resized",resized)
    cv2.imshow("Flexed",dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Here is a replacement block to map out a fisheye in the middle of the image. Please look elsewhere for details on the math. Use this in place of the 2 for loops in the previous code.

As stated in the first half of my answer (see previous answer), the purpose of this block is to create 2 maps that work together to remap the source image into the destination image.

To create the two maps, this block sweeps through 2 for loops with the dimensions of the image. Values are calculated for the X and y maps (flex_x and flex_y). It starts with assigning each to simply x and y for a 1-to-1 replacement map. Then, if the radius (r) is between 0 and 1, the map for the tangential slide for the fisheye is applied and new flex_x and flex_y values are mapped.

Please see my other answer for more details.

    # create simple maps with a modified assignment
    # outside the bulge is normal, inside is modified
    # this is where the magic is assembled
    for y in range(h):
        ny = ((2*y-250)/(h-250))-1     #play with the 250's to move the y
        ny2 = ny*ny
        for x in range(w):
            nx = ((2*x-50)/(w-50))-1   #play with the 50's to move the x
            nx2 = nx*nx
            r = math.sqrt(nx2+ny2)
            flex_x[y,x] = x
            flex_y[y,x] = y
            if r>0 and r<1:
                nr1 = 1 - r**2
                nr2 = math.sqrt(nr1)
                nr = (r + (1.0-nr2)) / 2.0
                theta = math.atan2(ny,nx)
                nxn = nr*math.cos(theta)
                nyn = nr*math.sin(theta)
                flex_x[y,x] = (((nxn+1)*w)/2.0)
                flex_y[y,x] = (((nyn+1)*h)/2.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM