NumPy 2.x 完全指南【二十一】元素重排操作

1. 翻转

1.1 fliplr

numpy.flip: 沿指定轴翻转数组元素顺序,返回视图,共享原数组内存。

函数定义:

def flip(m, axis=None)

参数说明:

  • m:输入的数组(支持任意维度)。
  • axis:指定翻转的轴(整数或元组)。若为 None,则默认翻转所有轴。

示例 1 ,翻转一维数组:

import numpy as np

# 一维数组
arr_1d = np.array([1, 2, 3])
flipped_1d = np.flip(arr_1d)
print(flipped_1d)  # [3 2 1]
# 输出:
# [3 2 1]

一维数组只有一个 0 轴,没有指定 axis 参数时(None)也就是沿着 0 轴进行翻转,很容易理解,就是掉了个头:
在这里插入图片描述
二维数组有 0 轴和 1 轴,没有指定 axis 参数时,需要依次沿着所有的轴进行翻转:

  • 首先是 0 轴,当前维度的元素是行,需要翻转所有行。
  • 接着是 1 轴,当前维度的元素是列,需要翻转所有列。

在这里插入图片描述
示例 2 ,翻转二维数组:

# 二维数组
arr_2d = np.array([[1, 2],
                   [3, 4]])
flipped_2d = np.flip(arr_2d)
print(flipped_2d)
# 输出:
# [[4 3]
#  [2 1]]

# 中间过程:O 轴
# [[3 4]
#  [1 2]]

三维数组有 012 轴,也是按照同样的规则翻转:
在这里插入图片描述
示例 3 ,翻转三维数组:

# 三维数组
arr_3d = np.arange(8).reshape(2, 2, 2)
print(arr_3d)
# 输出:
# [[[0 1]
#   [2 3]]
#
#  [[4 5]
#   [6 7]]]
flipped = np.flip(arr_3d)
print(flipped)
# 输出:
# [[[7 6]
#   [5 4]]
#
#  [[3 2]
#   [1 0]]]

# 中间过程:O 轴
# [[[4 5]
#   [6 7]]
#
#  [[0 1]
#   [2 3]]]


# 中间过程:1 轴
# [[[6 7]
#   [4 5]]
#
#  [[2 3]
#   [0 1]]]

axis 是可选参数,用于指定翻转的维度,默认为 None(反转所有轴),可以是整数或元组类型。

示例 4 ,指定在一个轴上翻转:

# 二维数组
arr_2d = np.array([[1, 2],
                   [3, 4]])
flipped_2d = np.flip(arr_2d, axis=1)  # 列
print(flipped_2d)
# 输出:
# [[2 1]
#  [4 3]]

# 三维数组
arr_3d = np.arange(8).reshape(2, 2, 2)
print(arr_3d)
# 输出:
# [[[0 1]
#   [2 3]]
#
#  [[4 5]
#   [6 7]]]
flipped = np.flip(arr_3d, axis=1)  # 行
print(flipped)
# 输出:
# [[[2 3]
#   [0 1]]
#
#  [[6 7]
#   [4 5]]]

示例 5 ,指定在两个轴上翻转:

# 三维数组
arr_3d = np.arange(8).reshape(2, 2, 2)
print(arr_3d)
# 输出:
# [[[0 1]
#   [2 3]]
#
#  [[4 5]
#   [6 7]]]
flipped = np.flip(arr_3d, axis=(0, 1))  # 层、行
print(flipped)
# 输出:
# [[[6 7]
#   [4 5]]
#
#  [[2 3]
#   [0 1]]]

# 中间过程:O 轴
# [[[4 5]
#   [6 7]]
#
#  [[0 1]
#   [2 3]]]

在计算机视觉中,就可以使用翻转函数实现翻转图像:
在这里插入图片描述
完整代码如下:

import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import platform


# 跨平台字体配置方案
def config_chinese_font():
    """自动适配不同操作系统的中文字体配置"""
    system = platform.system()

    # 候选字体列表(按优先级排序)
    font_candidates = {
        'Windows': ['Microsoft YaHei', 'SimHei'],  # 微软雅黑/黑体
        'Darwin': ['Arial Unicode MS', 'Songti SC'],  # MacOS字体
        'Linux': ['WenQuanYi Zen Hei']  # 文泉驿字体
    }

    # 根据系统类型选择候选字体
    fonts = font_candidates.get(system, ['sans-serif'])

    try:
        # 自动检测已安装字体
        available_fonts = [f.name for f in fm.fontManager.ttflist]
        valid_fonts = [f for f in fonts if f in available_fonts]

        if valid_fonts:
            plt.rcParams['font.sans-serif'] = valid_fonts
            print(f"已设置中文字体: {valid_fonts[0]}")
        else:
            raise RuntimeError("未找到中文字体")

    except Exception as e:
        print(f"字体自动配置失败: {str(e)}, 将使用默认字体")

    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


def load_image(path):
    """加载图像文件并转换颜色空间"""
    image = cv2.imread(path)
    if image is None:
        raise FileNotFoundError(f"图像文件 {path} 未找到")
    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)


def plot_images(images, titles):
    """可视化图像(自动处理中文标题)"""
    plt.figure(figsize=(15, 5))

    for i, (img, title) in enumerate(zip(images, titles)):
        plt.subplot(1, 3, i + 1)
        plt.imshow(img)
        plt.title(title, fontsize=12)  # 使用已配置的字体
        plt.axis('off')

    plt.tight_layout()
    plt.show()


def main(image_path):
    # 初始化字体配置
    config_chinese_font()

    # 加载并处理图像
    try:
        original = load_image(image_path)
        print(f"成功加载图像: {original.shape} (HxWxC)")

        # 随机水平翻转 (50%概率)
        if np.random.rand() > 0.5:
            h_flip = np.flip(original, axis=1)
            flip_type = "水平翻转"
        else:
            h_flip = original.copy()
            flip_type = "原始图像"

        # 组合翻转
        combined_flip = np.flip(h_flip, axis=(0, 1))

        # 可视化结果
        plot_images(
            [original, h_flip, combined_flip],
            ["原始图像", flip_type, "组合翻转 (180度)"]
        )

    except Exception as e:
        print(f"处理失败: {str(e)}")


if __name__ == "__main__":
    # 使用实际图片路径
    main("QQ20250416-144551.jpg")  # 替换为您的图片路径

1.2 fliplr

numpy.fliplr():沿水平方向(列方向,即 axis=1)左右翻转二维及以上数组的元素(返回原数组的视图)。

函数定义:

def fliplr(m)

参数说明:

  • m:输入数组,必须至少是二维的。

等价操作:

  • m[:, ::-1]:通过切片语法直接反转列顺序。
  • np.flip(m, axis=1):使用更通用的 flip 函数指定轴。

示例 1 ,翻转一维数组会报错:

A = np.array([1, 2, 3,4, 5, 6])
B = np.fliplr(A) # ValueError: Input must be >= 2-d.

示例 2 ,对于二维数组,相当于镜像翻转每一行:

A = np.array([[1, 2, 3],
              [4, 5, 6]])

B = np.fliplr(A)
print(B)
# 输出:
# [[3 2 1]
#  [6 5 4]]

示例 3 ,对高维数组(如三维),仅在第二个轴(列方向)翻转,其他维度保持不变:

C = np.arange(12).reshape(2, 3, 2)  # 形状 (2,3,2)
D = np.fliplr(C)

print("原数组 C:\n", C)
print("翻转后 D:\n", D)
# 输出:
# C: [[[ 0  1], [ 2  3], [ 4  5]],
#     [[ 6  7], [ 8  9], [10 11]]]
# D: [[[ 4  5], [ 2  3], [ 0  1]],
#     [[10 11], [ 8  9], [ 6  7]]]

1.3 flipud

numpy.flipud():沿垂直方向(行方向,即 axis=0)上下翻转数组的元素(返回原数组的视图)。

函数定义:

def flipud(m)

参数说明:

  • m:输入数组,必须至少是一维的。

等价操作:

  • m[::-1, ...]:通过切片语法直接反转列顺序。
  • np.flip(m, axis=0):使用更通用的 flip 函数指定轴。

示例 1 ,一维数组翻转:

arr_1d = np.array([1, 2, 3])
reversed_arr = np.flipud(arr_1d)
print(reversed_arr)  # 输出:[3 2 1]

示例 2 ,二维数组翻转:

import numpy as np

A = np.array([[1, 2, 3],
              [4, 5, 6]])

B = np.flipud(A)
print(B)
# 输出:
# [[4 5 6]
#  [1 2 3]]

示例 3 ,三维数组翻转:

C = np.arange(12).reshape(3, 2, 2)  # 形状 (3,2,2)
D = np.flipud(C)

print("原数组 C:\n", C)
print("翻转后 D:\n", D)
# 输出:
# C: [[[0  1], [2  3]],
#     [[4  5], [6  7]],
#     [[8  9], [10 11]]]
# D: [[[8  9], [10 11]],
#     [[4  5], [6  7]],
#     [[0  1], [2  3]]]

2. 滚动

2.1 roll

numpy.roll():沿指定轴循环滚动数组元素(返回新数组)。

函数定义:

numpy.roll(a, shift, axis=None)

参数说明:

  • a:输入数组。
  • shift:移动的步数。正数表示向轴的正方向(如右/下)移动,负数则反向。若为元组,需与 axis 参数一一对应。
  • axis:指定沿哪个轴滚动。默认为 None,此时数组被展平后滚动,再恢复原形状。

注意事项:

  • 元素在滚动时不会丢失,末尾元素从开头重新出现,实现“循环移位”。
  • 可同时沿多个轴滚动,每个轴独立操作。
  • 返回新数组,​不影响原数组。

示例 1 ,一维数组滚动:

x = np.arange(10)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(np.roll(x, 2))   # 输出:[8 9 0 1 2 3 4 5 6 7](右移2步)
print(np.roll(x, -2))  # 输出:[2 3 4 5 6 7 8 9 0 1](左移2步)

示例 2 ,二维数组滚动:

x2 = np.reshape(x, (2, 5))  # [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
print(np.roll(x2, 1, axis=0))
# 输出:
# [[5 6 7 8 9]
#  [0 1 2 3 4]]

示例 3 ,三维数组滚动:

print(np.roll(x2, 1, axis=1))
# 输出:
# [[4 0 1 2 3]
#  [9 5 6 7 8]]

示例 4 ,多轴同时滚动:

print(np.roll(x2, (1, -1), axis=(0, 1)))
# 输出:
# [[9 5 6 7 8]
#  [4 0 1 2 3]]

2.2 rot90

numpy.rot90():沿指定轴循环滚动数组元素(返回新数组)。

函数定义:

numpy.roll(a, shift, axis=None)

参数说明:

  • a:输入数组。
  • shift:移动的步数。正数表示向轴的正方向(如右/下)移动,负数则反向。若为元组,需与 axis 参数一一对应。
  • axis:指定沿哪个轴滚动。默认为 None,此时数组被展平后滚动,再恢复原形状。

注意事项:

  • 元素在滚动时不会丢失,末尾元素从开头重新出现,实现“循环移位”。
  • 可同时沿多个轴滚动,每个轴独立操作。
  • 返回新数组,​不影响原数组。

示例 1 ,一维数组滚动:

x = np.arange(10)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(np.roll(x, 2))   # 输出:[8 9 0 1 2 3 4 5 6 7](右移2步)
print(np.roll(x, -2))  # 输出:[2 3 4 5 6 7 8 9 0 1](左移2步)

示例 2 ,二维数组滚动:

x2 = np.reshape(x, (2, 5))  # [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
print(np.roll(x2, 1, axis=0))
# 输出:
# [[5 6 7 8 9]
#  [0 1 2 3 4]]

示例 3 ,三维数组滚动:

print(np.roll(x2, 1, axis=1))
# 输出:
# [[4 0 1 2 3]
#  [9 5 6 7 8]]

示例 4 ,多轴同时滚动:

print(np.roll(x2, (1, -1), axis=(0, 1)))
# 输出:
# [[9 5 6 7 8]
#  [4 0 1 2 3]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨 禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值