Home > other >  How to create light tunnel transformation image
How to create light tunnel transformation image

Time:01-12

I have an exercise to transform an image to the one have light tunnel effect like this. enter image description here

enter image description here

My first idea is to select a region circle in the middle and every point outside of the circle will have the value of the circle's boundary point if the center point, boundary point, and the considered point are in the same line but the result is very poor. enter image description here

here is my code:

import numpy as np
import cv2 
import math 
import numpy as np
from google.colab.patches import cv2_imshow
from shapely.geometry import LineString
from shapely.geometry import Point

img = cv2.imread("./orig_img.png")
h,w,_ = img.shape
flex_x = np.zeros((h,w),np.float32)
flex_y = np.zeros((h,w),np.float32)

scale_y= 1
center_x, center_y = (w // 2, h // 2)
radius = 50
scale_x = 1

p = Point(center_x, center_y)
c = p.buffer(radius).boundary

for y in range(h):
    delta_y = scale_y * (y - center_y)
    for x in range(w):
        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:
            l = LineString([(center_x, center_y), (x,y)])
            i = c.intersection(l)
            new_x,new_y = round(i.coords[0][0]),round(i.coords[0][1])
            flex_x[y,x] = flex_x[new_y,new_x]
            flex_y[y,x] = flex_y[new_y,new_x]
            


dst = cv2.remap(img, flex_x, flex_y, cv2.INTER_LINEAR)

cv2_imshow(dst)

Does anyone have a better idea to do this or Can my code be fixed? , please help me! much appreciated!

CodePudding user response:

This takes cv.remap and some geometry.

You have trouble because you tried to draw lines. You wouldn't even need remap for that.

im = cv.imread("d1LU6.png")
(h,w) = im.shape[:2]

# some definitions
center = np.array([w/2, h/2])
radius = h / 5

i,j = np.mgrid[0:h, 0:w]
xymap = np.dstack([j,i]).astype(np.float32) # "identity" map

# coordinates relative to center
coords = (xymap - center)
# distance to center
dist = np.linalg.norm(coords, axis=2)
# touch only what's outside of the circle
mask = (dist >= radius)
# project onto circle (calculate unit vectors, move onto circle, then back to top-left origin)
xymap[mask] = coords[mask] / dist[mask,None] * radius   center

out = cv.remap(im, map1=xymap, map2=None, interpolation=cv.INTER_LINEAR)
# imshow(out)

out

  •  Tags:  
  • Related