You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量处理图像计算天顶角温度均值代码执行过慢,求优化方案

哇,1分30秒处理一张图确实有点拖后腿了,咱们来一步步把速度拉上来!你的代码里有几个核心性能瓶颈,我帮你拆解并给出具体的优化方案:

核心问题分析

你的代码慢主要来自三个地方:Python嵌套循环处理像素(几十万次循环效率极低)、重复读取Excel文件、以及不必要的数组拼接和DataFrame合并操作。下面是针对性的优化:


1. 用NumPy向量化替代嵌套循环

Python的for循环在处理几十万像素时效率极低,我们可以用NumPy的向量化操作一次性处理所有像素,这能把速度提升几个数量级:

预先生成坐标与天顶角映射

提前创建整个图像的坐标网格,一次性计算所有像素到中心的距离和对应的天顶角,完全去掉i和j的嵌套循环:

# 预先生成图像的像素坐标网格(对应480行640列)
i, j = np.meshgrid(np.arange(480), np.arange(640), indexing='ij')
# 计算所有像素到中心(235, 332)的距离
distances = np.sqrt((332 - j)**2 + (235 - i)**2)

# 天顶角计算:直接用距离线性映射,不用匹配theta数组(原代码的theta匹配完全冗余)
# 当距离<200时,天顶角=距离*90/200;否则设为120
zenith_map = np.where(distances < 200, np.round(distances * 90 / 200, 6), 120)

向量化温度转换

直接对整个灰度图应用温度公式,不用逐个像素计算:

# 温度转换参数(提前定义,不用每次循环重复计算)
Tmax, Tmin = 25, -10
Zmax, Zmin = 255, 0
m = (Tmax - Tmin) / (Zmax - Zmin)
c = -10

# 一次性计算所有像素的温度,再处理距离>=200的像素
grey = cv.cvtColor(image_data[r], cv.COLOR_BGR2GRAY)
Tem = m * grey + c
Tem[distances >= 200] = 255

2. 只读取一次Excel掩码文件

原代码在每个图像循环里都重复读取contour.xlsx,这会反复打开文件、加载数据,耗时极多。把这一步提到循环外面,只做一次:

# 提前读取掩码数据,仅执行一次!
df_con = pd.read_excel('contour.xlsx')
# 预先生成有效像素的掩码数组(pxl_new <255的位置为True)
valid_mask = df_con['pxl_new'].values < 255

3. 简化DataFrame操作,用掩码直接过滤

原代码里的多次merge操作完全没必要,直接用预先生成的掩码过滤有效像素,再筛选天顶角范围:

# 把图像数据展平,用掩码提取有效像素
flattened_zenith = zenith_map.flatten()
flattened_Tem = Tem.flatten()

# 提取有效像素的天顶角和温度
valid_zenith = flattened_zenith[valid_mask]
valid_Tem = flattened_Tem[valid_mask]

# 筛选65-85度的天顶角,计算平均温度
target_mask = (valid_zenith >= 65) & (valid_zenith <= 85)
mean_temp = np.mean(valid_Tem[target_mask])
T_hot = np.append(T_hot, mean_temp)

完整优化后的代码

import glob
import os
import cv2 as cv
import numpy as np
import pandas as pd
from tqdm import tqdm

# ---------------------- 预处理:仅执行一次的操作 ----------------------
# 读取所有图像
files = glob.glob("Images/*.jpg")
files.sort(key=os.path.getmtime, reverse=True)
image_data = np.array([cv.imread(img) for img in files])

# 预先生成像素坐标网格和距离矩阵(针对480*640的图像)
i, j = np.meshgrid(np.arange(480), np.arange(640), indexing='ij')
distances = np.sqrt((332 - j)**2 + (235 - i)**2)

# 预先生成天顶角映射
zenith_map = np.where(distances < 200, np.round(distances * 90 / 200, 6), 120)

# 温度转换参数
Tmax, Tmin = 25, -10
Zmax, Zmin = 255, 0
m = (Tmax - Tmin) / (Zmax - Zmin)
c = -10

# 读取掩码数据(仅一次)
df_con = pd.read_excel('contour.xlsx')
valid_mask = df_con['pxl_new'].values < 255

# ---------------------- 批量处理图像 ----------------------
T_hot = []  # 用列表替代np.append,效率更高

for img in tqdm(image_data):
    # RGB转灰度图
    grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    
    # 向量化计算温度
    Tem = m * grey + c
    Tem[distances >= 200] = 255
    
    # 提取有效像素并计算目标范围的平均温度
    flattened_Tem = Tem.flatten()
    flattened_zenith = zenith_map.flatten()
    
    valid_Tem = flattened_Tem[valid_mask]
    valid_zenith = flattened_zenith[valid_mask]
    
    target_mask = (valid_zenith >= 65) & (valid_zenith <= 85)
    mean_temp = np.mean(valid_Tem[target_mask])
    T_hot.append(mean_temp)

# 转成numpy数组(如果需要)
T_hot = np.array(T_hot)

额外优化建议

  • 如果图像数量极大(17000张),可以考虑用多进程/多线程并行处理(比如multiprocessing模块或者joblib),把图像分成多个批次同时处理。
  • 用列表T_hot.append()替代np.append(),因为列表的append操作是O(1)的,而np.append每次都会重新分配数组内存。
  • 如果你用的是OpenCV 4.x,确保cv.imread读取的图像格式是最优的,或者可以考虑用PIL读取图像,有时候速度会更快。

这些优化应该能把单张图的处理时间从1分30秒压缩到几秒甚至更短,24张图的处理时间会大幅降低!

内容的提问来源于stack exchange,提问作者hrpandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:27:44