gpt4 book ai didi

python - 在 Python,OpenCV 中将对象映射到圆

转载 作者:行者123 更新时间:2023-12-02 16:19:19 25 4
gpt4 key购买 nike

给定一个包含分割对象的灰度图像的 numpy 数组。 numpy 数组的维度为 (32,32) .这个物体的背景编码为零,物体本身有一个介于 (0,255] 之间的数字。
示例(尺寸为 (7,7) ):

# Input
> np.array([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,1,2,3,0,0],[0,0,2,2,2,0,0],[0,0,1,2,3,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], dtype=np.uint8)

array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 2, 3, 0, 0],
[0, 0, 2, 2, 2, 0, 0],
[0, 0, 1, 2, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

numpy 数组中的对象可以具有任意形状。
我想拉伸(stretch)(扭曲)对象,使其变成一个圆形,而不管它以前的形状如何。圆圈应填满整个 32x32 数组。这些值应该是线性插值的。
示例(简化,没有线性插值):

# Desired output = Circle with linearly interpolated values
array([[0, 0, 0, 2, 0, 0, 0],
[0, 1, 1, 2, 3, 3, 0],
[0, 1, 1, 2, 3, 3, 0],
[2, 2, 2, 2, 2, 2, 2],
[0, 1, 2, 2, 3, 3, 0],
[0, 1, 2, 2, 3, 3, 0],
[0, 0, 0, 2, 0, 0, 0]], dtype=uint8)

我该怎么做。是否有一个 OpenCV 函数可以将对象扭曲为圆形?

最佳答案

让我们将您的问题分为 3 个步骤:

  • 将图像大小调整为 32x32
  • 将矩阵从正方形重新映射为圆形
  • 必要时修剪边缘并调整大小

  • 将图像大小调整为 32x32
    您可以使用 cv2.resize() 为您完成工作。它将执行所有必要的插值以使图像成为您想要的大小
    square = np.array([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,1,2,3,0,0],[0,0,2,2,2,0,0],[0,0,1,2,3,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], dtype=np.uint8)
    resized_image = cv2.resize(square, (32, 32))
    resize
    将矩阵从正方形重新映射为圆形
    从数学上讲,有很多方法可以创建从方阵到圆的变换。关于这个有一个非常有趣的话题 here .基本上,您必须定义一个函数以从一组点 [x, y] 出发。到另一组点 [u, v] ,Ch Fong 提到的一种可能的解决方案是:

    u = x √(x² + y² - x²y²) / √(x² + y²)

    v = y √(x² + y² - x²y²) / √(x² + y²)


    您可以将此等式与 cv2.remap() 一起使用函数来获得你想要的转换。但是有一个工具叫做 squircle 为您完成所有工作!通过阅读他们的文档,您可以编写一个简单的代码来进行这种转换:
    导入:
    from squircle import to_circle 
    from PIL import Image
    打开图片后调用转换:
    circle = to_circle(square)
    remmaped
    必要时修剪边缘并调整大小
    现在,您只需从矩阵中修剪所有零,然后再次调整它的大小,以便所有 32x32 矩阵中都有内容。描述了您可以使用的解决方案 here在哪里 circle是您重新映射的图像。在您剪切所有初始和最终的行和列都为零后,您必须再次将其调整为 32x32。
    coords = np.argwhere(circle)
    x_min, y_min = coords.min(axis=0)
    x_max, y_max = coords.max(axis=0)
    b = cropped = circle[x_min:x_max+1, y_min:y_max+1]
    resized_cropped_image = cv2.resize(cropped, (32, 32))
    trimmed
    完整示例

    示例 1 - 使用您的数组:
    yourexample

    示例 2 - 使用另一个图像:
    myexample
    您可以找到 a Jupyter Notebook for this example在我的 Github 页面中。完整的代码可以在下面看到
    import numpy as np
    import cv2
    import matplotlib.pyplot as plt
    from squircle import to_circle, to_square
    from PIL import Image

    square = np.asarray(Image.open('Picture.png').convert('L'))
    #square = np.array([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,1,2,3,0,0],[0,0,2,2,2,0,0],[0,0,1,2,3,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], dtype=np.uint8)
    resized_image = cv2.resize(square, (32, 32))

    circle = to_circle(resized_image)

    coords = np.argwhere(circle)
    x_min, y_min = coords.min(axis=0)
    x_max, y_max = coords.max(axis=0)
    b = cropped = circle[x_min:x_max+1, y_min:y_max+1]
    resized_cropped_image = cv2.resize(cropped, (32, 32))


    fig, axs = plt.subplots(2, 2, figsize=(10,10))

    axs[0, 0].imshow(square)
    axs[0, 0].set_title('Original')

    axs[0, 1].imshow(resized_image)
    axs[0, 1].set_title('Resized to 32x32')

    axs[1, 0].imshow(circle)
    axs[1, 0].set_title('Remapped to cicle')

    axs[1, 1].imshow(resized_cropped_image)
    axs[1, 1].set_title('Trimmed')

    关于python - 在 Python,OpenCV 中将对象映射到圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61913732/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com