Как я могу обрабатывать изображения с OpenCV параллельно, используя многопроцессорность?

1

У меня есть набор изображений в папке, которую я хочу предварительно обработать, используя некоторые функции OpenCV. Функция

detectAndaligncrop

берет путь изображения, предварительно обрабатывает его с помощью OpenCV и возвращает utput изображение. Я могу это сделать, используя:

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, потому что "перед cvtColor" вызывается для каждого изображения, тогда как "после cvtColor" не является:

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?

Теги:
opencv
multithreading
python-multiprocessing

1 ответ

0

Я нуждался в многопроцессорном подходе к предварительной обработке изображений перед подачей их в нейронные сети. Я наткнулся на эту страницу под названием " Смущающе параллельна для циклов, где математические задачи выполнялись для элементов в массиве/списке параллельно. Я хотел знать, может ли это быть распространено на изображения (ведь изображения - это не что иное, как массивы, большие 3D-массивы!)

Я решил выполнить операцию взвешивания add из 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
  • 2
    Разве вы не должны вызывать joblib_loop ()? Я смотрю на меня так, как будто вы рассчитали mkdir и def, фактически ничего не вычисляя.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню