opencv Python不规则形状的图像变形为圆形

vnjpjtjt  于 2023-10-24  发布在  Python
关注(0)|答案(1)|浏览(141)

我想采取一个不规则形状的png图像与透明的背景,并将其扭曲成一个圆圈。
内容:图像将不得不被投射到一个半球的外部,通过拉伸它来完全填满一个圆似乎是一个很好的第一步。
下面的图片显示了我为此采取的两个步骤:

我的进攻计划如下:
1.将图像调整为正方形
1.获取图像的轮廓作为np数组
1.创建一个与图像直径相同、点数与轮廓相同的圆
1.使用findHomography获取变换矩阵
1.使用此矩阵扭曲源图像

def image_to_circle(filename: str):
    source_image = cv2.imread(filename)
    source_gray = cv2.cvtColor(source_image, cv2.COLOR_BGR2GRAY)

    # resize image and grayscale image to a square
    height, width = source_gray.shape
    dimension = min(width, height)
    source_image = cv2.resize(source_image, (dimension, dimension))
    source_gray = cv2.resize(source_gray, (dimension, dimension))

    # find the source contour
    contours, _ = cv2.findContours(
        source_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
    source_contour = max(contours, key=cv2.contourArea)

    radius = dimension / 2
    target_contour = generate_circle_points(radius, len(source_contour))

    # compute the perspective transformation matrix
    homography_matrix, _ = cv2.findHomography(source_contour, target_contour)

    # warp the source image to the destination based on the homography matrix
    warped_image = cv2.warpPerspective(
        source_image, homography_matrix, (dimension, dimension)
    )

    cv2.imwrite("warped-" + filename, warped_image)
def generate_circle_points(radius, num_points):
    angles = np.linspace(0, 2 * np.pi, num_points)

    x = radius * np.cos(angles)
    y = radius * np.sin(angles)

    return np.column_stack((x, y))

然而,这并不起作用,将其视为输入图像:

导致以下输出:

我猜warpPerspective的工作方式与我预期的不一样?

9fkzdhlc

9fkzdhlc1#

下面是如何在Python/OpenCV中将一个正方形图像变形到一个球体上。

  • 读取输入
  • 获取中心坐标并设置半径
  • 设置x,y和掩码黑色数组为浮点数
  • 对于输出图像中的每个x,y像素,计算输入的逆变换
  • 应用重新Map来进行变形
  • 使用圆形面具
  • 保存结果

输入:

import numpy as np
import cv2
import math

img = cv2.imread("lena.jpg")

# set gain
gain = 1.5

# set background color
bgcolor = (0,0,0)

# get dimensions
h, w = img.shape[:2]
xcent = w / 2
ycent = h / 2
rad = min(xcent,ycent)

# set up the x and y maps as float32
map_x = np.zeros((h, w), np.float32)
map_y = np.zeros((h, w), np.float32)
mask = np.zeros((h, w), np.uint8)

# create map with the spherize distortion formula --- arcsin(r)
# xcomp = arcsin(r)*x/r; ycomp = arsin(r)*y/r
for y in range(h):
    Y = (y - ycent)/ycent
    for x in range(w):
        X = (x - xcent)/xcent
        R = math.hypot(X,Y)
        if R == 0:
            map_x[y, x] = x
            map_y[y, x] = y
            mask[y,x] = 255
        elif R > 1:
            map_x[y, x] = x
            map_y[y, x] = y
            mask[y,x] = 0
        elif gain >= 0:
            map_x[y, x] = xcent*X*math.pow((2/math.pi)*(math.asin(R)/R), gain) + xcent
            map_y[y, x] = ycent*Y*math.pow((2/math.pi)*(math.asin(R)/R), gain) + ycent
            mask[y,x] = 255
        elif gain < 0:
            gain2 = -gain
            map_x[y, x] = xcent*X*math.pow((math.sin(math.pi*R/2)/R), gain2) + xcent
            map_y[y, x] = ycent*Y*math.pow((math.sin(math.pi*R/2)/R), gain2) + ycent
            mask[y,x] = 255

# do the remap  this is where the magic happens
result = cv2.remap(img, map_x, map_y, cv2.INTER_LINEAR, borderMode = cv2.BORDER_REFLECT_101, borderValue=(0,0,0))

# process with mask
result2 = result.copy()
result2[mask==0] = bgcolor

# save results
cv2.imwrite("lena_spherize_A.jpg", result)
cv2.imwrite("lena_spherize_B.jpg", result2)

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

设盲前结果:

掩蔽后的结果:

注:增加增益,增加球面失真

相关问题