numpy -- np.concatenat 学习笔记

np.concatenate是NumPy中用于连接数组的函数。以下是详细说明:

基本语法

numpy.concatenate((a1, a2, ...), axis=0, out=None, dtype=None)
 
  

参数说明

  • arrays: 要连接的数组序列(元组或列表)
  • axis: 连接轴的方向,默认为0

        在NumPy中,axis指定了操作的维度方向:

  1. axis=0: 第一个维度(行方向)
  2. axis=1: 第二个维度(列方向)
  3. axis=2: 第三个维度(深度/通道方向)
  • out: 输出数组(可选)
  • dtype: 输出数据类型(可选)

基本用法示例

1. 一维数组连接

import numpy as np

# 创建两个一维数组
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# 连接数组
result = np.concatenate([arr1, arr2])
print(result)  # [1 2 3 4 5 6]

# 连接多个数组
arr3 = np.array([7, 8, 9])
result = np.concatenate([arr1, arr2, arr3])
print(result)  # [1 2 3 4 5 6 7 8 9]

2. 二维数组连接

# 创建两个二维数组
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

# 沿axis=0连接(垂直连接,增加行数)
vertical = np.concatenate([arr1, arr2], axis=0)
print("垂直连接:")
print(vertical)
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

# 沿axis=1连接(水平连接,增加列数)
horizontal = np.concatenate([arr1, arr2], axis=1)
print("水平连接:")
print(horizontal)
# [[1 2 5 6]
#  [3 4 7 8]]

3. 不同轴的连接

# 三维数组示例
arr1 = np.array([[[1, 2]], [[3, 4]]])
arr2 = np.array([[[5, 6]], [[7, 8]]])

print(f"原数组形状: {arr1.shape}")  # (2, 1, 2)

# axis=0连接(第一个维度)
concat_axis0 = np.concatenate([arr1, arr2], axis=0)
print(f"axis=0连接后形状: {concat_axis0.shape}")  # (4, 1, 2)

# axis=1连接(第二个维度)
concat_axis1 = np.concatenate([arr1, arr2], axis=1)
print(f"axis=1连接后形状: {concat_axis1.shape}")  # (2, 2, 2)

# axis=2连接(第三个维度)
concat_axis2 = np.concatenate([arr1, arr2], axis=2)
print(f"axis=2连接后形状: {concat_axis2.shape}")  # (2, 1, 4)

在图像处理中的应用

1. 添加Alpha通道

import cv2
import numpy as np

# 读取图像
img = cv2.imread('image.png')  # BGR图像
h, w, c = img.shape

# 创建Alpha通道
alpha = np.full((h, w, 1), 255, dtype=np.uint8)  # 完全不透明

# 添加Alpha通道,变成BGRA
img_with_alpha = np.concatenate([img, alpha], axis=2)

print(f"原图形状: {img.shape}")          # (h, w, 3)
print(f"添加Alpha后: {img_with_alpha.shape}")  # (h, w, 4)

2. 图像拼接

import cv2
import numpy as np

# 读取多张图像
img1 = cv2.imread('image1.png')
img2 = cv2.imread('image2.png')
img3 = cv2.imread('image3.png')

# 水平拼接图像
horizontal_concat = np.concatenate([img1, img2, img3], axis=1)

# 垂直拼接图像
vertical_concat = np.concatenate([img1, img2, img3], axis=0)

# 显示结果
cv2.imshow('Horizontal', horizontal_concat)
cv2.imshow('Vertical', vertical_concat)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 通道操作

# 分离和重组通道
img = cv2.imread('image.png')
b, g, r = cv2.split(img)

# 创建新的通道组合
# 只保留红色和绿色通道,蓝色通道置零
zero_channel = np.zeros_like(b)
rg_only = np.concatenate([zero_channel[..., np.newaxis], 
                         g[..., np.newaxis], 
                         r[..., np.newaxis]], axis=2)

# 交换红蓝通道(BGR to RGB)
rgb_img = np.concatenate([r[..., np.newaxis],
                         g[..., np.newaxis],
                         b[..., np.newaxis]], axis=2)

高级应用示例

1. 批量图像处理

def batch_concatenate_images(image_list, direction='horizontal'):
    """批量拼接图像"""
    if not image_list:
        return None
    
    # 确保所有图像尺寸一致(除了拼接维度)
    if direction == 'horizontal':
        axis = 1
        # 统一高度
        target_height = min(img.shape[0] for img in image_list)
        resized_images = []
        for img in image_list:
            if img.shape[0] != target_height:
                ratio = target_height / img.shape[0]
                new_width = int(img.shape[1] * ratio)
                resized = cv2.resize(img, (new_width, target_height))
                resized_images.append(resized)
            else:
                resized_images.append(img)
        
    else:  # vertical
        axis = 0
        # 统一宽度
        target_width = min(img.shape[1] for img in image_list)
        resized_images = []
        for img in image_list:
            if img.shape[1] != target_width:
                ratio = target_width / img.shape[1]
                new_height = int(img.shape[0] * ratio)
                resized = cv2.resize(img, (target_width, new_height))
                resized_images.append(resized)
            else:
                resized_images.append(img)
    
    return np.concatenate(resized_images, axis=axis)

# 使用示例
images = [cv2.imread(f'img{i}.png') for i in range(1, 4)]
result = batch_concatenate_images(images, 'horizontal')

2. 创建边框

def add_border(img, border_size=10, color=[255, 255, 255]):
    """为图像添加边框"""
    h, w = img.shape[:2]
    
    # 创建边框
    if len(img.shape) == 3:
        # 彩色图像
        top_bottom = np.full((border_size, w, 3), color, dtype=np.uint8)
        left_right = np.full((h, border_size, 3), color, dtype=np.uint8)
        
        # 添加上下边框
        with_tb = np.concatenate([top_bottom, img, top_bottom], axis=0)
        # 添加左右边框
        with_border = np.concatenate([left_right, with_tb, left_right], axis=1)
        
    else:
        # 灰度图像
        top_bottom = np.full((border_size, w), color[0], dtype=np.uint8)
        left_right = np.full((h, border_size), color[0], dtype=np.uint8)
        
        with_tb = np.concatenate([top_bottom, img, top_bottom], axis=0)
        with_border = np.concatenate([left_right, with_tb, left_right], axis=1)
    
    return with_border

# 使用示例
img = cv2.imread('image.png')
bordered_img = add_border(img, 20, [0, 0, 255])  # 红色边框

与其他连接函数的比较

1. np.vstack(垂直堆叠)

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

# 使用concatenate
result1 = np.concatenate([arr1, arr2], axis=0)

# 使用vstack(等效)
result2 = np.vstack([arr1, arr2])

print(np.array_equal(result1, result2))  # True

2. np.hstack(水平堆叠)

# 使用concatenate
result1 = np.concatenate([arr1, arr2], axis=1)

# 使用hstack(等效)
result2 = np.hstack([arr1, arr2])

print(np.array_equal(result1, result2))  # True

3. np.dstack(深度堆叠)

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

# 使用concatenate
arr1_3d = arr1[..., np.newaxis]
arr2_3d = arr2[..., np.newaxis]
result1 = np.concatenate([arr1_3d, arr2_3d], axis=2)

# 使用dstack(等效)
result2 = np.dstack([arr1, arr2])

print(np.array_equal(result1, result2))  # True

np.concatenate是最通用的数组连接函数,通过指定不同的axis参数可以实现各种连接方式,在图像处理中经常用于通道操作、图像拼接等场景。

你可能感兴趣的:(numpy,笔记,python)