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

Python 如何使用多处理并行处理OpenCV图像?,python,multithreading,opencv,python-multiprocessing,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)),crop

我在一个文件夹中有一组图像,我想使用一些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)
我已经验证了它调用了detectandalligncrop函数,但不处理从以下行开始的图像:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
称为inside detectAndaligncrop,因为对每个图像调用“在cvtColor之前”,而“在cvtColor之后”不是:

此外,我尝试:

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

这是可行的,但并不比简单地运行for循环快。是因为GIL吗?

我需要一种多重处理方法来预处理图像,然后再将它们输入神经网络。我看到了一个页面,名为“并行地为数组/列表中的元素运行数学任务的位置”。我想知道这是否可以扩展到图像(毕竟所有的图像都是数组,大的3D数组!)

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

我对桌面上的一组图像执行了带有和不带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

在将图像输入神经网络之前,我需要一种多处理方法来预处理图像。我看到了一个页面,名为“并行地为数组/列表中的元素运行数学任务的位置”。我想知道这是否可以扩展到图像(毕竟所有的图像都是数组,大的3D数组!)

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

我对桌面上的一组图像执行了带有和不带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

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

gray = cv2.imread(impath,0)
而不是

image = cv2.imread(impath)
image_float = np.float32(image)/255.0
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
代码运行良好


在多处理中使用cv2.cvtColor可能存在一些问题。有人可以解释原因。这是关于挑剔的问题吗

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

gray = cv2.imread(impath,0)
而不是

image = cv2.imread(impath)
image_float = np.float32(image)/255.0
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
代码运行良好



在多处理中使用cv2.cvtColor可能存在一些问题。有人可以解释原因。这是关于挑剔的问题吗

嗯?我们看不到您提到的行。进行了一些更改您应该为
detectAlignandcrop()
函数添加代码。或者,更好的方法是创建一个。为函数detectandAlignCropImage\u float添加代码请问这是什么意思?如果没有“在cvtColor()之后”,怎么能调用“在cvtColor()之前”?嗯?我们看不到您提到的行。进行了一些更改您应该为
detectAlignandcrop()
函数添加代码。或者,更好的方法是创建一个。为函数detectandAlignCropImage\u float添加代码请问这是什么意思?如果没有“在cvtColor()之后”,如何调用“在cvtColor()之前”呢?您不应该实际调用joblib_loop()吗?在我看来,您对mkdir和def进行了计时,但没有实际计算任何内容。您不应该实际调用joblib_loop()吗?在我看来,你对mkdir和def进行了计时,但实际上没有进行任何计算。其他opencv函数在多处理中是否适用于你?这不是答案@Amogh刚刚发现,在cv2.cvtColor上,它无法工作。cvtColor依赖于在后端处理并行性的numpy。当numpy重载函数并行运行时,numpy可用的线程数量会减少,因此速度会变慢。如果您只执行numpy操作,很可能并行执行这些操作会给您带来任何好处,因为线程总数不会有任何不同。例如,在4核机器上运行的4x numpy操作将在每个numpy操作上运行4个线程4次。相同的并行场景可能会在4个并行线程中的每个numpy操作上运行1个线程。根据您执行操作的方式,最终可能会导致对CPU资源的超额订阅,并在4个并行线程中实际运行4个线程numpy操作,导致16个线程最终争夺CPU时间和强制交换惩罚,这可能比其他两种情况更糟糕。其他opencv函数在多处理中适用吗?这不是答案@Amogh刚刚发现,在cv2.cvtColor上,它无法工作。cvtColor依赖于在后端处理并行性的numpy。当numpy重载函数并行运行时,numpy可用的线程数量会减少,因此速度会变慢。如果您只执行numpy操作,那么并行执行这些操作很可能会给您带来任何好处,因为总线程数为wo