В предыдущей статье я кратко описал свою прошивку для ККТ ШТРИХ-ФР-К, которая позволяет управлять термоголовкой, движками и соответственно выводить на печать все что угодно. В этой части я покажу как написать софт, который будет общаться с кассой и форматировать картинку для печати.

image

Начнем с описания пакетов, которые нам понадобиться

import cv2 
import numpy as np
import serial

cv2 — OpenCV библиотека компьютерного зрения. Берет на себя всю нагрузку по вводу и форматированию изображения.
numpy — библиотека для работы с массивами. Без нее OpenCV работать не будет.
serial — библиотека для работы с com-порт ПК.

ser = serial.Serial('COM5', 9600, write_timeout=1, timeout=0.1)  

Инициализация библиотеки со скоростью 9600 бод/сек.

frame1 = cv2.imread('ars2.jpg')

Функция, которая загружает изображение с жесткого диска.

height = frame1.shape[0]//(frame1.shape[1]//432)
frame1 = cv2.resize(frame1, (432,height), interpolation = cv2.INTER_AREA)

Функция изменения изображения по заданным размерам.

grayscaled1 = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)    
ret,thresh1 = cv2.threshold(grayscaled1,127,255,cv2.THRESH_BINARY)  
img_bin = thresh1/255

Первая строка делает изображение черно-белым. Вторая делает бинаризацию. Бинаризация — суть в том что бы превратить картинку в массив где каждый пиксель будет иметь значение 1 или 0. Касса не уметь делать оттенки черного, поэтому нужна такая обработка. В этой функции все пиксели со значением меньше 127 будут 0, больше 1.

for n in range(img_bin.shape[0]):
    for m in range(img_bin.shape[1]):
        #print(n,m)
        df=img_bin[n,m]
        if df==0:
            bb = bb+1*zz
        zz=zz*2
        if zz==256:
            zz=1

            print_img.append(bb)
            bb=0

Этот код превращает каждую строку в набор байтов. Т.е. берет первые восемь пикселей из строки и превращает их в байт. Затем берет следующие 8 из этой же строки и превращает их в байт.

  while i:
        while u!=1:

            u = ser.write( b'P') 
        u=0 
        ff=ser.read(1)
        if ff==b'B':
            i=0

Начало передачи. Если ответ не получен то не запуститься.

   i=54
    while i:
        while u!=1:
            #u = ser.write(bytes([print_img[y]]))

                u = ser.write(bytes([print_img[y]]))
                #buf.append(print_img[y])
            #print(bytes([print_img[y]]))
        y=y+1

        if y == len(print_img):
            f=f-1
            y=0

        i=i-1

        u=0

Отправка строки с проверкой закончилась ли картинка.

   if h==2:
        low=low+54
        h=0

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

 while i:
        ff = ser.read(1)
        #print(ff)
        if ff==b'D':
            i=0
    

Ждем букву Д для синхронизации. Это означает что аппарат напечатал строку и готов к получению данных.

Ссылка на исходники github.com/beetlea/shtrih-m-fr-k

Ну и вот вам видосики. К сожалению самого видоса с печатью Киану не сохранилось.


Комментарии (5)


  1. amphasis
    06.09.2019 09:30

    Первая строка делает изображение черно-белым. Вторая делает бинаризацию
    Почему именно бинаризация по пороговому значению, а не какой нибудь алгоритм с рассеиванием ошибок, например отсюда habr.com/ru/post/326936
    Одна маленькая особенность. Если изображения отправить на печать как оно есть, то высота изображения уменьшится в два раза.
    Вероятно имеет смысл еще до бинаризации изменить размер изображения до пропорций необходимых для печати


    1. xo4y_B_BostonDynamics Автор
      06.09.2019 11:04

      Я даже не знал про существование таких алгоритмов.

      Можно и так и так. Я делал эту работу в мае и уже не помню почему выбрал именно этот способ.


      1. 402d
        06.09.2019 12:48

        дизеринг / dithering
        www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code
        имхо лучшая страница на эту тему.

        но ой и ах для малого числа точек в линии (384) и 203 dpi результат на троечку.


  1. IronHead
    06.09.2019 14:36

    Нужен дизеринг habr.com/ru/post/326936, с ним изображения приятнее.
    У нас получалось так
    image
    Лента узкая 54мм


    1. 402d
      06.09.2019 15:23

      по флойду будет так image

      белые полосы по середине — убитая термоголовка за полтора года