Python if-elif-else оптимизация времени выполнения - PullRequest
0 голосов
/ 19 сентября 2018

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

Для информации, я работаю на Python 2.7, но при необходимости могу измениться на 3

Я конвертирую каждый пиксель изображения, и из-за некоторых условий я должен сделать это попиксельно.Так что я вложил в цикл цикл с оператором if-elif-else, и для его запуска требуется очень много времени.Для изображения размером 1536 x 2640 весь код занимает ~ 20 секунд, и 90% времени находится внутри этого двойного цикла for

Я считаю, что должен быть лучший способ написания кода ниже

  for pixel in range(width):
    for row in range(height):
      ADC = img_original[row, pixel]
      if ADC < 84:
        gain   = gain1
        offset = offset1
      elif ADC > 153: 
        gain   = gain3
        offset = offset3
      else:
        gain   = gain2
        offset = offset2

      Conv_ADC  = int(min(max(ADC * gain + offset, 0),255))
      img_conv[row, pixel] = Conv_ADC

Спасибо за помощь


для дополнительной информации отредактируйте:

@ Жан-Франсуа Фабр прав, и я применяю три различных коэффициента усиления / смещения в зависимости от того, в каком разделе я нахожусь междуОт 0 до 255. Но разделы не всегда равномерно распределены и могут быть изменены.Может быть, чтобы дать некоторый дополнительный контекст, я просто применяю пользовательскую S-кривую к изображению, чтобы сместить значение пикселя вверх / вниз.И каждый столбец в изображении имеет свою собственную S-кривую

Мои значения коэффициента усиления1,2,3 / смещения1,2,3 являются плавающей точкой.усиление всегда будет положительным, а смещение может быть отрицательным или положительным. У меня также есть индивидуальное значение для каждого пикселя в направлении ширины, но они являются общими в направлении строки.

Например, все пиксели из столбца1 с может использовать усиление / смещение 1,2,3 из 1-й строки в таблице ниже.Все пиксели из столбца 2 на изображении будут использовать усиление / смещение из строки 2 в таблице ниже

Pixel   Gain1     Offset1    Gain2     Offset2   Gain3     Offset3
1       0.417722  24.911392  0.623188  7.652176  1.175676  -76.878357
2       0.43038   25.848103  0.623188  9.652176  1.148649  -70.743225
3       0.443038  23.784809  0.637681  7.434776  1.175676  -74.878357
4       0.443038  22.784809  0.652174  5.217384  1.175676  -74.878357
5       0.455696  23.721519  0.637681  8.434776  1.202703  -78.013519
6       0.455696  21.721519  0.637681  6.434776  1.243243  -86.216217
7       0.455696  22.721519  0.623188  8.652176  1.216216  -82.081085
8       0.443038  22.784809  0.623188  7.652176  1.22973   -85.148651
... until pixel 2640 in width direction

Я посмотрю на решение @ Jean-FrançoisFabre, но пока я также смотрю на использованиенекоторые сбитые с толку подходы.

Как только я получу что-то, что вычисляется быстрее, я опубликую свою находку здесь

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Попробуйте использовать справочную таблицу: вы предварительно вычислите все преобразованные значения АЦП в диапазоне [0,255], и тело цикла упростит

  for pixel in range(width):
    for row in range(height):
      img_conv[row, pixel]= LUT[img_original[row, pixel]]
0 голосов
/ 24 сентября 2018

Это последняя реализация, которую я использую для удаления циклов 2 for.Переходя примерно к 1 ~ 2 секундам для изображений

Я создаю 3 массива, где я заменяю контент на 0, когда он не находится в желаемом диапазоне.Затем выполните умножение усиления и смещение для каждого перед добавлением целых

  height = img_original.shape[0]
  width  = img_original.shape[1]
  print 'height = ', height, 'width = ', width

  # create temp 3 2D-arrays
  img1 = np.array(img_original,dtype=np.int)
  img2 = np.array(img_original,dtype=np.int)
  img3 = np.array(img_original,dtype=np.int)

  #create the 2D array for gain/offset based on 1D array
  # csv array acquire from .csv file, INDEX_xx for column to read
  array_gain1    = np.tile(csv[1:, INDEX_G1],(height,1))
  array_offset1  = np.tile(csv[1:, INDEX_O1],(height,1))

  array_gain2   = np.tile(csv[1:, INDEX_G2],(height,1))
  array_offset2 = np.tile(csv[1:, INDEX_O2],(height,1))

  array_gain3    = np.tile(csv[1:, INDEX_G3],(height,1))
  array_offset3  = np.tile(csv[1:, INDEX_O3],(height,1))

  # replace the content by 0 when not in the desired zone
  np.place(img1,img_original >= G2_TARGET, 0) 
  np.place(img2,img_original < G2_TARGET,0)   
  np.place(img2,img_original > G1_TARGET,0)   
  np.place(img3,img_original <= G1_TARGET, 0) 

  np.place(array_offset1,img_original >= G2_TARGET, 0)
  np.place(array_offset2,(img_original < G2_TARGET), 0)
  np.place(array_offset2,(img_original > G1_TARGET), 0)
  np.place(array_offset3,img_original <= G1_TARGET, 0)

  # apply the gain/offset for each zone
  img1 = np.array(img1 * array_gain1 + array_offset1, dtype=np.uint8)
  img2 = np.array(img2 * array_gain2 + array_offset2, dtype=np.uint8)
  img3 = np.array(img3 * array_gain3 + array_offset3, dtype=np.uint8)

  # recrete the whole image
  img_conv = np.clip(img1 + img2 + img3, 0, 255)
0 голосов
/ 19 сентября 2018

Поскольку ваши значения находятся в диапазоне от 0 до 255, а ваши границы равномерно распределены, вы можете использовать трюк ниже:

вы, кажется, хотите применить 3 различных коэффициента усиления в зависимости от того, находитесь ли вы на первой трети,вторая треть или третья третья от диапазона 0-255.

Почему бы не вычислить индекс путем деления на 85 (255/3)?

простое доказательство концепции:

gainsoffsets = [(10,1),(20,2),(30,3),(30,3)] # [(gain1,offset1),(gain2,offset2),(gain3,offset3)] + extra corner case for value 255

for value in 84,140,250:
    index = value // 85
    gain,offset = gainsoffsets[index]
    print(gain,offset)

результат:

10 1
20 2
30 3

в этом цикле есть только одно деление и нет if.Должно быть намного быстрее (помимо numpy подходов)

Вы можете использовать более тонкий уровень с более точными таблицами поиска (также избегайте деления, генерируя 256 кортежей):

gainsoffsets = [(10,1)]*85+[(20,2)]*85+[(30,3)*86]  # add more intervals for more thresholds
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...