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

Представьте себе человека за рулем машины в солнечный день. Если начнется дождь, поначалу им может быть трудно управлять автомобилем в дождь. Но постепенно они к этому привыкают.

Искусственная нейронная сеть также находит затруднительным вождение в новой среде, если она не видела это раньше. Это различные техники увеличения, такие как переворачивание, перевод, добавление шума или изменение цветового канала.

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

Я выпустил полностью реализованный Jupyter Notebook, с которым вы можете поиграть на GitHub.

Давайте посмотрим.

Сначала я покажу вам исходное тестовое изображение, а затем дополню его.

Санни и Шейди

После добавления случайного солнечного и теневого эффекта яркость изображения изменится. Это простое и быстрое преобразование.

def add_brightness(image):
    image_HLS = cv2.cvtColor(image,cv2.COLOR_RGB2HLS) ## Conversion to HLS
    image_HLS = np.array(image_HLS, dtype = np.float64) 
    random_brightness_coefficient = np.random.uniform()+0.5 ## generates value between 0.5 and 1.5
    image_HLS[:,:,1] = image_HLS[:,:,1]*random_brightness_coefficient ## scale pixel values up or down for channel 1(Lightness)
    image_HLS[:,:,1][image_HLS[:,:,1]>255]  = 255 ##Sets all values above 255 to 255
    image_HLS = np.array(image_HLS, dtype = np.uint8)
    image_RGB = cv2.cvtColor(image_HLS,cv2.COLOR_HLS2RGB) ## Conversion to RGB
    return image_RGB

Яркость изображения можно изменить, изменив значения пикселей «Яркость» - канал 1 изображения в цветовом пространстве HLS. Преобразование изображения обратно в RGB дает то же изображение с усиленным или подавленным освещением.

Тени

Для автомобиля тень - это не что иное, как темные участки изображения, которые иногда могут быть яркими. Таким образом, беспилотный автомобиль всегда должен учиться водить с тенями или без них. Случайно меняющаяся яркость на холмах или в лесу часто сбивает с толку восприятие автомобиля, если его не обучить должным образом. Это еще более распространено в солнечные дни и в зданиях разной высоты в городе, через которые проникают лучи света.

Яркость хороша для восприятия, но неравномерная, резкая или слишком большая яркость создает проблемы с восприятием. Давайте создадим несколько искусственных теней.

def generate_shadow_coordinates(imshape, no_of_shadows=1):
    vertices_list=[]
    for index in range(no_of_shadows):
        vertex=[]
        for dimensions in range(np.random.randint(3,15)): ## Dimensionality of the shadow polygon
            vertex.append(( imshape[1]*np.random.uniform(),imshape[0]//3+imshape[0]*np.random.uniform()))
        vertices = np.array([vertex], dtype=np.int32) ## single shadow vertices 
        vertices_list.append(vertices)
    return vertices_list ## List of shadow vertices

def add_shadow(image,no_of_shadows=1):
    image_HLS = cv2.cvtColor(image,cv2.COLOR_RGB2HLS) ## Conversion to HLS
    mask = np.zeros_like(image) 
    imshape = image.shape
    vertices_list= generate_shadow_coordinates(imshape, no_of_shadows) #3 getting list of shadow vertices
    for vertices in vertices_list: 
        cv2.fillPoly(mask, vertices, 255) ## adding all shadow polygons on empty mask, single 255 denotes only red channel
    
    image_HLS[:,:,1][mask[:,:,0]==255] = image_HLS[:,:,1][mask[:,:,0]==255]*0.5   ## if red channel is hot, image's "Lightness" channel's brightness is lowered 
    image_RGB = cv2.cvtColor(image_HLS,cv2.COLOR_HLS2RGB) ## Conversion to RGB
    return image_RGB

В этом случае очень удобна функция fillPoly() OpenCV. Давайте создадим несколько случайных вершин и наложим многоугольник на пустую маску с помощью fillPoly(). После этого остается только проверить маску на наличие горячих пикселей и уменьшить «яркость» в HLS-изображении, где бы эти горячие пиксели ни были обнаружены.

Снег

Ну это что-то новенькое. Мы часто задаемся вопросом, как бы наш автомобиль вёл себя на заснеженной дороге. Один из способов проверить это - сделать снимки заснеженных дорог или сделать что-нибудь с изображениями, чтобы получить аналогичный эффект. Этот эффект не является полной альтернативой заснеженным дорогам, но его стоит попробовать.

def add_snow(image):
    image_HLS = cv2.cvtColor(image,cv2.COLOR_RGB2HLS) ## Conversion to HLS
    image_HLS = np.array(image_HLS, dtype = np.float64) 
    brightness_coefficient = 2.5 
    snow_point=140 ## increase this for more snow
    image_HLS[:,:,1][image_HLS[:,:,1]<snow_point] = image_HLS[:,:,1][image_HLS[:,:,1]<snow_point]*brightness_coefficient ## scale pixel values up for channel 1(Lightness)
    image_HLS[:,:,1][image_HLS[:,:,1]>255]  = 255 ##Sets all values above 255 to 255
    image_HLS = np.array(image_HLS, dtype = np.uint8)
    image_RGB = cv2.cvtColor(image_HLS,cv2.COLOR_HLS2RGB) ## Conversion to RGB
    return image_RGB

Ага! Вот и все. Этот код обычно отбеливает самые темные части изображения, которые в основном представляют собой дороги, деревья, горы и другие элементы ландшафта, используя тот же метод увеличения HLS «Яркость», который использовался в других подходах, описанных выше. Этот метод не подходит для темных изображений, но вы можете изменить его для этого. Вот что вы получите:

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

Дождь

Да, вы не ослышались. Почему не дождь? Когда люди испытывают трудности с вождением под дождем, почему следует избегать этого в транспортных средствах? На самом деле, это одна из ситуаций, для которой я больше всего хочу, чтобы мой беспилотный автомобиль был обучен. Скользкие дороги и расплывчатые представления - дело рискованное, и автомобили должны знать, как с ними справляться.

def generate_random_lines(imshape,slant,drop_length):
    drops=[]
    for i in range(1500): ## If You want heavy rain, try increasing this
        if slant<0:
            x= np.random.randint(slant,imshape[1])
        else:
            x= np.random.randint(0,imshape[1]-slant)
        y= np.random.randint(0,imshape[0]-drop_length)
        drops.append((x,y))
    return drops
        
    
def add_rain(image):
    
    imshape = image.shape
    slant_extreme=10
    slant= np.random.randint(-slant_extreme,slant_extreme) 
    drop_length=20
    drop_width=2
    drop_color=(200,200,200) ## a shade of gray
    rain_drops= generate_random_lines(imshape,slant,drop_length)
    
    for rain_drop in rain_drops:
        cv2.line(image,(rain_drop[0],rain_drop[1]),(rain_drop[0]+slant,rain_drop[1]+drop_length),drop_color,drop_width)
    image= cv2.blur(image,(7,7)) ## rainy view are blurry
    
    brightness_coefficient = 0.7 ## rainy days are usually shady 
    image_HLS = cv2.cvtColor(image,cv2.COLOR_RGB2HLS) ## Conversion to HLS
    image_HLS[:,:,1] = image_HLS[:,:,1]*brightness_coefficient ## scale pixel values down for channel 1(Lightness)
    image_RGB = cv2.cvtColor(image_HLS,cv2.COLOR_HLS2RGB) ## Conversion to RGB
    return image_RGB

Что я здесь сделал, так это то, что я снова сгенерировал случайные точки по всему изображению, а затем использовал функцию OpenCV line() для создания небольших линий по всему изображению. Я также использовал случайный наклон капель дождя, чтобы почувствовать настоящий дождь. Я также уменьшил яркость изображения, потому что дождливые дни обычно тенистые, а также размытые из-за дождя. Вы можете изменить размер фильтра размытия и количество капель дождя для достижения желаемого эффекта.

Вот результат:

Туман

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

Интенсивность тумана - важный параметр, который помогает приучить машину работать с дроссельной заслонкой. Для кодирования такой функции вы можете брать случайные участки со всего изображения и увеличивать яркость изображения внутри этих участков. С помощью простого размытия получается приятный эффект тумана.

def add_blur(image, x,y,hw):
    image[y:y+hw, x:x+hw,1] = image[y:y+hw, x:x+hw,1]+1
    image[:,:,1][image[:,:,1]>255]  = 255 ##Sets all values above 255 to 255
    image[y:y+hw, x:x+hw,1] = cv2.blur(image[y:y+hw, x:x+hw,1] ,(10,10))
    return image
def generate_random_blur_coordinates(imshape,hw):
    blur_points=[]
    midx= imshape[1]//2-hw-100
    midy= imshape[0]//2-hw-100
    index=1
    while(midx>-100 or midy>-100): ## radially generating coordinates
        for i in range(250*index):
            x= np.random.randint(midx,imshape[1]-midx-hw)
            y= np.random.randint(midy,imshape[0]-midy-hw)
            blur_points.append((x,y))
        midx-=250*imshape[1]//sum(imshape)
        midy-=250*imshape[0]//sum(imshape)
        index+=1
    return blur_points
    
def add_fog(image):
    image_HLS = cv2.cvtColor(image,cv2.COLOR_RGB2HLS) ## Conversion to HLS
    mask = np.zeros_like(image) 
    imshape = image.shape
    hw=100
    image_HLS[:,:,1]=image_HLS[:,:,1]*0.8
    haze_list= generate_random_blur_coordinates(imshape,hw)
    for haze_points in haze_list: 
        image_HLS[:,:,1][image_HLS[:,:,1]>255]  = 255 ##Sets all values above 255 to 255
        image_HLS= add_blur(image_HLS, haze_points[0],haze_points[1], hw) ## adding all shadow polygons on empty mask, single 255 denotes only red channel
    image_RGB = cv2.cvtColor(image_HLS,cv2.COLOR_HLS2RGB) ## Conversion to RGB
    return image_RGB

Кодирование этой функции было самой сложной из всех вышеперечисленных функций. Я пробовал здесь радиальный подход для создания патчей. Поскольку в туманный день обычно большая часть тумана находится в дальнем конце дороги, и когда мы приближаемся к нам, зрение продолжает проясняться.

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

Проливной дождь

Я подумал о том, чтобы сделать часть дождя немного лучше, объединив туман и дождь. Ведь во время дождя всегда бывает дымка, и машину для этого тоже полезно приучить. Для этого не требуется никакой новой функции. Мы можем добиться эффекта, последовательно вызывая оба.

Автомобиль справа на этом изображении почти не виден, и это реальный сценарий. В сильный дождь на дороге почти ничего не разглядеть.

Надеюсь, эта статья поможет вам обучить модель в различных погодных условиях. Полный код вы можете найти в моем профиле GitHub. И я написал много других статей, которые вы можете прочитать на Medium и на моем сайте WordPress.

Наслаждаться!