Фотостудия для кукол Барби

Барби известна как ролевая модель для девочек. Узнаваемость Барби в мире феноменальна – в России ее знают 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)  

 

Весь скрипт и библиотеки можно скачать из архива. 

И видео.