Русский
Русский
English
Статистика
Реклама

Fish

Самая сложная задача в Computer Vision

15.06.2020 12:08:41 | Автор: admin
Среди всего многообразия задач Computer Vision есть одна, которая стоит особняком. К ней обычно стараются лишний раз не притрагиваться. И, если не дай бог работает, не ворошить.
У неё нет общего решения. Практически для каждого применения существующие алгоритмы надо тюнинговать, переобучать, или судорожно копаться в куче матриц и дебрях логики.

Статья о том как делать трекинг. Где он используется, какие есть разновидности. Как сделать стабильное решение.

Что можно трекать


Трекингом называют задачу сопровождения объектов. От детекции задача отличается тем что нам не только надо задетиктировать объект в первом кадре, но и понять где он находится в следующем.

Что можно трекать?

  • Людей
  • Животных
  • Машины и прочую технику

Конечно, можно трекать что угодно (точки на пальцах, или на лице), но 99% задач из перечисленных категорий.

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

Люди


Трекинг людей нужен чаще всего.
Самая стандартная задача на которой больше всего решений трекинг людей на улице. Для этого даже большой челлендж есть (даже не один):



Где применяется трекинг на улице/в толпе? Всякие системы безопасности/защиты периметра. Иногда чтобы отслеживать кого-то.

Не сказать что существует готовое общее решение работающее всегда. Почему? В такой толпе даже человек неправильно всё разметит:



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



Примерно те же подходы используются при трекинге на предприятиях. Это очень важно для детектирования ситуаций плана вход в закрытую зону (пример с Хабра). Но может работать и для задач уровня помыл ли руки перед подходом к разделочному столу. Тут важнее не статистика, а качество решения.



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

Животные


Глобально, трекинг животных в 95% нужен только на фермах. В природе делают скорее детекцию, чтобы посчитать статистику. А на ферме очень полезно знать какая корова не отдоилась и куда она пошла. Как ни странно, но таких фирм очень много. Вот несколько которые решают эти задачи Cows.ai, Cattle-Care. Но, как водиться, таких не мало.

image
(Видео с сайта первых)

Можно трекать овец. Можно свиней.

А можно Рыбок! (картинка от google, но есть много разных фирм, например Aquabyte)

image

Машины и прочая техника


Машины и прочие самолёты обычно трекать очень просто. Они ездят по практически идеальным траекториям, что сильно упрощает работу алгоритма. Прочую технику зачастую трекают военные, и это редко встречается на практике.

А машины трекать нужно и в системах умного города, и в системах выписывания штрафов, и в всяких системах сопровождения гонок.



Как можно трекать


Есть несколько базовых алгоритмов, которые будут лежать в основе любого построения трека, и бесчисленное число комбинаций между ними:

  • Детекция объектов в кадре. Не важно что тут используется. Главное чтобы детекция выдавала положение объекта. Это может быть YOLO, SSD, или любой из десятков более новых алгоритмов.
  • Алгоритм распознавания объекта в кадре. Так называемая задача ReIndentification. Это может быть:

    1. Распознавание человека по телу
    2. Распознавание человека по лицу
    3. Распознавание типа автомобиля
    4. и.т.д, и.т.п.

  • Алгоритмы сопоставления объектов по физическим параметрам. Это может быть сопоставление по IoU(пересечение выделенного прямоугольника), сопоставление по скелету (насколько они похожи), сопоставление по положению на полу/на земле/на дороге. и.т.д.
  • Алгоритм межкадрового трекинга. Эта часть самая загадочная.
  • Сюда входит много алгоритмов оптического трекинга, оптического потока, и.т.д

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

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

Сейчас эти взаимосвязи пытаются обучать, или закладывать напрямую в алгоритм. Но всё слишком нестабильно. Классикой является алгоритм трекинга, который завязывает наборы детекций и матриц перехода в трек с учётом пропусков и появлением новых объектов. Обычно это различные фильтры Калмана, или нейронки.

Что важно отметить при переходе к алгоритмам трекинга


95% качества при трекенге, как впрочем и у любой задачи ComputerVision установка камеры.
Сравните:




Где проще посчитать людей?

Но помните, установка камеры сверху зачастую усложняет создание системы. Ни Yolo ни SSD, ни стандартные ReID алгоритмы не будут работать по таким объектам. Потребуется полномасштабное переобучение (ниже приведу пример).

Детекция объектов в кадре


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

Если вы не разбираетесь что вам надо, то на июнь 2020 хорошим вариантом является YOLOv4, обеспечивающая баланс качества/производительности. Для максимальной скорости можно посмотреть в сторону YOLOv3- tiny или в сторону быстрых версий EfficientDet.

(Ещё мутный YOLOv5 появился за время написания статьи, но там какая-то хрень).

Но в ряде случаев эти решения могут не быть оптимальными.

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

Для трекинга детекция это основа. Какие бы крутые у вас не были следующие алгоритмы без детекции трекинг не будет работать.

Прямым следствием является то, что детектор скорее всего придётся преобучать по вашему датасету.

Обычно детекторы учатся на каких-нибудь универсальных датасетах (например Microsoft COCO):

image

Там мало людей которые плохо видны, скорее всего нет камеры похожей на вашу (ИК, широкий угол). Нет ваших условий освещения, и многое другое.

Переобучение детектора по датасету из используемых условий может уменьшить число ошибок в 2-3 раза. Лично я видел примеры где и в 10-20 уменьшало (процентов с 60-70 точности до 98-99).

Отдельным моментом стоит отметить что в ситуациях когда люди/животные/машины в нестандартных ракурсах переобучать придётся всегда. Вот пара примеров как работает непереобученный Yolo v4:





Несколько мест где можно взять готовые нейронки для детекции:


Я не буду подробно заостряться на этой теме, про детекцию безумно много статей.

Person ReIndentification


Предположим вы мельком в толпе увидели эффектную блондинку в красном платье. Выходите из толпы, и внезапно блондинка тоже вышла.



Вы не видели как она вышла из толпы. Вы не видели её последние 30 секунд. Но вы же знаете, что это она.

Тут работает именно алгоритм распознавания по телу.

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

Особенно после разрыва трека.

Существует несколько крупных датасетов для обучения таких алгоритмов. Самые известные:

  • Market-1501
  • CUHK03
  • MARS
  • DukeMTMC
  • iLIDS-VID

Большая часть датасетов собрана каким-то таким образом:

image

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

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

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

image

У нейронной сети создаётся бутылочное горлышко, из небольшого числа нейронов. А на выходе нейронной сети будет число нейронов по числу людей в датасете. Сеть научится распознавать людей, но параллельно научится описывать их в качестве небольшого вектора.

Так просто никто уже не делает. При обучении последних версий ReID используется и hard negative mining, и различные хитрые аугментации и трюки с подрезанием, и фокальные потери, и многое-много другое.

Всё бы хорошо, но у ReID алгоритмов есть слишком много проблем. Даже по датасетам которые идеально под них заточены (улица, одинаковые условия освещения, почти одинаковое время съемки, отсутствие пёстрого фона, нет больших пересечений людей, нет заслонений объектами переднего фона, человек целиком в кадре, и.т.д., и.т.п.), даже у самых последних моделей точность будет на уровне 95-98%

На практике такие сети очень сложно использовать: Предположим у вас завод где все ходят в одинаковой униформе

Так что данный класс сетей надо использовать в очень ограниченных задачах, или при очень аккуратном контроле, иначе он не привнесёт точности в ваш алгоритм.

Ниже мы рассмотрим как алгоритмы ReID используются в сетях трекинга и иногда ощутимо повышают результат.

ReID по одежде


Одна из вариаций ReID распознавание по одежде:

  1. Пример сорсов
  2. Пример алгоритма
  3. Пример алгоритма

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



Например, если у вас люди носят три типа формы можете обучить по ним!

ReID по лицу


Отдельно стоит упомянуть про возможность трекинга по лицу. Если с вашей камеры видно лицо, да ещё и в разумном качестве бинго! Вы можете сделать хорошую систему трекинга.

Про распознавание по лицам можно почитать например тут 1, 2.

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

Про точность распознавания лиц и их применимость я писал длинную статью.

Пусть будет ещё картиночка про олдфажеский TripletLoss для обучения лиц, который уже не используется:



ReID не на людях


Алгоритм реиндентификации очень удобен для трекинга. Хотите посмотреть где он работает на животных? Например тут:


Для некоторых рыб можно вообще обучить аналог лицевого ReID, с достаточно высокой точностью. Вот тут рассказано подробнее 1, 2

Очень хорошо ReID работает на коровах. Каждая корова по шкуре уникальна: 1, 2

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

Прочие ReID


Какие-то аналоги ReID можно использовать для трекинга автомобилей (например распознавание марки автомобиля). Можно обучить ReID для трекинга людей по головам.

Но так как ReID обычно обучать муторно достаточно редко вижу его использование для трекинга вне случаев описанных выше (не для трекинга применений масса!).

Алгоритмы сопоставления объектов по физическим параметрам


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

  • Размеры выделенной области (bbox) объекта. Чем более похожи объекты в соседних кадрах по размеру тем с большей вероятностью это один объект.
    image
  • Положение центра масс. Чем ближе центр масс к планируемой траектории тем с большей вероятностью это один и тот же объект.
  • Скорость передвижения объекта в прошлых кадрах. Чем больше скорость и ускорение соответствуют какому-то объекту, тем с большей вероятностью это одно и то же.
  • Координаты проекции на землю. Можно вычислить если знать как висит камера. Для установок камер вертикально сверху совпадает с позапрошлым пунктом. Хорошо работает при трекинге машин.

  • Близость позы. ReID алгоритмы работают в длительном окне времени, не учитывая позу человека, стараясь отвязаться от неё. Но если сэтап имеет достаточно высокую скорость обработки, то наоборот, можно привязывать соседние детекции по позе человека.

    image
  • Наверняка есть что-то что я ещё забыл. Но оно сильно реже на практике.

Оптический трекер


Ну вот мы и пришли. К могучем, огромному, бесполезному оптическому трекингу!

По этой теме фанатеют многие. Смысл этого класса алгоритмов очень простой.

Пусть в первом кадре у нас есть заданное положение объекта. Нужно найти его в следующем.
И не важно какой объект: человек, машина, точка на руке, вертолёт или падающий лист.

Задача достаточно простая и древняя. Для неё существует множество подходов. Начинающихся ещё с OpticalFlow задачи:

image

(найти для каждой точки кадра порождающую её точку с прошлого кадра).

А потом пошло поехало:


И многое, многое другое.

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

Обычно после этого он натыкается на примеры из Эндриана Розеброка:


И использует их в продакшне (видел минимум в двух фирмах)

Но нет Не надо так. Каждый раз когда вы берёте пример с pyimagesearch и несёте его в прод вы делаете грустным ещё одного котика (с).



Эдриан хороший популяризатор. Возможно он даже знает как делать машинное зрение. Но 95% его примеров это пример использования готовой библиотеки. А готовая библиотека почти всегда бесконечно далека от прода.

Разберём что может пойти не так (специально записал!):

  1. Похожие объекты, оптический трекинг не учитывает направление и скорость, он выбирает оптимальный минимум ближе всего:


  2. Неадекватный детектор потери. Например человек входит в дверь. Оптический трекер это не любит:

  3. Неадекватная реакция на сильно изменение формы. Резкий разворот/поворот убивает трекеры:

  4. Перепады яркости

Есть и другие, менее значительные причины, которые тоже могут проявится. Это приводит к нескольким утверждениям:

  1. Если у вас более-менее стабильная детекция оптический трекер нет смысла использовать
  2. Если у вас нет опыта тонкого тюнинга таких алгоритмов то тоже не надо брать такое
  3. Если у вас есть несколько независимых алгоритмов, а их результаты вы планируете склеивать в ручную то лучше не надо использовать оптический трекер. Только при автоматической склейке где какой-то ML алгоритм выберет параметры склейки сам.

Это не значит, что оптический трекер не имеет смысла вообще. Есть небольшой процент ситуаций когда его использование может быть оправданно. Какие? Апологеты этого подхода выделяют два типа ситуаций:

  1. Оптимизация скорости работы. Запускать детектор пореже, а трекинг меньше ест.
  2. Универсальность работы на любом железе.

Но по мне оба аргумента очень сомнительны при современном уровне развития технологий.

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

И вот что выдаст обычный YOLOv4 (детекции клею через SORT, про который будет ниже):


Понятно, что YOLO можно дообучить, и всё будет сильно лучше. Но, наверное, когда нет таких сил можно и через трекинг прототип сделать.

А вот что будет оптическим трекером из OpenCV (GOTURN, каждый раз когда разрыв реинициализирую заново):


И да, ниже по тексту мы столкнёмся с алгоритмами которые включают в себя оптический трекер по умолчанию.

Часть 2


Как всё это завязать.

Нагенерили детекций. Возможно нагенерили каких-то метрик близости между ними. Как всё это завязать друг с другом?

Есть много подходов. Проблемы есть почти везде. Начнём с простого.

Классическая математика


Самым классическим и стабильным подходом является модель движения + алгоритм целераспределения. Собственно, все эти алгоритмы целераспределения и родились в 60-70 годах для слежения за целями в воздухе и космосе.

Как ни странно, один из самых классических подходов, где в качестве модели был взят фильтр Калмана, а в качестве целераспределения венгерский алгоритм выстрелил в 2016, взяв первое место в MOT соревновании (SORT). И если по точности он был плюс-минус сравним с другими решениями, то по скорости бил в 20 раз. А по понятности в 100.

Почему этого не произошло раньше? Не знаю. Подход настолько классический и дубовый, что для определения параметров спутников нам его ещё году в 2008 на кафедре МФТИ преподавали. И эта программа, как я понимаю, лет 20-30 не менялась.
Скорее всего так вышло потому, что не было ни одной opensource реализации нормальной. Всё пряталось в глубинах продуктового софта.

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

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

Или в конце концов близость между ReID описаниями. Именно так делает, например DeepSORT.

Сравните качество работы SORT против Deep SORT:



И то и то собрано на базе детекции из Yolov4 которая выглядиттак.

Надо сказать что данный подход до сих пор в топе.

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

А вот так будет выглядеть то же самое видео что и выше (правда я запустил не самую мощную сетку, как я понял):


На более мощной чуть лучше детекция работает. Тут явно завалена ближняя часть.

Только вот не везде этот подход будет работать. ReID нестабилен в большом временном окне. ReID не будет работать по одинаковым вещам как машины, или олени. Или, например, работники в униформе.

Мы наталкивались на задачи когда ReID был самой плохой метрикой для людей, из всех перечисленных.

Нейронончки везде


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

image

К этому подходу будет относится и упомянутые уже LSTM сети трекинга:

image

И так же упомянутые сети трекинга скелетов:



image

Казалось бы. Раз можно достичь высокие результаты так и надо делать всегда! Но, как ни странно, нет.

Предположим вы решили обучить трекер по головам. Подошли серьёзно. И LSTM-сеть с пачкой кадров взяли. И ReID добавили, и детектор переобучили.

Только вот есть одна проблема. Обучать по видео это огромные объемы датасетов. Длительная разметка, не понятен профит от обучения относительно того же SORT. Даже FairMot надо переобучать. И куда сложнее переобучать, чем отдельно YOLO.

И самое плохое. Если вы сегодня обучаете по головам, а завтра люди с наклоном (или объектив поменяли) то это разные датасеты. И если для детекции это сделать несложно (у нас сейчас на такую итерацию уходит в среднем 3-4 дня), то собрать датасет треков это огромная задача.

Как в реальности


Мы затронули интересный вопрос. А как всё устроено на практике?. Тут всё интересно. По сути, как мне кажется: на практике всё либо очень сложно, либо очень просто.

Очень сложно когда надо получить какой-то качественно новый результат. Например водить автомобиль. Тогда рождаются вот такие химеры:



Бывает и сложнее. Я почти уверен, что если у любой Tesla или Yandex-машинке разрисовать схему обучения алгоритмов трекинга то там сума сойдёт даже адекватный человек.

По тому что видел лично я:

  • В двух стартапа видел схему с уже упомянутого pyimagesearch. Когда происходила детекция, а для связывания детекций использовался оптический трекер. В одном стартапе работало на гране допустимого качества. Во втором не работало.
  • В одном стартапе разрабатывали детектор + аналог МНК для слежения. Но там трекались точки на человеке. Работало хорошо.
  • Сами участвовали/разрабатывали несколько систем трекинга авто. И везде трекинг был через какого-нибудь Калмана/аналог с МНК. Видел несколько фирм где в целом было так же. Работало у всех хорошо.
  • Видел 3 фирмы где в качестве трекинга использовался SORT. Одной из них разрабатывали процесс обучения детектора, который подавался в SORT. У всех всё было классно, всё работало.
  • Участвовали/до сих пор участвуем в разработке стартапа где трекаются люди в помещениях. Используются почти все техники которые тут упомянуты. Но вес каких-то очень мал. Работает в целом неплохо. Но, конечно, хуже того что человек глазом может.

Что посоветую использовать


Я всегда считаю что простота залог успеха. Мне больше всего нравится SORT. Пока писал статью написал простой пример того как можно SORT использовать, строчек на 20. Вот тут описание того как оно работает.

Это сработает и для трекинга людей, и для машин, и для котиков.


Если вы хотите залезть в ReID то проще всего это будет сделать через DeepSort. Но надо понимать, что ReID это огромный мир, вариантов использования масса. Многие из них напрямую не связаны с трекингом.

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

Вообще, правильно помнить, что без правильного оборудования трекинг это всегда мучение. Хорошая и правильно поставленная камера >> алгоритма трекинга.

Если вы решили трекать что-то сложное или нестандартное, или захотели сильно повысить точность того что у вас есть вам придётся использовать большинство описанных техник!

P.S.


Тема трекинга очень большая. Я наверняка что-то забыл. Что-то, может, неправильно написал. Да и примеров не много. Но это всё можно поправить в комментариях! Особенно последний пункт.
Подробнее..

Как приручить консоль, или 5 шагов к жизни с командной строкой

25.01.2021 16:17:27 | Автор: admin

Всем привет! Меня зовут Осип, я Android-разработчик в Redmadrobot и я люблю автоматизировать всё, что автоматизируется. В этом мне помогает консоль, поэтому решил поделиться опытом, как настроить командную оболочку так, чтобы в ней было приятно работать и она ежедневно помогала вам решать задачи.

Статья для тех, кто использует Linux или macOS. Если у вас Windows, вы можете использовать WSL (приравнивается к Ubuntu).

Есть задачи, которые проще выполнить в командном интерфейсе, а не в графическом, к примеру:

  • посчитать количество строк кода в проекте,

  • скопировать все файлы с расширением .png из одной папки в другую,

  • постучаться API и посмотреть какой ответ он выдаёт.

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

Поверьте, стоит один раз настроить командную оболочку и разобраться, как в ней работать, и рабочее окружение начнёт помогать вам как хорошая IDE.

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


Статья только началась, а по тексту уже встречались и командная строка, и командная оболочка. Чем отличаются консоль, терминал, командная оболочка и командная строка?

Если объяснять из центра наружу: командная строка строка, где пользователь пишет команды; командная оболочка программа, которая интерпретирует команды, введённые в командную строку и выводит результат.

Термины консоль и терминал в статье используются как синонимы и обозначают программу для ввода и вывода информации. В терминале запускается командная оболочка.

Подробнее о различиях можно почитать на Ask Ubuntu: What is the difference between Terminal, Console, Shell, and Command Line?

В статье будут встречаться примеры команд. Если по ходу прочтения вы не понимаете, что делает консольная команда, скопируйте её и вставьте в ExplainShell. Благо Роскомнадзор перестал его блокировать после разблокировки Telegram.

Зачем вообще использовать командную строку

Дисклеймер: Я не призываю использовать только командную строку и отказаться от графического интерфейса. Нужно просто учитывать командную строку при выборе инструмента для решения задачи.

Когда хотят рассказать чем же хорош CLI, выделяют разные преимущества перед GUI:

  • Доступность. Командная строка доступна везде. Внутри Android Studio есть вкладка с командной строкой. Можно и вовсе настроить drop-down терминал (ещё его называют quake style), который будет появляться поверх всех приложений по нажатию сочетания клавиш.

  • Многофункциональность. Одна точка доступа к любым утилитам.

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

  • Легковесность. Как правило, CLI утилиты используют меньше ресурсов.

Меня как разработчика больше всего впечатляет, как можно комбинировать CLI утилиты. Текст интерфейс общения, который понятен для всех утилит с командным интерфейсом. Утилиты принимают на вход текст и возвращают тоже текст. Это один из принципов Unix, которые сформулировал Дуглас Макилрой в 1978 году:

Пишите программы, которые делают одну вещь и делают её хорошо.


Пишите программы, которые бы работали вместе.


Пишите программы, которые поддерживают текстовые потоки, потому что это универсальный интерфейс.

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

Примеры из жизни

Я задал вопрос коллегам-роботам: Для чего вы чаще всего открываете терминал? Получился такой ТОП-5:

  1. Работа с Git там, где не хватает графического интерфейса.

  2. Установка пакетов и управление зависимостями (подробнее про менеджер пакетов поговорим в разделе Устанавливаем менеджер пакетов).

  3. Работа с SSH.

  4. Проверка API с помощью curl.

  5. Когда нужно грохнуть процесс.

Есть и менее очевидные применения:

  1. Скачать видео из YouTube поможет youtube-dl. Качаете подкаст и нужна только аудио-дорожка? Добавьте к команде флаг --audio. Хотите скачать весь плейлист или даже весь канал? Подставляйте ссылку на канал и готовьте побольше свободного места.

  2. Хотите посмотреть отличия между файлами? Выполните команду diff и укажите пути до файлов, которые надо сравнить.

Шаг 1: Открываем терминал

Не терминал, а эмулятор терминала. (c) Департамент зануд

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

cool-retro-terminalcool-retro-terminal

Выбор терминала это тема для отдельной статьи. Кратко: если у вас Linux, начните с этого списка. На macOS популярен iTerm2, но я его не использовал, поэтому не могу ни поругать, ни похвалить.

Для меня важно чтобы и на компьютере с Linux, и на рабочем ноутбуке с macOS был один и тот же терминал с одинаковыми настройками. Я выбирал среди кроссплатформенных и остановился на kitty.

Шаг 2: Устанавливаем менеджер пакетов

Мы оказались в терминале. Первое, с чем нужно разобраться, менеджер пакетов.

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

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

Менеджеры пакетов в Linux

В дистрибутивах Linux менеджер пакетов есть по умолчанию. В Ubuntu, Debian и Mint это apt-get, а в Manjaro и ArchLinux pacman.

Чтобы установить пакет достаточно в терминале написать apt-get install [package]. Если у вас pacman, то pacman -S [package]. Может понадобиться sudo в начале, чтобы выполнить команду с правами root.

Чтобы обновить все пакеты с помощью apt-get введите команду apt-get update && apt-get upgrade. В pacman pacman -Syu.

В pacman много флагов и сложно сразу запомнить нужные. Ещё одно неудобство он не поддерживает установку пакетов из репозитория AUR. Это репозиторий, в который могут загружать пакеты любые пользователи. Исправить минусы помогут утилиты, которые упрощают работу с pacman. Рекомендую попробовать yay.

Менеджеры пакетов в macOS

В macOS придется установить пакетный менеджер. Самые популярные Homebrew и MacPorts. Homebrew активнее поддерживается сообществом, а пакеты в нём обновляются чаще, поэтому лучше использовать его. Для установки скопируйте актуальную команду установки c официального сайта. Эта команда скачает скрипт установки и запустит его.

Может понадобиться установка XCode Command Line Tools. Это базовый набор консольных инструментов clang, git, make и других. Он не зависит от XCode, а называется так, потому что необходим XCode для компиляции.

Теперь, чтобы установить пакет, достаточно в терминале написать brew install [package].

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

Шаг 3: Устанавливаем командную оболочку

Чтобы было проще работать, командная оболочка должна вам помогать. В ней должен быть поиск по введённым ранее командам, а ещё должно работать автодополнение. Здорово, если будут подсказки, которые учитывают, какие команды вы используете чаще других. Не помешает подсветка синтаксиса и ошибок при вводе команд.

Все примеры в статье будут сделаны с использованием командной оболочки fish. Эта командная оболочка проста для освоения и в ней все нужные функции работают из коробки.

Чтобы узнать, какая оболочка используется по умолчанию у вас, выполните команду echo $SHELL. Скорее всего, команда выведет /env/bash или /env/zsh это самые популярные оболочки. Если хотите сравнить возможности bash, zsh и fish, посмотрите эту таблицу.

Установим fish c помощью менеджера пакетов:

# Если pacmansudo pacman -S fish# Если apt-getsudo apt-get install fish# Если brewbrew install fish

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

Fish установлен. Запускаем его командой fish:

osip@homepc ~ % fishWelcome to fish, the friendly interactive shellType `help` for instructions on how to use fishosip@homepc ~>

Теперь можно настроить внешний вид. Команда fish_config откроет в браузере страницу настроек. Здесь можно настроить цветовую схему, приглашение командной строки (prompt), посмотреть список функций, переменные окружения, историю команд и список горячих клавиш. Здесь же можно добавлять, редактировать и удалять аббревиатуры команд. Про аббревиатуры поговорим чуть позже.

Fish по умолчанию

Закройте терминал и откройте его заново. Вы окажетесь не в fish, а в командной оболочке по умолчанию. Есть два варианта, как сделать так, чтобы открывался fish:

  1. Назначить fish командной оболочкой по умолчанию.

    Нужно учитывать, что скрипты инициализации текущей командной оболочки не будут выполняться. Команды и переменные окружения из .bashrc, .bash_profile, .zshrc и т.д, нужно переместить в .config/fish/fish.config , а затем адаптировать под синтаксис fish.

  2. Использовать fish только как интерактивную оболочку.

    Это более безболезненный способ, потому что не нужно мигрировать скрипты и переменные окружения. В конце скрипта инициализации текущей командной оболочки нужно запустить fish. Добавьте строку exec fish в файл .bash_profile, если у вас bash или в .zshrc, если zsh. Эти файлы находятся в корневой директории пользователя.

    На ArchWIki есть более подробное описание этого и еще нескольких способов.

Поиск по истории

Давайте-ка посмотрим, что умеет fish. Если еще не установили, можно попробовать в браузере. Я изменил только цвета и prompt, больше ничего не настраивал.

Когда вы начинаете набирать команду, fish подсказывает команды и аргументы, которые вы использовали раньше. Чтобы применить подсказку нажмите . Подставить одно слово из подсказки Ctrl+.

sample_command это демонстрационная функция. Она принимает любые параметры и ничего не возвращает.

Чтобы ввести предыдущую команду, нажмите клавишу . С помощью клавиш и можно перемещаться по истории команд. Если командная строка пуста, команды будут листаться по очереди. Если в командной строке есть текст, то история будет фильтроваться по нему.

Автодополнение

Начните писать любую команду и нажмите Tab, не дописывая её до конца. Попробуйте с командой git config:

Дополнение работает с командами, подкомандами и аргументами. Вместе с вариантами дополнения выводится описание подкоманд из документации.

Если утилита не поддерживает автодополнение, fish умеет создавать дополнения из документации man. Для этого нужно выполнить команду fish_update_completions.

А что с путями? Например, хотим перейти в папку dev/tools/jarjar/:

Дополнение путей тоже работает на Tab. Для перехода по пути не обязательно писать команду cd в начале. А еще работает дополнение, если написать первую букву имени каждой папки в пути. Если указан несуществующий путь, он подсвечивается красным.

Сложно запомнить все нужные флаги у команд. Хочу вывести дерево файлов, но не помню, как ограничить его глубину и сделать так, чтобы вывод был цветным. Для такого случая есть Shift+Tab дополнение с поиском:

Автодополнение может сработать в самых неожиданных местах, например, так работает автодополнение для команды kill:

Убийство Android Studio на глазах у studentdУбийство Android Studio на глазах у studentd

Wildcards

В fish, как и в bash, есть поддержка wildcards. Wildcards позволяют выполнить команду для нескольких файлов.

Выводим все файлы с расширением .md в текущей папкеВыводим все файлы с расширением .md в текущей папке

* соответствует любой строке
** соответствует любой иерархии папок, то есть рекурсивно заходит во вложенные папки

Применим wildcard, чтобы скопировать все файлы apk после сборки в папку output:

  • cp build/*.apk output/ скопирует все apk из папки build.

  • cp build/**.apk output/ скопирует все apk из папки build и из всех вложенных папок. То, что надо.

Функции, алиасы и аббревиатуры

Большиство команд fish это функции. Можно писать и свои функции. Синтаксис такой:

funcion [название]    [тело функции]end

Если функцию нужно сохранить для будущих сессий, не забудьте выполнить команду funcsave [название] после того как напишете функцию и проверите, что она корректно работает.

Для часто используемых команд можно создать более короткие синонимы алиасы. В fish команда alias создаёт однострочную функцию.

Как выглядит alias?

Флаг --save указывает, что нужно автоматически вызвать команду funcsave после создания алиаса. Таким образом алиасы сохранятся для будущих сессий.

Другой вариант сокращения команд аббревиатуры. Они настраиваются командой abbr или в fish_config во вкладке Abbreviations.

Удобно создавать аббревиатуру одновременно в английской и русской раскладках (см. скриншот). Такая аббревиатура выполнится, даже если вы забыли переключить раскладку клавиатуры.

Аббревиатуры подставляются на лету, когда вы нажимаете Space или Enter. В отличие от алиасов, аббревиатуры не являются функциями.

И па и gf превращается в git fetchИ па и gf превращается в git fetch

Шаг 4: Изучаем арсенал

Командная оболочка есть, теперь нужны команды.

Консольные утилиты могут быть с CLI и TUI. Command Line Interface (CLI) программа принимает команды через командную строку. Так работает большинство утилит. Text User Interface (TUI) интерфейс рисуется псевдографикой и по нему можно кликать мышкой как по GUI.

TUI для SpotifyTUI для Spotify

CLI не нужно бояться. На замену старым утилитам появляются новые с улучшенным UX, ориентированные на человека, а не на скрипты.

Например, многие старые утилиты, которые выводят размер файла, по умолчанию выводят его в байтах. А утилита df вообще выводит свободное место на диске в количестве блоков по 512 байт.

Чтобы выводились понятные человеку размерности, нужно добавить флаг -h (human readable). Цветной вывод удобнее читать, но он тоже по умолчанию обычно отключен и включается добавлением флага, чаще всего -C. В современных же утилитах по умолчанию включен цветной человекопонятный вывод.

Стандартные команды

Чтобы пользоваться командной строкой, нужно знать несколько стандартных команд:

  • cd [сhange directory] команда для навигации по файловой системе. Если запустить её без аргументов, вы окажетесь в домашней папке;

  • cp [copy], mv [move], rm [remove] команды для копирования, перемещения и удаления файлов, соответственно;

  • mkdir [make directory] команда для создания папки;

  • echo выводит строку, которую ей передали.

Если команда долго работает и вы не хотите дожидаться её завершения, прервите её выполнение сочетанием клавиш Ctrl + C.

Помощь: man, help, tldr

Есть несколько способов получить справку по команде.

man выводит полную справку:

  • описание команды,

  • список аргументов и описание каждого из них,

  • какие переменные окружения использует утилита и для чего,

  • известные баги,

  • советы и примеры использования,

  • другая информация, которую посчитал полезной разработчик.

Если ввести man man, вы получите справку по команде man, где всё это подробно описано.

man это утилита с TUI, в ней есть горячие клавиши. Для поиска нажмите /, а для выхода q. / и q стандартные клавиши для поиска и выхода, они работают во многих TUI утилитах. Ещё один стандартная клавиша ?, она открывает справку.

Можно выполнить команду из man для этого нажмите ! и введите команду. Хотите открыть man для другой команды внутри man или сразу попробовать выполнить команду, следуя документации? Легко.

Страницы в man пишут разработчики утилит. Если разработчик не написал справку, man выдаст No manual entry for [command]. Но даже если нет страницы в man можно вывести краткую справку с помощью флага --help. Попробуйте написать man --help.

Для команд fish можно открыть справку в браузере командой help <command>.

Если читать мануалы некогда, то поможет утилита tldr. Она отображает типичные случаи использования команд:

tldr tldrtldr tldr

Объединяем команды

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

Чтобы направить вывод одной команды на вход другой, используется оператор |. Он называется pipe, а на русский его переводят как конвейер. Если мы хотим подать вывод команды find_bone на вход команде eat, нужно между этими командами поставить трубу (pipe):

$ find_bone | eat

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

$ echo -e "spot\\nhandle\\npick\\natlas" > robots.txt$ cat robots.txt | sortatlashandlepickspot

Оператор | нам уже знаком, но что делает >? Этот оператор направляет вывод команды в файл. После этого командой cat мы достаём содержимое файла и с помощью оператора | отдаём на сортировку.

Современные утилиты

Просмотр списка файлов: ls, tree exa

Для просмотра списка файлов в папке обычно используют стандартную команду ls, а для просмотра иерархии папках tree. Обе эти утилиты можно заменить более дружелюбной утилитой exa.

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

Скриншоты. Сравнение ls, tree и exa.
Сравнение вывода ls и exaСравнение вывода ls и exaСравнение вывода tree и exaСравнение вывода tree и exa

Бонус: В exa можно совместить два режима вывода.

Просмотр запущенных процессов: top htop

top и htop. Обе утилиты выводят список запущенных процессов, но htop делает это гораздо приятнее.

В htop можно сортировать процессы по разным столбцам, нажимая на них. Кнопки в нижнем меню тоже нажимаются. Столбцы и информационные блоки в шапке настраиваются можно убрать лишнее и добавить нужное.

А как выглядит top?

Работа с JSON: jq

jq незаменимая утилита, если вы работаете с JSON. Проще показать на примерах что умеет делать jq.

Валидируем json:

$ echo '{"model": spot}' | jq typeparse error: Invalid numeric literal at line 1, column 15$ echo '{"model": "spot"}' | jq type"object"

Форматируем json:

$ echo '{"model":"spot"," type":"robodog"}' | jq{  "model": "spot",  "type": "robodog"}

Выкусываем из json'а только то, что нужно:

$ set json '[{"model": "spot", "type": "robodog"}, {"model": "atlas", "type": "humanoid"}]'$ echo $json | jq 'map(.model)' --compact-output["spot","atlas"]$ echo $json | jq .[0].model"spot"# А теперь пример посложнее$ echo $json | jq 'map({(.model): .type}) | add'{  "spot": "robodog",  "atlas": "humanoid"}

Это только малая часть возможностей. Все возможности смотрите в доке.

Другие утилиты

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

Консольный HTTP клиент: curl, wget httpie

httpie делает то же что curl отправляет запросы в сеть. Но посмотрите как отличается синтаксис и оформление вывода в curl и httpie.

На фотографии слева направо: curl и httpieНа фотографии слева направо: curl и httpie
Отображение содержимого файла: cat bat

cat и bat выводят содержимое файла, но bat подсвечивает синтаксис и отображает изменения из гита.

Поиск по содержимому файлов: grep ripgrep

ripgrep более быстрая версия grep. Сравнение скорости работы показывает, что ripgrep быстрее всех :)

Поиск файлов: find fd, fzf

Для поиска файлов можно использовать стандартную утилиту find. Для неё есть альтернатива fd. Она работает быстрее, поддерживает цветной вывод, по умолчанию игнорирует скрытые файлы и файлы из .gitignore. Посмотрите на гифку, которая демонстрирует работу fd.

Ещё одна утилита для поиска fzf [fuzzy finder]. Это утилита с TUI для интерактивного поиска файлов с использованием нечёткого поиска по названиям.

Ещё из приятного есть предпросмотр содержимого.

Подсчёт количества строк кода: wc tokei

Стандартная утилита wc [word count] считает количество слов, символов и строк в файлах, но чтобы с помощью неё посчитать количество строк кода в проекте, придётся написать что-то такое:

$ fd -g '*.kt' | xargs wc -l

У такой команды есть сразу несколько недостатков:

  • считаются все строки, включая комментарии и пустые строки,

  • ищутся только файлы с расширением .kt, для поиска других придётся менять команду,

  • сгенерированные файлы и остальные файлы, которые заигнорены в гите, тоже попадут в статистику,

  • такую команду долго писать.

Утилита tokei лишена перечисленных недостатков. Вот пример вывода tokei на одном из наших проектов:

Упс, файлы proguard засчитались в пользу PrologУпс, файлы proguard засчитались в пользу Prolog
Свободное место на диске: du ncdu

Ещё один пример разницы CLI и TUI. В отличие от du, ncdu это TUI. Тут же можно перейти внутрь папки или удалить ненужное нажав d.

Хм, накопилось много врапперов и кэшей Gradle. Можно почистить.Хм, накопилось много врапперов и кэшей Gradle. Можно почистить.
Сравнение файлов: diff delta

Отличная замена старому-доброму diff - delta. Можно использовать режим отображения side-by-side, если больше нравится, включить отображение номеров строк. Даже без дополнительных настроек диффы выглядят приятно:

Измерение времени работы программы: time hyperfine

Не верьте на слово, если я говорю, что одна утилита работает быстрее другой. Лучше проверьте.

Можно измерить время выполнения команды с помощью time (в macOS gtime). Эта утилита не предназначена для бенчмарков нет возможности прогрева, команда выполняется один раз. hyperfine подойдёт лучше, потому что изначально разработан для бенчмарков.

Попробуем замерить время выполнения команды tree:

Вывод команды tree перенаправлен в пустоту (/dev/null), потому что здесь не важен вывод команды, важно только время её выполнения. С hyperfine этого делать не нужно, он сам отбрасывает вывод команды.

Hyperfine умеет отслеживать признаки неправильного бенчмарка. Вот некоторые подсказки:

  • если во время замера есть выбросы, hyperfine посоветует закрыть другие программы, потому что они могут влиять на бенчмарк,

  • если первый запуск команды дольше остальных, hyperfine посоветует сделать прогрев, задав параметр --warmup N. Перед бенчмарком программа выполнится N раз.

Можно сравнивать скорость выполнения нескольких команд. Для этого нужно написать команды друг за другом, заключив их в кавычки:

$ hyperfine 'command_one' 'command_two' 'command_three'

Шаг 5: Сохраняем настройки

Чтобы не настраивать каждый раз все программы заново, нужно где-то сохранять настройки.

Конфиги это файлы. Обычно они хранятся в корневой директории пользователя вместе со скриптами инициализации командной оболочки, например, в папке .config/. Если вы установили fish, то найдёте папку .config/fish/ и в ней файлы с настройками. Самый простой способ сохранить конфиги сохранить их в Git-репозиторий.

Имена файлов и папок с настройками обычно начинаются с точки, поэтому одним словом их называют dotfiles. На момент написания статьи на GitHub опубликовано 138 425 репозиториев с именем dotfiles есть куда подсмотреть.

На странице awesome-dotfiles вы найдёте много информации про dotfiles. Там же есть ссылки на инструменты, которые помогают управлять dotfiles.

Я использую yadm. Мне важна кроссплатформенность, поэтому пригождается его возможность создавать альтернативные версии файлов для разных ОС.

Заключение

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

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

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

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

Если будут вопросы или вам понадобится помощь с освоением консоли, пишите мне в Telegram@osipxd. Ещё я иногда пишу в канал @rareilly заметки про Android и вообще про всё интересное, что нахожу. Спасибо за внимание!

Что ещё почитать

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru