把圆变成正方形。解决方法:挤压包装

2024-04-28 05:13:44 发布

您现在位置:Python中文网/ 问答频道 /正文

OpenCV/Python相关:

给定一张圆形对象的照片,如何在调整表面积的同时将该对象展平,以下是输入的示例图像:

Soccer ball

这类似于调整摄影机扭曲(将圆形对象转换为平面对象),但在这种情况下,扭曲来自对象本身,而不是摄影机

Distorted image

Undistorted image

任何建议都会有帮助。谢谢大家!

编辑:这个包裹正是我需要的,谢谢fmw42


Tags: 对象图像image示例情况圆形opencv照片
1条回答
网友
1楼 · 发布于 2024-04-28 05:13:44

下面是Python/OpenCV中的一个解决方案。它创建转换映射,定义从输出到输入的方程,并使用cv2.remap()应用它们。方程来自椭圆网格映射方法的https://arxiv.org/pdf/1509.06344.pdf

输入:

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 1
for y in range(h):
    Y = (y - ycent)/ycent
    for x in range(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()

结果:

enter image description here

下面是另一个例子:

输入:

enter image description here

结果:

enter image description here

下面是第三个例子:

输入:

enter image description here

结果:

enter image description here

添加

以下是基于上述参考中简单拉伸方程的替代方法:

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 x
for y in range(h):
    Y = (y - ycent)/ycent
    for x in range(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()

输入:

enter image description here

结果:

enter image description here

输入:

enter image description here

结果:

enter image description here

输入:

enter image description here

结果:

enter image description here

相关问题 更多 >