Барби известна как ролевая модель для девочек. Узнаваемость Барби в мире феноменальна – в России ее знают 99%, Барби занимает 1-е место по продажам в мире в категории “классические куклы”. Ассортимент огромен, и это не только куклы, но и наборы одежды к куклам, а также тематические игровые наборы. Коллекционеры кукол для демонстрации своих кукол создают авторские наборы. Меня попросили создать набор Фотостудия для Барби. Набор будет использоваться в Музее кукол на КМВ. Для большей реальности Фотостудия делает реальные фото и распечатывает их в черно-белом цвете на реальном термопринтере, что создает иллюзию настоящей кукольной фотостудии.
Для фотостудии используются следующие компоненты:
- Плата OpenMV H7+
- Плата расширения OpenMV LCD Shield
- Термопринтер Adafruit
- Блок питания 12В
- Модуль понижающего стабилизатора на LM2596 – 2 шт
- Кнопка
- Детали, напечатанные на 3d-принтере
Электрическая схема подключения:
И внешний вид устройства
OpenMV H7+ — это система компьютерного зрения в виде компактного модуля камеры с низким энергопотреблением. Она отличается от обычных камер дополнительной начинкой с микроконтроллером для обработки изображения на лету и управления внешними устройствами.
Захватом изображения занимается светочувствительная КМОП-матрица OmniVision OV7725 размером 1/3″ с разрешением 640×480. Камера снимает видео в 8-битном режиме оттенков серого или цветном 16-битном формате RGB565 с частотой до 75 кадров в секунду. Поддерживаются форматы сжатия MJPEG, GIF и несжатое видео RAW. На камере предусмотрена подсветка RGB-светодиодом и два ИК-светодиода для съёмки в темноте.
Объектив с фокусным расстоянием 2,8 мм и диафрагмой F2.0 крепится через байонет со стандартной резьбой M12 с шагом 0,5 мм, поэтому к OpenMV H7 подходят сменные объективы от GoPro и других портативных камер.
За обработку изображения отвечает 32-битный микроконтроллер STM32H743VI от компании STMicroelectronics с вычислительным ядром ARM Cortex-M7. Процессор работает на тактовой частоте до 480 МГц, у него на борту 1 МБ оперативной памяти SRAM и 2 МБ Flash-памяти.
Начинка справляется с алгоритмами компьютерного зрения разной сложности, среди которых:
- анализ изображений через TensorFlow Lite;
- детекция движения в кадре;
- распознавание лиц;
- отслеживание цветных объектов и маркеров;
- отслеживание движения зрачков;
- определение и считывание QR-кодов, штрих-кодов и AprilTags;
- скоростное отслеживание линии;
- распознавание геометрических объектов;
- сравнение изображения с заданным шаблоном.
Для записи видео и хранения рабочих данных используется карта памяти microSD. Скорость чтения и записи до 100 Мбит/с позволяет оперативно подгружать объекты для машинного зрения
LCD Shield для мгновенного отображения картинки с камерного модуля OpenMV без использования внешних проводов и мультимедийных устройств. Разрешение дисплея 128×160 точек и глубиной 65536 цветов.
Плата расширения OpenMV LCD Shield подключается к контактам к OpenMV H7+, а для подключения платы OpenMV H7+ к кнопке и термопринтеру сделаем самодельный шилд
Напечатаем корпус и внизу корпуса разместим питание и модули стабилизаторов.
Разместим в корпусе термопринтер Adafruit, а плату OpenMV H7+ с шилдами разместим на панели и соединим к корпусу термоклеем
Написание программы
Умная камера программируется на MicroPython в среде разработки OpenMV IDE с поддержкой русского языка. Она объединяет в себе редактор программного кода, просмотр видеобуфера камеры и построение RGB-гистограмм в реальном времени, чтобы упростить процесс отладки.
Для работы с термопринтером Adafruit необходимо скачать библиотеку Adafruit_Thermal.
Термопринтер Adafruit позволяет печатать текст (включая русский), штрих-коды и изображения на чековых лентах из термальной бумаги стандартной ширины 57 мм и диаметром рулона до 36 мм. Способ печати заключается в использовании специальной накалённой головки, которая буквально выжигает текст на бумаге. Температура головки доходит до 200 градусов Цельсия. В местах воздействия бумага темнеет и получается необходимый текст. Получается черно-белый принтер разрешением 8 точек на мм = 384 точек на линию.
Но нам не нужна черно-белая печать. Попробуем реализовать печать изображения в оттенках серого. Будем получать с камеры цветное изображение RG565 c разрешением 128×160 и сохранять его в файле bmp.
sensor.set_pixformat(sensor.RGB565) # sensor.set_framesize(sensor.LCD) # 128x160
Для каждой точки изображения будем вычислять значение в оттенках серого. Считываем данные из файла bmp. Формат файла bmp
File contents analysis
Byte 1,2 should be [0x4D 0x42]: 424D
Bytes 3-6 (Images Size) 0000073E
Bytes 7,8 (Must be zero) 0000
Bytes 9,10 (Must be zero) 0000
Bytes 11-14 (Image offset) 00000036
Bytes 15-18 (size of BITMAPINFOHEADER structure, must be 40 [0x28]) 00000028
Bytes 19-22 (image width) 00000018
Bytes 23-26 (image height) 00000019
Bytes 27,28 (number of planes in the image, must be 1) 0001
Bytes 29,30 (number of bits per pixel (1, 4, 8, or 24 [0x18])) 0018
— Note 24 bit color, is three bytes of red, green and blue, each
File signature analysis (Header analysis)
BMP file (Starts with 0x42 0x4D)
Формат RGB565 – каждая точка представлена 2 байтами.
r = ((color >> 11) & 0x1F); g = ((color >> 5) & 0x3F); b = (color & 0x1F); grey=(3*r+6*g+1*b)/2
Затем для имитации серого цвета будем выводить выводить на черно-белый принтер матрицу 3х3, Пиксель шкалы серого со значением от 0 до 255 будет преобразован в черно-белую матрицу 3×3, например:
Но т.к. печать происходит построчно, мы будем сначала создавать bitmap-файл, а затем его распечатывать средствами библиотеки Adafruit_Thermal.
Создание bitmap-файла из bmp
mask=[[1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,1,1,1],[0,1,1,1,1,1,1,1,0], [0,1,1,1,0,1,1,1,0],[0,1,0,1,0,1,0,1,0],[1,0,1,0,0,0,1,0,1], [0,0,1,0,1,0,1,0,0],[0,0,1,0,0,0,1,0,0],[0,0,0,0,1,0,0,0,0], [0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]] def convertBMP_toBitmap(fbmp): global arr1; pyb.LED(GREEN_LED_PIN).on() img=image.Image(fbmp) img1=img lcd.display(img1) try: with open(fbmp, 'rb') as bmp_file: filenamebitmap=fbmp.replace(".bmp","") #fbitmap=open("bitmap","wb") fbitmap=open(filenamebitmap,"wb") arr1 = [[0 for x in range(384)] for y in range(3)] # BitmapHeader headerbmp = bmp_file.read(14) filesize=int.from_bytes(headerbmp[2:6], 'little') fileoffset=int.from_bytes(headerbmp[-4:], 'little') print("filesize = ",filesize) print("fileoffset = ",fileoffset) width=128 height=160 # bmp_file.seek(fileoffset) col=0;row=0; #for d in range (0,(filesize-fileoffset)/2,1): print("create bitmap ",filenamebitmap) for row in range (0,160,1): for col in range (0,128,1): bytecolor=bmp_file.read(2) color=int.from_bytes(bytecolor,"little") #print("color= ",hex(color)) r = ((color >> 11) & 0x1F); g = ((color >> 5) & 0x3F); b = (color & 0x1F); #r = ((color & 0xF800) >> 11) << 3 #g = ((color & 0x7E0) >> 5) << 2 #b = ((color & 0x1F)) << 3 #grey=(2*r+7*g+1*b)/2 grey=(3*r+6*g+1*b)/2 setBits(col,grey) arr2 = [[0 for x in range(48)] for y in range(3)] for b1 in range (0,3): for b2 in range (0,48): bb=0x00; for b3 in range (0,8): bb=bb+(arr1[b1][b2*8+b3]<<(8-b3-1)) arr2[b1][b2]=bb; fbitmap.write(bb.to_bytes(1,sys.byteorder)); fbitmap.close() except OSError as e: print('error: {}'.format(e)) pyb.LED(GREEN_LED_PIN).off() def setBits(col,g): global arr1; g=int(g // 25) for i in range(0,3): for j in range(0,3): arr1[i][col*3+j]=mask[g][i*3+j] И печать bitmap файла def print_snaphot(ff): pyb.LED(BLUE_LED_PIN).on() filenamebitmap=ff.replace(".bmp","") img1=image.Image(ff) printer.printBitmapFromFile(384, 480, filenamebitmap) pyb.LED(BLUE_LED_PIN).off()
И основной цикл – печать при нажатии кнопки
startphoto = Pin('P9', Pin.IN, Pin.PULL_UP) while(True): lcd.display(sensor.snapshot()) if startphoto.value()==0: # filename=save_snaphot() print(filename) # convertBMP_toBitmap(filename) # print_snaphot(filename)
Весь скрипт и библиотеки можно скачать из архива.
И видео.