如何在Python中利用multiprocessing加速图片处理循环?
解决Python多进程处理图片返回None及效率问题
问题根源分析
你的多进程代码存在几个关键错误,导致返回None且无法正常工作:
- 代码结构错误:
if __name__ == "__main__":放在了图片遍历循环内部,且处理函数定义在循环里,子进程无法正确加载这些函数。 - 无返回值:
mask函数没有返回任何结果,pool.map会收集每个任务的返回值,自然得到全是None的列表。 - 共享变量失效:多进程中每个子进程有独立的内存空间,
x1、y1、total这些列表的修改不会同步到主进程,必须通过函数返回值传递结果。 - 逻辑错误:
equation函数传入的是单个坐标y,x,却调用np.average(y),这是无效操作(单个整数的平均值就是自身),和单进程逻辑不符。 - 任务拆分错误:
[blackMask] *3是重复处理同一张图的mask,没有批量处理不同图片。
修正后的多进程代码
import numpy as np import cv2 import os from multiprocessing import Pool def process_single_image(img_path): # 单张图片处理逻辑 img = cv2.imread(img_path) gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, blackMask = cv2.threshold(gry, 0, 255, cv2.THRESH_BINARY_INV) x1 = [] y1 = [] def verticle(mask, y, x): vertiPixel = 0 while y < mask.shape[0]: if (y + 1) == mask.shape[0]: break if mask[y + 1][x] == 255: vertiPixel += 1 y += 1 else: break return vertiPixel def horizontal(mask, y, x): horiPixel = 0 while x < mask.shape[1]: if (x + 1) == mask.shape[1]: break if mask[y][x + 1] == 255: horiPixel += 1 x += 1 else: break return horiPixel for y in range(blackMask.shape[0]): for x in range(blackMask.shape[1]): if blackMask[y][x] == 255: y1.append(verticle(blackMask, y, x)) x1.append(horizontal(blackMask, y, x)) # 计算最终结果,和单进程逻辑对齐 avg_x = np.average(x1) if x1 else 0 avg_y = np.average(y1) if y1 else 0 a = avg_y * (9.9 / 305) c = avg_x * (9.9 / 305) final = (a + c) / 2 return final if __name__ == "__main__": folderDir = "C://Users/ruler/Desktop/testseg/" # 收集所有目标图片路径 image_paths = [] for allImages in os.listdir(folderDir): if allImages.startswith('TRAIN_SET') and allImages.endswith(".bmp"): image_paths.append(os.path.join(folderDir, allImages)) # 启动多进程池,进程数默认匹配CPU核心数 with Pool() as pool: # 批量处理所有图片 results = pool.map(process_single_image, image_paths) # 将结果写入文件 with open('readme.txt', 'w') as f: for idx, res in enumerate(results, 1): f.write(f"图片{idx}处理结果: {res}\n") print(f"所有图片处理完成,共{len(results)}张")
额外效率优化建议
原单进程的逐像素遍历效率很低,这也是80张图耗时久的核心原因之一,可以用OpenCV的轮廓提取替代手动循环,大幅提升单张图处理速度:
def process_single_image_optimized(img_path): img = cv2.imread(img_path) gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, blackMask = cv2.threshold(gry, 0, 255, cv2.THRESH_BINARY_INV) # 提取黑色区域轮廓,直接获取区域的宽高 contours, _ = cv2.findContours(blackMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) x1 = [] y1 = [] for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) x1.append(w) # 水平方向连续像素数等价于轮廓宽度 y1.append(h) # 垂直方向连续像素数等价于轮廓高度 avg_x = np.average(x1) if x1 else 0 avg_y = np.average(y1) if y1 else 0 a = avg_y * (9.9 / 305) c = avg_x * (9.9 / 305) final = (a + c) / 2 return final
这个优化后的函数能比原循环快数倍,结合多进程会让整体处理速度得到质的提升。
内容的提问来源于stack exchange,提问作者user20680514
相关产品推荐
相关产品推荐

