I have an exercise to transform an image to the one have light tunnel effect like this.
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.
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!
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)