Python获取坐标的常用方法

文章目录

  • 一、列表
    • 1.1、列表索引
    • 1.2、枚举索引
    • 二、numpy 数组
      • 2.1、数组索引
      • 2.2、乘法运算:image * mask
      • 2.3、条件索引
        • 2.3.1、np.argwhere():返回满足条件的元素的坐标(数组表示)
        • 2.3.2、np.where():返回满足条件的元素的索引(元组表示)
        • 2.3.3、np.nonzero():返回数组中非零元素的索引(元组表示)
        • 2.3.4、np.indices():返回数组中每个维度上索引值的数组(元组表示)
        • 2.3.5、np.extract():提取数组中满足条件的元素并返回一维数组
        • 实战一:获取每一列的最小值:np.min(coordinates, axis=0)
        • 实战二:提取坐标(时耗优化)
        • 实战三:数据归一化到[0, 255] + 数据类型转换为uint8

          一、列表

          1.1、列表索引

          my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
          row_index = 1
          column_index = 2
          value_at_index = my_list[row_index][column_index]
          print(f"列表索引: 在位置 ({row_index}, {column_index}) 的值是 {value_at_index}")
          # 列表索引: 在位置 (1, 2) 的值是 6
          

          1.2、枚举索引

          my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
          for row_index, row_list in enumerate(my_list):    # 使用 enumerate 遍历行
              for col_index, value in enumerate(row_list):  # 使用 enumerate 遍历列
                  print(f"在位置 ({row_index}, {col_index}) 的值是 {value}")
          """
          在位置 (0, 0) 的值是 1
          在位置 (0, 1) 的值是 2
          在位置 (0, 2) 的值是 3
          在位置 (1, 0) 的值是 4
          在位置 (1, 1) 的值是 5
          在位置 (1, 2) 的值是 6
          在位置 (2, 0) 的值是 7
          在位置 (2, 1) 的值是 8
          在位置 (2, 2) 的值是 9
          """
          

          二、numpy 数组

          2.1、数组索引

          import numpy as np
          my_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
          row_index = 1
          column_index = 2
          value_at_index = my_array[row_index, column_index]
          print(f"数组索引: 在位置 ({row_index}, {column_index}) 的值是 {value_at_index}")
          # 数组索引: 在位置 (1, 2) 的值是 6
          

          2.2、乘法运算:image * mask

          使用 * 操作符对图像和掩码进行逐元素的乘法运算,两者的形状必须相同。

          import numpy as np
          image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
          # mask = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]).astype(bool)  # 指定索引
          mask = (image > 4)  # 条件索引
          result = image * mask  # 获取image中mask对应为True的图像(其余置零)
          print(result)
          """
          [[0 0 0]
           [0 5 6]
           [7 8 9]]
          """
          

          2.3、条件索引

          2.3.1、np.argwhere():返回满足条件的元素的坐标(数组表示)

          import numpy as np
          arr = np.array([[1, 0, 3], [4, 0, 6], [7, 8, 0]])
          coordinates = np.argwhere(arr != 0)
          print(coordinates)
          """
          [[0 0]
           [0 2]
           [1 0]
           [1 2]
           [2 0]
           [2 1]]
          """
          

          2.3.2、np.where():返回满足条件的元素的索引(元组表示)

          import numpy as np
          arr = np.array([[1, 0, 3], [4, 0, 6], [7, 8, 0]])
          indices = np.where(arr != 0)
          coordinates = np.array(np.nonzero(arr)).T
          print(indices)
          print(coordinates)
          """
          (array([0, 0, 1, 1, 2, 2], dtype=int64), array([0, 2, 0, 2, 0, 1], dtype=int64))
          [[0 0]
           [0 2]
           [1 0]
           [1 2]
           [2 0]
           [2 1]]
          """
          

          2.3.3、np.nonzero():返回数组中非零元素的索引(元组表示)

          import numpy as np
          arr = np.array([[1, 0, 3], [4, 0, 6], [7, 8, 0]])
          indices = np.nonzero(arr)  # 返回数组中非零元素的索引
          coordinates = np.array(np.nonzero(arr)).T  # 返回数组中非零元素的坐标
          print(indices)
          print(coordinates)
          """
          (array([0, 0, 1, 1, 2, 2], dtype=int64), array([0, 2, 0, 2, 0, 1], dtype=int64))
          [[0 0]
           [0 2]
           [1 0]
           [1 2]
           [2 0]
           [2 1]]
          """
          

          2.3.4、np.indices():返回数组中每个维度上索引值的数组(元组表示)

          import numpy as np
          image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
          coordinates = np.indices(image.shape)  # 获取图像所有坐标
          flat_coordinates = np.vstack([coord.flatten() for coord in coordinates]).T  # 将坐标展平为一维数组(获取图像中所有像素的坐标)
          print(flat_coordinates)
          """
          [[0 0]
           [0 1]
           [0 2]
           [1 0]
           [1 1]
           [1 2]
           [2 0]
           [2 1]
           [2 2]]
          """
          

          2.3.5、np.extract():提取数组中满足条件的元素并返回一维数组

          import numpy as np
          import matplotlib.pyplot as plt
          # 生成一个随机的图像数据
          np.random.seed(42)
          ImageStack = np.random.randint(0, 256, size=(10, 10), dtype=np.uint8)
          threshold = 150  # 设置阈值
          # 使用 np.extract 函数提取满足条件的元素
          condition = ImageStack > threshold
          image_extracted = np.extract(condition, ImageStack)
          print("提取的元素个数", len(image_extracted))
          # 恢复原图的形状
          image_extracted_reshaped = np.zeros_like(ImageStack, dtype=np.uint8)
          image_extracted_reshaped[condition] = image_extracted
          # 显示原始图像、处理后的图像以及提取得到的元素的图像
          plt.figure(figsize=(15, 5))
          plt.subplot(1, 3, 1)
          plt.imshow(ImageStack, cmap='gray', vmin=0, vmax=255)
          plt.title('ImageStack')
          plt.subplot(1, 3, 2)
          plt.imshow(image_extracted_reshaped, cmap='gray', vmin=0, vmax=255)
          plt.title(f'image_extracted_reshaped')
          plt.subplot(1, 3, 3)
          plt.plot(image_extracted, marker='o')
          plt.title(f'image_extracted')
          plt.show()
          

          实战一:获取每一列的最小值:np.min(coordinates, axis=0)

          import numpy as np
          my_array = np.zeros((10, 10, 10))  # 随机生成0和1整数的数组
          my_array[2:4, 2:3, 5:9] = 1  # 指定位置填充值
          nonzero_coordinates = np.argwhere(my_array != 0)  # 获取非零元素的坐标
          min_coords_nonzero = np.min(nonzero_coordinates, axis=0)  # 获取所有列中每一列的最小值(axis=0 表示沿着第一个轴(即列轴)进行操作。)
          max_coords_nonzero = np.max(nonzero_coordinates, axis=0)  # 获取所有列中每一列的最大值(axis=0 表示沿着第一个轴(即列轴)进行操作。)
          print("最小坐标值:", min_coords_nonzero)
          print("最大坐标值:", max_coords_nonzero)
          # 最小坐标值: [2 2 5]
          # 最大坐标值: [3 2 8]
          

          实战二:提取坐标(时耗优化)

          import numba
          import numpy as np
          import time
          @numba.jit()
          def where(input_data, output_data):
              # output_coordinate = []
              num = 0
              for z in range(input_data.shape[0]):
                  for y in range(input_data.shape[1]):
                      for x in range(input_data.shape[2]):
                          if input_data[z, y, x]:
                              # output_coordinate.append([z, y, x])  # 时耗增加
                              output_data[num][0] = z
                              output_data[num][1] = y
                              output_data[num][2] = x
                              num += 1
              # return output_coordinate   # 时耗增加
              return num
          if __name__ == "__main__":
              np.random.seed(42)
              start_time = time.time()
              ImageStack11 = np.random.randint(0, 256, size=(1024, 1024, 2024), dtype=np.uint8)  # 生成一个随机的图像数据
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              #######################################
              start_time = time.time()
              ImageStack22 = np.random.randint(0, 256, size=(1024, 1024, 2024)).astype(np.uint8)   # 生成一个随机的图像数据
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              """
              总耗时:1.2737秒
              总耗时:2.8277秒
              """
              ImageStack = ImageStack11.copy()
              threshold = 50  # 设置阈值
              mask = (ImageStack < threshold)
              print("非零数量", np.count_nonzero(mask))
              ####################################################################
              start_time = time.time()
              output_data = np.zeros((ImageStack.shape[0]*ImageStack.shape[1]*ImageStack.shape[2], 3), dtype=ImageStack.dtype)  # 创建一个与 arr 具有相同形状和数据类型的全零数组
              num = where(mask, output_data)  # 找到mask的非零元素的坐标
              coordinate1 = output_data[0:num]
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              ####################################################################
              start_time = time.time()
              coordinate2 = np.argwhere(mask)  # 找到mask的非零元素的坐标
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              ####################################################################
              start_time = time.time()
              index3 = np.where(mask)  # (1)找到mask的非零元素的索引
              # coordinates = np.array(c1).T
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              ####################################################################
              start_time = time.time()
              coordinate4 = np.array(np.where(mask)).T  # (1)找到mask的非零元素的索引(2)索引转坐标
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              ####################################################################
              start_time = time.time()
              coordinate5 = np.array(np.nonzero(mask)).T  # (1)找到mask的非零元素的索引(2)索引转坐标
              print(f"总耗时:{time.time() - start_time:.4f}秒")
              """
              非零数量 209707383
              总耗时:2.1542秒     Numba加速
              总耗时:5.0483秒     np.argwhere(mask)
              总耗时:3.8276秒     np.where(mask)
              总耗时:5.1381秒     np.array(np.where(mask)).T
              总耗时:5.1958秒     np.array(np.nonzero(mask)).T
              """
          ####################################################################
          # (2)根据条件进行索引与赋值(正方向)
          ImageStack2 = ImageStack.copy()
          start_time = time.time()
          ImageStack2[np.where(ImageStack2 < threshold)] = 0      # (1)条件索引(2)坐标获取(3)再赋值
          end_time = time.time()
          runtime2 = end_time - start_time
          ImageStack3 = ImageStack.copy()
          start_time = time.time()
          ImageStack3[ImageStack3 < threshold] = 0                # (2)条件索引(2)再赋值(速度最快,但无法获取坐标)
          end_time = time.time()
          runtime3 = end_time - start_time
          print(f"方法二:总运行时间: {runtime2:.2f} 秒")
          print(f"方法三:总运行时间: {runtime3:.2f} 秒")
          """
          方法二:总运行时间: 0.56 秒
          方法三:总运行时间: 0.07 秒
          """
          ####################################################################
          # (3)根据条件进行索引与赋值(反方向)
          ImageStack2 = ImageStack.copy()
          start_time = time.time()
          ImageStack2[np.where(ImageStack2 > threshold)] = 0      # (1)条件索引(2)坐标获取(3)再赋值
          end_time = time.time()
          runtime2 = end_time - start_time
          ImageStack3 = ImageStack.copy()
          start_time = time.time()
          ImageStack3[ImageStack3 > threshold] = 0                # (2)条件索引(2)再赋值(速度最快,但无法获取坐标)
          end_time = time.time()
          runtime3 = end_time - start_time
          print(f"方法二:总运行时间: {runtime2:.2f} 秒")
          print(f"方法三:总运行时间: {runtime3:.2f} 秒")
          """
          方法二:总运行时间: 0.18 秒
          方法三:总运行时间: 0.07 秒
          """
          

          实战三:数据归一化到[0, 255] + 数据类型转换为uint8

          import numpy as np
          np.random.seed(42)  # 设置种子点
          # (1)生成一个随机的uintt16数据类型的图像[0, 65535]
          ImageStack = np.random.randint(0, 65535, size=(10, 10), dtype=np.uint16)
          # (2)数据归一化到[0, 255] + 数据类型转换为uint8
          normalized_data = ((ImageStack - ImageStack.min()) / (ImageStack.max()- ImageStack.min()) * 255).astype(np.uint8)
          print(ImageStack.min(), ImageStack.max())
          print(normalized_data.min(), normalized_data.max())
          # import napari
          # viewer = napari.Viewer()
          # viewer.add_image(ImageStack, name='ImageStack', colormap='gray')
          # viewer.add_image(normalized_data, name='normalized_data', colormap='gray')
          # napari.run()