Skip to content Skip to sidebar Skip to footer

Turning Circle Into Square. Solved: Squircle Package

OpenCV / Python related: Given a photo of a round object, how can you output that object flattened, while adjusting for surface area? Here is an example image of an input: Soccer b

Solution 1:

Here is a solution in Python/OpenCV. It creates transformation maps that define the equations from output back to input and applies them using cv2.remap(). The equations come from https://arxiv.org/pdf/1509.06344.pdf for the Elliptical Grid Mapping approach.

Input:

enter image description here

import numpy as np
import cv2
import math

# References:# https://arxiv.org/pdf/1509.06344.pdf# http://squircular.blogspot.com/2015/09/mapping-circle-to-square.html# Evaluate:# u = x*sqrt(1-y**2/2)# v = y*sqrt(1-x**2/2)# u,v are input circle coordinates and x,y are output square coordinates# read input
img = cv2.imread("rings.png")

# get dimensions and center
h, w = img.shape[:2]
xcent = w / 2
ycent = h / 2# set up the maps as float32 from output square (x,y) to input circle (u,v)
map_u = np.zeros((h, w), np.float32)
map_v = np.zeros((h, w), np.float32)

# create u and v maps where x,y is measured from the center and scaled from -1 to 1for y inrange(h):
    Y = (y - ycent)/ycent
    for x inrange(w):
        X = (x - xcent)/xcent
        map_u[y, x] = xcent * X * math.sqrt(1 - 0.5*Y**2) + xcent
        map_v[y, x] = ycent * Y * math.sqrt(1 - 0.5*X**2) + ycent

# do the remap
result = cv2.remap(img, map_u, map_v, cv2.INTER_LINEAR, borderMode = cv2.BORDER_REFLECT_101, borderValue=(0,0,0))

# save results
cv2.imwrite("rings_circle2square.png", result)

# display images
cv2.imshow('img', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:

enter image description here

Here is another example:

Input:

enter image description here

Result:

enter image description here

And here is a 3rd example:

Input:

enter image description here

Result:

enter image description here

ADDITION

Here is an alternate approach based upon the Simple Stretch equations in the reference above:

import numpy as np
import cv2
import math

# References:# https://arxiv.org/pdf/1509.06344.pdf# Simple stretch equations# read input
img = cv2.imread("rings.png")
#img = cv2.imread("ICM.png")#img = cv2.imread("soccerball_small.jpg")# get dimensions and center
h, w = img.shape[:2]
xcent = w / 2
ycent = h / 2# set up the maps as float32 from output square (x,y) to input circle (u,v)
map_u = np.zeros((h, w), np.float32)
map_v = np.zeros((h, w), np.float32)

# create u and v maps where x,y is measured from the center and scaled from -1 to 1# note: copysign(1,x) is signum(x) and returns 1 ,0, or -1 depending upon sign of xfor y inrange(h):
    Y = (y - ycent)/ycent
    for x inrange(w):
        X = (x - xcent)/xcent
        X2 = X*X
        Y2 = Y*Y
        XY = X*Y
        R = math.sqrt(X2+Y2)
        if R == 0:
            map_u[y, x] = xcent
            map_v[y, x] = ycent
        elif X2 >= Y2:
            map_u[y, x] = xcent * math.copysign(1, X) * X2/R + xcent
            map_v[y, x] = ycent * math.copysign(1, X) * XY/R + ycent
        else:
            map_u[y, x] = xcent * math.copysign(1, Y) * XY/R + xcent
            map_v[y, x] = ycent * math.copysign(1, Y) * Y2/R + ycent

# do the remap
result = cv2.remap(img, map_u, map_v, cv2.INTER_LINEAR, borderMode = cv2.BORDER_REFLECT_101, borderValue=(0,0,0))

# save results
cv2.imwrite("rings_circle2square2.png", result)
#cv2.imwrite("ICM_circle2square2.png", result)#cv2.imwrite("soccerball_small_circle2square2.png", result)# display images
cv2.imshow('img', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Input:

enter image description here

Result:

enter image description here

Input:

enter image description here

Result:

enter image description here

Input:

enter image description here

Result:

enter image description here

Post a Comment for "Turning Circle Into Square. Solved: Squircle Package"