Код занимает слишком много времени для выполнения при пакетной обработке изображения

Я пытаюсь рассчитать среднюю температуру для определенного диапазона зенитного угла для каждого изображения.

Я использую цикл for для выполнения вышеупомянутой задачи. Внутри цикла я вычисляю расстояние каждого пикселя от центра, а затем применяю условия на основе расстояния.

На изображении много нежелательных отражений, которые я удаляю с помощью фрейма данных df_con.

Цикл занимает 1 минуту 30 секунд для обработки всех операций с одним изображением (всего 24 изображения заняло 38 минут). Есть ли способ улучшить скорость кода.

### Reading all the images inside the Images folder
X_data = []
files = glob.glob ("Images/*.jpg"). #  Total 17,000 images of(480*640*3)
files.sort(key=os.path.getmtime, reverse=True)


X_data = [cv.imread(img) for img in files]

image_data = np.array(X_data)

T_hot = np.array([])

for r in tqdm(range(image_data[:,0,0,0].size)):

    ##Converting RGB image to grey scale image 
    grey = cv.cvtColor(image_data[r],cv.COLOR_BGR2GRAY)


    Z = grey.reshape(-1,1)

    Tem = np.array([])

    Tmax = 25 
    Tmin = -10 

    Zmax = 255 
    Zmin = 0
    c = -10

    m = (Tmax - Tmin) / (Zmax - Zmin)

    zenith = np.array([])
    theta = np.around(np.arange(0,90,90/200),6)

    for i in range(0,480):
        for j in range(0,640):

            # Calculating distance of each pixel from the center.
            r = np.around(np.sqrt((332 - j)**2 + (235 - i)**2))

            # Assigning zxenith angle to each pxl.
            # Calculating Temperature of indexed pxl.

            if r < 200:
                k = theta[theta == np.around((r*90/200),6)]
                zenith = np.append(zenith,k)
                T =  (m*grey[i,j]) + c 
                Tem = np.append(Tem,T)
            else:
                k = 120
                zenith = np.append(zenith,k) 
                T = 255
                Tem = np.append(Tem,T)



    # creating panda dataframe 
    df = pd.DataFrame({'Pxl':Z[:,0],'Tem':Tem[:],'zenith':zenith[:]})

    # Fetching the Image mask data points 
    df_con = pd.read_excel('contour.xlsx')

    dataset_final = pd.merge(df,df_con, how='outer', on=None, \
                            left_index=True, right_index=True, sort=True)
    dataset_final = dataset_final[dataset_final['pxl_new'] < 255]

    df_0 = pd.DataFrame(0, index=range(Z.shape[0]), columns={'Null'}) 

    df_image = pd.merge(dataset_final,df_0, how='outer', on=None, \
                            left_index=True, right_index=True,\
                         sort=True)

    df_image = df_image[['Pxl','Tem','zenith']].fillna(255)


    df_target = dataset_final[(dataset_final['zenith'] >= 65) & \
                              (dataset_final['zenith'] <= 85)]
    mean = np.mean(df_target[['Tem']].values)
    T_hot = np.append(T_hot, mean)


person Baba_Voss    schedule 19.05.2020    source источник
comment
Вы действительно загружаете все 17 000 изображений в память за один раз, чтобы вычислить их среднее значение? Обычно вам нужен только один образ-аккумулятор, а затем по одному добавляются к нему остальные. Вы действительно загружаете их все как цветные только для преобразования в оттенки серого? Если это так, вы тратите в 51 000 раз больше памяти, чем вам нужно. Подумайте о том, чтобы сразу же загрузить их как оттенки серого.   -  person Mark Setchell    schedule 19.05.2020
comment
Вы не только считываете все изображения сразу, но и затем объединяете их в одну большую матрицу, чтобы извлекать их одно за другим для обработки. Вам действительно следует рассмотреть возможность загрузки их по одному и обработки по отдельности. Затем вы должны профилировать свой код, чтобы увидеть, какие операции занимают больше всего времени, и сосредоточиться на улучшении их в первую очередь.   -  person Cris Luengo    schedule 19.05.2020
comment
@MarkSetchell На самом деле я пытаюсь рассчитать среднюю температуру и построить ее относительно временной метки каждого изображения. Вот почему я загружаю все изображения сразу. Я попытался загрузить все изображения в оттенках серого, и да, это значительно сократило время загрузки изображения с 2:30 до 0,35 с. Кроме того, я не понял концепции изображения аккумулятора.   -  person Baba_Voss    schedule 19.05.2020


Ответы (1)


Итак, после 3-х долгих дней борьбы мне удалось частично решить проблему. Я заметил три вещи в своем коде:

  1. Я читал все изображения в цвете, а затем преобразовывал их в оттенки серого, что было лишним дополнительным шагом и требовало много времени на вычисления. Спасибо @Mark Setchell, он указал мне на это.
X_data = []

files = glob.glob ("Images/*.jpg")
files.sort(key=os.path.getmtime, reverse=True)
for img in tqdm(files):
# Reading images in greyscale
    X = cv.imread(img,0);
    X_data.append(X)
  1. Я использовал кадр данных панды внутри цикла для выполнения операции индексации. Хотя фрейм данных panda упрощает нашу жизнь, он требует чертовски много времени для вычислений. Итак, я решил использовать numpy array вместо panda DataFrame.

  2. Я реализовал многопроцессорность для приведенного ниже блока кода.

for i in range(0,480):
        for j in range(0,640):

            r = np.around(np.sqrt((332 - j)**2 + (235 - i)**2))

            if r < 200:
                k = theta[theta == np.around((r*90/200),6)]
                zenith = np.append(zenith,k)
                T =  (m*grey[i,j]) + c 
                Tem = np.append(Tem,T)
            else:
                k = 120
                zenith = np.append(zenith,k) 
                T = 255
                Tem = np.append(Tem,T)

Теперь новый блок кода выглядит примерно так:

def temperature(count):
    zenith = np.array([])
    Tem = np.array([])

    theta = np.around(np.arange(0, 90, 90 / 200), 6)
    for j in range(0, 640):
        r = np.around(np.sqrt((332 - j) ** 2 + (235 - count) ** 2))

        if r < 200:
            k = theta[theta == np.around((r * 90 / 200), 6)]
            zenith = np.append(zenith,k)
            T = (m * grey[count, j]) + c
            Tem = np.append(Tem,T)
        else:
            k = 120
            zenith = np.append(zenith,k)
            T = 20
            Tem = np.append(Tem,T)

    result = np.vstack((zenith, Tem)).T
    return np.array(result)

if __name__ == '__main__':
        pool = Pool(cpu_count())
        result = pool.map(temperature, range(0,480))
        pool.close()
        res = np.array(result)
        Tem = res[:,:,1].reshape(-1,1)
        zenith = res[:,:,0].reshape(-1,1)

Внедрив вышеуказанные изменения, мне удалось сократить время обработки одного изображения с 1min30sec to 2sec. Я уверен, что есть лучшие способы дальнейшей оптимизации. Пожалуйста, не стесняйтесь предлагать свое решение. Это будет большим подспорьем для новичка, как я.

person Baba_Voss    schedule 22.05.2020