Автоматическая обрезка изображения в Python 3


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

У меня 4 разных видах изображений (фиксированной высоты, но разной ширины) и они обрезаются по-разному в зависимости от их типа.

Вот пример входного изображения (Тип 2) (2462x256) enter image description here

Вот пример входного изображения (Тип 3) (34482x256) enter image description here

Типы изображения 1 и 2-это просто обрезанные от правого края до нужного размера (в данном случае 1600px), так как самая интересная часть сигнала находится справа. Я, по сути, сняв левой части изображения, пока у меня осталось широкое изображение 1600px.

Типы изображений 3 и 4 изначально очень длинные изображения, поэтому я могу обрезать несколько изображений от каждого, накладываясь друг на фиксированную сумму. (В этом случае, я буду обрезать изображение широкого 1600px начиная с (0,0), сохранить урожай еще один широкий изображения на 1600px (400,0), то в (800,0) и так далее.)

Вот первый пример после обрезки. (1600x256) enter image description here

Вот первые два урожая из второго примера, вы можете увидеть, как пересекаются справа. (1600x256) enter image description here enter image description here


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

#Packages
import cv2
import os
from imageio import imwrite, imread

#Defined parameters
#Input and output paths
path_directory_input = '/home/.../spectrograms/uncropped'
path_directory_output = '/home/.../spectrograms/cropped'
#Cropping parameters
image_height_final = 256
image_width_final = 1600
image_overlap = 400
crop_nb_maximum = 11

#Class example counters
class1,class2,class3,class4 = 0,0,0,0
class1_out,class2_out,class3_out,class4_out = 0,0,0,0
# Object slipping = 1
# Object slipping on surface = 2
# Robot movement = 3
# Robot movement with object = 4

#Iterate over all samples in the input directory
for path_image in os.listdir(path_directory_input):

    #Defines the current image path, output path and reads the image
    path_image_input = os.path.join(path_directory_input, path_image)
    path_image_output = os.path.join(path_directory_output, path_image)
    image_current = imread(path_image_input)

    #Parse the filename and determine the current class (determined by the 15th character)
    class_current = int(path_image[15])

    #Counts the number of input examples being treated
    if class_current == 1:
        class1 += 1
    if class_current == 2:
        class2 += 1
    if class_current == 3:
        class3 += 1
    if class_current == 4:
        class4 += 1

    #Get image dimensions
    image_height_current, image_width_current = image_current.shape[:2]

    #Changes the procedure depending on the current class
    if (class_current == 1) or (class_current == 2):
        print('Processing class: ', class_current)

        #Crops the image to target size (Format is Y1:Y2,X1:X2)
        image_current_cropped = image_current[0:image_height_final,
                                (image_width_current-image_width_final):image_width_current]
        #Saves the new image in the output file
        imwrite(path_image_output,image_current_cropped)

    elif (class_current == 3) or (class_current == 4):
        print('Processing class: ', class_current)

        #Count how many crops can fit in the original
        crop_nb = int((image_width_current - image_width_final)/image_overlap)
        #Limit the crop number to arrive at equal class examples
        if crop_nb > crop_nb_maximum:
            if class_current == 3:
                crop_nb = crop_nb_maximum
            else:
                crop_nb = crop_nb_maximum * 2

        #Loop over that number
        for crop_current in range(0,crop_nb):
            #Counts the number of output examples
            if class_current == 3:
                class3_out += 1
            if class_current == 4:
                class4_out += 1

            #Crop the image multiple times with some overlap
            image_current_cropped = image_current[0:image_height_final,
                                    (crop_current * image_overlap):((crop_current * image_overlap) + image_width_final)]
            #Save the crop with a number appended
            path_image_output_new = path_image_output[:-4] #Removes the .png
            path_image_output_new = str.join('_',(path_image_output_new,str(crop_current))) #Appends the current crop number
            path_image_output_new = path_image_output_new + '.png' #Appends the .png at the end
            imwrite(path_image_output_new,image_current_cropped)

    else:
        #If the current class is not a valid selection (1-4)
        print('Something went wrong with the class selection: ',class_current)


#Prints the number of examples
print('Cropping is done. Here are the input example numbers:')
print('class1',class1)
print('class2',class2)
print('class3',class3)
print('class4',class4)
print('Here are the output example numbers')
print('class1',class1)
print('class2',class2)
print('class3',class3_out)
print('class4',class4_out)


727
6
задан 4 апреля 2018 в 08:04 Источник Поделиться
Комментарии
1 ответ

Я не хочу отвечать на этот вопрос, потому что я не достаточно хорошо знаком с Python. Но я, конечно, могу дать несколько советов. Я надеюсь, что этот ответ поощряет других, чтобы тоже поучаствовать в обсуждении.

Избегать имен переменных с индексом прилагается

Это всегда лучше, чтобы сделать, что показатель фактический показатель.

Если вместо имен переменных class1, class2и т. д. вы используете список class = [0,0,0,0]некоторые ваш код будет проще:


if class_current == 1:
class1 += 1
if class_current == 2:
class2 += 1
if class_current == 3:
class3 += 1
if class_current == 4:
class4 += 1

становится

class[class_current] += 1

Кроме этого, я думаю, что ваши имена переменных очистить и сделать его, так что вам не нужно, чтобы добавить комментарий, объясняющий каждый.

Документ предположений

В этот кусок кода:


 if crop_nb > crop_nb_maximum:
if class_current == 3:
crop_nb = crop_nb_maximum
else:
crop_nb = crop_nb_maximum * 2

вы установить crop_nb два раза некоторым постоянным значением. Я предполагаю, что вы сделать это, потому что вы знаете наверняка crop_nb больше эта константа, вы предполагаете, что для класса 4 изображения, которые вы всегда можете обрезать как минимум 22 изображений. Это может быть правдой, но это не ясно из кода, и поэтому он пахнет как клоп. Таким образом, если это предположение верно, добавить комментарий.

Я бы, наверное, написать так:

if class_current == 3:
crop_nb = min(crop_nb, crop_nb_maximum)
else:
crop_nb = min(crop_nb, crop_nb_maximum * 2)

Упростить логику

Во внутреннем цикле для классов 3 и 4, вы начинаете так:


for crop_current in range(0,crop_nb):
#Counts the number of output examples
if class_current == 3:
class3_out += 1
if class_current == 4:
class4_out += 1
# <snip>

Это проще писать

class_out[class_current] += crop_nb
for crop_current in range(0,crop_nb):
# <snip>

2
ответ дан 10 апреля 2018 в 04:04 Источник Поделиться