Увеличение изображения - это метод создания изображения и его использования для создания новых. Это полезно для таких вещей, как обучение беспилотному вождению автомобиля.
Представьте себе человека за рулем машины в солнечный день. Если начнется дождь, поначалу им может быть трудно управлять автомобилем в дождь. Но постепенно они к этому привыкают.
Искусственная нейронная сеть также находит затруднительным вождение в новой среде, если она не видела это раньше. Это различные техники увеличения, такие как переворачивание, перевод, добавление шума или изменение цветового канала.
В этой статье я расскажу о погоде. Я использовал библиотеку 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.
Наслаждаться!