如何通过多处理并行使用OpenCV处理图像?

时间:2018-06-19 19:02:45

标签: python multithreading opencv python-multiprocessing

我要使用某些OpenCV函数预处理的文件夹中有一组图像。函数

detectAndaligncrop

拍摄图像路径,使用OpenCV对其进行预处理,然后返回输出图像。 我可以使用:

for image_path in files_list:
   cropped_image, _=detectAndaligncrop(im)
   cv2.imwrite("ouput_folder/{}".format(os.path.basename(image_path)),cropped_im*255.)

但是这不起作用:

jobs=[]
for im_no, im in enumerate(files_list):
    p=multiprocessing.Process(target=saveIm,args=[im])
    jobs.append(p)
    p.start()
for j in jobs:
    j.join()

其中saveIm是:

im,lm=detectAndaligncrop(im_path)
        fname="output_path/cropped2/{}".format(os.path.basename(im_path))
        cv2.imwrite(fname,im)

我已经验证它调用了detectAndaligncrop函数,但是没有处理从其中的行开始的图像

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

在detectAndaligncrop内部被称为,因为每个图像都调用“ before cvtColor”,而“ cvtColor after”则不是:

def detectAndaligncrop(impath):
    image=cv2.imread(impath)
    image_float=np.float32(image)/255.0
    print ("before cvtcolor")
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    print ("after cvtcolor")
    return gray, 1

我也尝试过:

with ThreadPoolExecutor(max_workers=32) as execr:
    res=execr.map(saveIm,files_list)

此方法有效,但仅比运行for循环快。是因为GIL吗?

2 个答案:

答案 0 :(得分:0)

经过几次实验发现错误: 基本上,错误在于将读取的图像转换为灰度图像的方法。 如果我使用:

gray = cv2.imread(impath,0)

代替

image = cv2.imread(impath)
image_float = np.float32(image)/255.0
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

代码正常工作

在MultiProcessing中使用cv2.cvtColor可能存在一些问题。有人可以阐明原因。关于可腌制性吗?

答案 1 :(得分:-1)

在将图像馈送到神经网络之前,我需要一种多处理方法来对图像进行预处理。我碰到了名为Embarrassingly parallel for loops的页面,其中并行执行数组/列表中元素的数学任务。我想知道是否可以将其扩展到图像(毕竟所有图像不过是数组,是大型3D数组!)

我决定从OpenCV到图像集合执行add weighted操作。使用此操作,您可以对两个图像应用不同的权重并将其添加。它用于混合图像see here

我在Joblib中使用来执行此功能,用于在我的桌面上设置一组图像,并比较了它们的性能。最后,我提到了图像的数量和所用图像的总大小。

代码:

import os
import time

#--- Importing the required library ---
from joblib import delayed

#--- Choosing all available image formats of images from my desktop ---
path = r'C:\Users\Jackson\Desktop'
img_formats = ['.png', '.jpg', '.jpeg']

#--- Defining the addWeighted function from OpenCV ---
def weight(im):
    addweighted = cv2.addWeighted(im, 0.7, cv2.GaussianBlur(im, (15, 15), 0), 0.3, 0)
    return addweighted


#--- Using joblib library-----
start_time = time.time()

new_dir = os.path.join(path, 'add_Weighted_4_joblib')
if not os.path.exists(new_dir):
    os.makedirs(new_dir)

def joblib_loop():
    for f in os.listdir(path):
        if any(c in f for c in img_formats):
            img = cv2.imread(os.path.join(path, f))
            r = delayed(weight)(img)
            cv2.imwrite(os.path.join(new_dir, f + '_add_weighted_.jpg'), r)

elapsed_time = time.time() - start_time
print('Using Joblib : ', elapsed_time)

#--- Without joblib ---
start_time = time.time()

#--- Check whether directory exists if not make one
new_dir = os.path.join(path, 'add_Weighted_4')
if not os.path.exists(new_dir):
    os.makedirs(new_dir)

for f in os.listdir(path):
    if any(c in f for c in img_formats):
        img = cv2.imread(os.path.join(path, f))
        r = weight(img)
        cv2.imwrite(os.path.join(new_dir, f + '_add_weighted_.jpg'), r)

elapsed_time = time.time() - start_time
print('Without Joblib : ', elapsed_time)

这是我得到的结果:

('Using Joblib : ', 0.09400010108947754)
('Without Joblib : ', 15.386000156402588)

如您所见,使用joblib可以加快疯狂的操作速度!

现在让我向您展示我的桌面上有多少张图像,它们的总大小是多少:

overall_size = 0
count = 0
#for f in os.listdir(path):
for  f in os.listdir(path):
    if any(c in f for c in img_formats):
        img = cv2.imread(os.path.join(path, f))
        overall_size+= img.size
        count+= 1

print('Collective Size of all {} images in the predefined path is {} MB'.format(count, overall_size/10**6))

和结果:

Collective size of all 14 images in the predefined path is 58 MB