Соси кошек вместе с кодом! Эта статья участвует【Эссе "Мяу Звезды"】
Введение
Я видел много видео в Интернете, где офицеры, разгребающие дерьмо, посылают своих кошек, играющих на пианино. Хотя в нашей семье есть знатный владелец кота, но из-за отсутствия фортепиано он не может проявить свой художественный талант.
Как квалифицированный сгребатель дерьма, никто не может огорчить своего владельца кота, и он должен найти способ создать условия без условий. Поэтому мы решили сделать «электронное» пианино для нашего владельца кошки, чтобы владелец кошки мог полностью осуществить свою музыкальную мечту.
Хоть и говорят, что это "электронное" пианино, но из-за ограниченного времени (чтобы заработать консервированные деньги для хозяина кота) нет возможности купить механические детали для изготовления клавиатуры, поэтому я планирую сделать "нищенское версия», чтобы дать владельцу кота целый «виртуальный» ключ.
Кроме того, все мы знаем, что самых больших препятствий в обучении игре на фортепиано на самом деле всего два — левая рука и правая рука. Так что мы собираемся сделать что-то другое - играть на пианино головой.
Поэтому мы решили сделать один для владельца кота"Кошачья голова фортепиано", используйте камеру, чтобы зафиксировать положение головы кошки, разные положения соответствуют разным клавишам и производят разные звуки. Таким образом решается проблема временных и денежных затрат, а во-вторых, это не дает котовладельцу научиться выходить из себя на нас, а также позволяет котовладельцу в полной мере насладиться радостью музыки, убив трех зайцев. одним камнем Разве это не красиво.
(Мастер Кот: Так вы обманываете труд и капитал?)
общий дизайн
Чтобы реализовать пианино с кошачьей головой, необходимо решить три проблемы:
- Как снять на видео хозяина кота
- Как определить положение головы кошки
- Как играть на пианино и как показывать
Первый – это съемка видео. Первоначально я купил дешевую USB-камеру на Double Eleven, но она еще не пришла из-за медленной доставки. Таким образом, вы можете использовать мобильный телефон только для записи видео, чтобы имитировать камеру, чтобы сначала захватить изображение.
Обнаружение кошачьих голов — самая сложная часть, и я планирую использовать для этого глубокое обучение. Прежде всего, вам нужно собрать несколько фотографий владельца кошки и использовать инструмент аннотации, чтобы отметить голову кошки. Затем используйте модель YOLOV5 с открытым исходным кодом Megvii для ее обучения. Наконец, исходный код openppl, недавно открытый SenseTime, используется для развертывания вывода модели.
Что касается того, как играть на пианино, я планирую использовать для этого Мингуса. Обработка видео и часть графического интерфейса выполняются с помощью OpenCV.
Получение изображения и аннотация
Хорошо использовать мобильный телефон для получения изображения, но сложность заключается в том, как заставить владельца кошки послушно сотрудничать.
Здесь я пожертвовал артефактом - кефиром, несколько раз протаскал хозяина кота по дому и наконец подобрал несколько подходящих роликов
(Cat Master: Дедушка такой милый, не напои дедушку)
Когда видео было собрано, на компьютере с Windows под рукой не было установленного OpenCV, поэтому я нашел сайт для конвертации видео в картинку:Woohoo.IMG2go.com/convert-to-…, конечно, это также можно сделать с помощью OpenCV VideoCapture
После преобразования его в изображение я использовал инструмент для аннотаций, найденный на github:GitHub.com/Тайзу Таллинн/Ла…
- Как мы все знаем, кошки — это жидкости, поэтому маркировка тела кошки не способствует обнаружению, поэтому я, наконец, решил пометить голову кошки.
- Поскольку фон простой, а задача одна, обнаружение кошачьей головы можно выполнить, пометив небольшое количество изображений.
- При маркировке необходимо обращать внимание на формат этикетки.Обязательно используйте для маркировки шаблон, который может распознать модель YOLOV5.
Наконец, мы аннотировали 430 изображений, число обучающих, проверочных и тестовых наборов: 400, 20, 10.
Обучение модели YOLOV5
обучение модели
Сначала клонируйте исходный код YOLOV5 с github:GitHub.com/ultra Еще одна ICS…
В процессе обучения не было внесено слишком много изменений в код, а напрямую использовался обучающий скрипт в репозитории.train.py
python .\train.py --data .\data\cat.yaml --weights .\weights\yolov5s.pt --img 160 --epochs 3000
Чтобы увеличить скорость обучения, размер изображения может быть соответственно уменьшен. Размер изображения, используемый в этом эксперименте, составляет (160, 160)
Тестирование модели
После обучения модели используйте немаркированные изображения, чтобы убедиться, что модель обучена правильно. Тестовый скрипт также относится к YOLOv5.decect.py
предварительная модельтренироватьсявизуализация
предварительная модельпроверятьвизуализация
Способна правильно определить владельца кота, модель без проблем обучается
Экспорт модели
Чтобы лучше адаптироваться к развертыванию, мы преобразуем модель PyTorch вONNXМодель. Преобразование модели также может напрямую использовать сценарий преобразования YOLOv5.export.py
Развертывание логического вывода
Установка платформы вывода
Среда развертывания выбрала платформу SenseTime.openppl, может эффективно работать на архитектуре x86/CUDA и имеет интерфейс Python, с помощью которого можно легко создавать и развертывать проекты:GitHub.com/open PP out — универсальный...
Скачайте и скомпилируйте openppl:
git clone https://github.com/openppl-public/ppl.nn.git
cd ppl.nn
./build.sh -DHPCC_USE_X86_64=ON -DHPCC_USE_OPENMP=ON -DPPLNN_ENABLE_PYTHON_API=ON
После компиляции в./pplnn-build/install/lib
будет сгенерирован по путиpyppl
пакет, наборPYTHONPATH
Он готов к использованию после
Вывод модели
Следуйте примеру Python в репозитории., я написал ModelRunner для запуска сетевого вывода для заданного ввода:
def RegisterEngines():
engines = []
# create x86 engine
x86_options = pplnn.X86EngineOptions()
x86_engine = pplnn.X86EngineFactory.Create(x86_options)
engines.append(pplnn.Engine(x86_engine))
return engines
class ModelRunner(object):
def __init__(self, model_path):
self.__initialize(model_path)
def __initialize(self, model_path):
# register engines
engines = RegisterEngines()
if len(engines) == 0:
raise Exception('failed to register engines')
# create runtime builder
runtime_builder = pplnn.OnnxRuntimeBuilderFactory.CreateFromFile(model_path, engines)
if not runtime_builder:
raise Exception('failed to create runtime builder from file: %s' % (model_path))
# create runtime
self.runtime = runtime_builder.CreateRuntime()
if not self.runtime:
raise Exception('failed to create runtime')
def get_input_tensor_shape(self):
return self.runtime.GetInputTensor(0).GetShape().GetDims()
def forward(self, input):
if not self.runtime:
raise Exception('runtime not created')
# get input tensor info
tensor = self.runtime.GetInputTensor(0)
shape = tensor.GetShape()
np_data_type = g_pplnntype2numpytype[shape.GetDataType()]
dims = shape.GetDims()
# feed input data
input = np.ascontiguousarray(input) # use contiguousarray to avoid calc error
status = tensor.ConvertFromHost(input)
if status != pplcommon.RC_SUCCESS:
raise Exception('failed to set input data')
# start to inference
status = self.runtime.Run()
if status != pplcommon.RC_SUCCESS:
raise Exception('failed to run')
# wait for inference finished
status = self.runtime.Sync()
if status != pplcommon.RC_SUCCESS:
raise Exception('failed to sync')
# get output data
out_datas = {}
for i in range(self.runtime.GetOutputCount()):
# get output tensor info
tensor = self.runtime.GetOutputTensor(i)
tensor_name = tensor.GetName()
# fetch output data
tensor_data = tensor.ConvertToHost()
if not tensor_data:
raise Exception('failed to get output ' + tensor_name)
out_data = np.array(tensor_data, copy=False)
out_datas[tensor_name] = copy.deepcopy(out_data)
return out_datas
Предварительная и постобработка данных
Код для предварительной обработки данных относительно прост:
# preprocess
img = cv2.resize(img, (self.input_img_w, self.input_img_h)) # resize
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR -> RGB
img = img.transpose(2, 0, 1) # HWC -> CHW
img = img.astype(dtype = np.float32) # uint8 -> fp32
img /= 255 # normalize
img = np.expand_dims(img, axis=0) # add batch dimension
Поскольку входная форма (160, 160) и все изображения в обучении имеют одинаковую форму, почтовый ящик здесь не используется.
Что касается постобработки, стандартный YOLOV5 имеет три выхода, которые необходимо комбинировать с привязками на разных уровнях для расчета положения выходного поля. Однако модель ONNX, экспортируемая репозиторием, уже сделала эту часть работы за нас, нам нужно только отфильтровать box_score и class_score в результате и выполнить nms. Я не буду публиковать здесь код постобработки.
сделать ключи
звук клавиатуры
Здесь я использую звук клавиатуры Python.mingusБиблиотека решается, установка очень простая:
pip3 install mingus
pip3 install fluidsynth
Воспроизведение заметок также очень просто, всего несколько строк кода:
from mingus.midi import fluidsynth
fluidsynth.init('/usr/share/sounds/sf2/FluidR3_GM.sf2', 'alsa') # for ubuntu
fluidsynth.play_Note(64, 0, 100) # 标准音 a1
дисплей клавиатуры
Графика клавиатуры сделана с помощью OpenCV
На клавиатуре фортепиано есть четыре вида клавиш - три вида белых клавиш и один вид черных клавиш.Здесь Enum используется для описания этих четырех видов клавиш, и различные виды клавиш подвергаются разной графической обработке, и, наконец, абстрагироваться в классыPianoKey
:
class KeyType(Enum):
WHITE_KEY = 0,
WHITE_KEY_LEFT = 1,
WHITE_KEY_RIGHT = 2,
BLACK_KEY = 3
PianoKey
существует одинplay(self, position)
Интерфейс, как только позиция попадает в диапазон клавиши, определяется, что клавиша нажата, и издается звук, соответствующий клавише.
Поместите картинку эффекта клавиши (желтый цвет - это клавиша, которая нажата, программатор подобрал цвет):
окончательный эффект
Соединив вышеперечисленные модули, мы получим наше «пианино с кошачьей головой».
Вставьте окончательный рендеринг, красный прямоугольник — обнаруженная голова кошки, красная точка — центр поля обнаружения, используйте эту точку, чтобы коснуться клавиш:
видео демонстрация
Демонстрация видео:Woohoo.Proportion.com/video/BV17 также…
ссылка на репозиторий гитхаб:GitHub.com/ZiChenTipress/…