<<
>>

Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея

//--------------------------------------------------------------------------

#ifndef CofAC unitH

#define CofAC_unitH

#include

#include

#include

#include

#include

#include

#include

//--------------------------------------------------------------------------

// Структура 4-байтного пикселя

union TPixel

{

unsigned int pixel4byte;

struct

{

BYTE low;

BYTE middle;

BYTE high;

BYTE sign;

} part;

};

// Тип-множество (состоит из возможных показаний сегментного индикатора) enum TIndicatorSet {ind0, ind1, ind2, ind3, ind4, ind5, ind6, ind7, ind8, ind9,

empty, degree, minus};

//--------------------------------------------------------------------------

class TfmMain : public TForm

{

__published: // IDE-managed Components

TImage *imInputImage;

TGroupBox *gbInputInfo;

TEdit *edInputFile;

TLabel *Label1;

TLabel *Label2;

TButton *bbLoad;

TGroupBox *gbOutput;

TSpeedButton *SpeedButton1;

TOpenDialog *OpenDialog;

TPanel *Panel1;

TLabel *Label3;

TLabel *lbMode;

TPanel *Panel2;

TLabel *Label5;

TLabel *lbResults;

TGroupBox *gbControl;

TBitBtn *bbRunControl;

TBitBtn *bbStopControl;

TRadioButton *rbSpeed;

TRadioButton *rbPetrol;

TRadioButton *rbTemperature;

TRadioButton *rbTemperature2;

TLabel *Label4;

TLabel *lbControlStatus;

void __fastcall SpeedButton1Click(TObject *Sender);

void __fastcall bbLoadClick(TObject *Sender);

void __fastcall edInputFileKeyPress(TObject *Sender, char &Key);

void __fastcall bbRunControlClick(TObject *Sender);

void __fastcall bbStopControlClick(TObject *Sender); private:

// none

public:

// Функция вывода сообщения об ошибке

void ShowErrorMessage(void);

// Функция определения наличия/отсутствия символа

bool IsSymbolDefined(BYTE *pObject, unsigned short size, unsigned short limit);

// Функция определения символа по шаблону из исходного множества шаблонов

TIndicatorSet DefineSymbol(BYTE *pObject);

// Функция интерполяции изображения методом билинейной интерполяции

void BilinearInterpolation(BYTE *pImage, BYTE *pFinalImage,

unsigned int oldWidth, unsigned int oldHeight,

unsigned int newWidth, unsigned int newHeight);

// Функция удаления лишних байтов из изображения

BYTE *ZipImage(Graphics::TBitmap *pImage, unsigned int HeightOfImage,

unsigned int WidthOfImage);

// Функция алгоритма распознавания картинки

void RecognitionAlgorithm(Graphics::TBitmap* pImage);

__fastcall TfmMain(TComponent* Owner);

__fastcall ~TfmMain();

};

//--------------------------------------------------------------------------

extern PACKAGE TfmMain *fmMain;

//--------------------------------------------------------------------------

#endif

Файл «CofAC_unit.cpp»

//--------------------------------------------------------------------------

#include

#pragma hdrstop

#include "CofAC unit.h"

#include

//--------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TfmMain *fmMain;

// Граничные числа черных пикселей для определения наличия/отсутствия символов

const limitLitre = 52; // all = 69

const limitPerHundred = 213; // all = 284

const limitPerHour = 105; // all = 140

const limitKilometre = 233; // all = 310

const limitAccum = 171; // all = 228

const limitPetrol = 244; // all = 325

const limitPoint2 = 8; // all = 12

const limitCar = 158; // all = 210

const limitPoint1 = 8; // all = 19

const limitPark = 136; // all = 181

const limitAlarm = 82; // all = 109

const limitClock = 106; // all = 141

// Размеры конечного изображения

const WIDTH_OF_FINAL_IMAGE = 256;

const HEIGHT_OF_FINAL_IMAGE = 91;

const SIZE_OF_FINAL_IMAGE = WIDTH_OF_FINAL_IMAGE * HEIGHT_OF_FINAL_IMAGE;

// Размеры области распознавания для сегментных индикаторов const WIDTH_OF_INDICATOR = 48;

const HEIGHT_OF_INDICATOR = 61;

// Размеры исходного изображения

unsigned int WidthOfImage;

unsigned int HeightOfImage;

// Контейнеры для изображения

Graphics::TBitmap *pImage;

BYTE *Image;

BYTE *FinalImage;

// Контейнеры для шаблонов

Graphics::TBitmap *pTemplate;

BYTE *Ind0; // Цифра "0"

BYTE *Ind1; // Цифра "1"

BYTE *Ind2; // Цифра "2"

BYTE *Ind3; // Цифра "3"

BYTE *Ind4; // Цифра "4"

BYTE *Ind5; // Цифра "5"

BYTE *Ind6; // Цифра "6"

BYTE *Ind7; // Цифра "7"

BYTE *Ind8; // Цифра "8"

BYTE *Ind9; // Цифра "9"

BYTE *IndDegree; // Символ градуса

BYTE *IndMinus; // Символ минуса

BYTE *IndEmpty; // Пусто

// Идентификаторы потоков xxxControlThread

DWORD dwSpeedControlThreadId;

DWORD dwTemperatureControlThreadId;

// Дескрипторы потоков xxxControlThread

HANDLE hSpeedControlThread = NULL;

HANDLE hTemperatureControlThread = NULL;

// Прототипы функций потоков

DWORD WINAPI SpeedControlThread(LPVOID lpParam);

DWORD WINAPI TemperatureControlThread(LPVOID lpParam);

// Параметры потоков

DWORD dwSpeedCtrlThrdParam;

DWORD dwTempCtrlThrdParam;

// Переменная, определяющая режим формирования управляющих сигналов /*unsigned char stateControlSignal; */

//--------------------------------------------------------------------------

__fastcall TfmMain::TfmMain(TComponent* Owner)

: TForm(Owner)

{

// Загрузка шаблонов для распознавания показаний сегментных индикаторов pTemplate = new Graphics::TBitmap();

pTemplate->LoadFromFile("Pictures\\Templates\\0.bmp"); // Цифра "0"

Ind0 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\1.bmp"); // Цифра "1"

Ind1 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\2.bmp"); // Цифра "2"

Ind2 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\3.bmp"); // Цифра "3"

Ind3 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\4.bmp"); // Цифра "4"

Ind4 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\5.bmp"); // Цифра "5"

Ind5 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\6.bmp"); // Цифра "6"

Ind6 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\7.bmp"); // Цифра "7"

Ind7 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\8.bmp"); // Цифра "8"

Ind8 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\9.bmp"); // Цифра "9"

Ind9 = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width);

pTemplate->LoadFromFile("Pictures\\Templates\\degree.bmp"); // Символ градуса

IndDegree = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\minus.bmp"); // Символ минуса

IndMinus = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); pTemplate->LoadFromFile("Pictures\\Templates\\empty.bmp"); // Empty IndEmpty = ZipImage(pTemplate, pTemplate->Height, pTemplate->Width); delete pTemplate; pTemplate = NULL;

}

//--------------------------------------------------------------------------

// Деструктор формы --------------------------------------------------------

_ fastcall TfmMain::~TfmMain()

{

// Освобождение памяти из-под контейнеров для шаблонов

delete []Ind0; Ind0 = NULL;

delete []Ind1; Ind1 = NULL;

delete []Ind2; Ind2 = NULL;

delete []Ind3; Ind3 = NULL;

delete []Ind4; Ind4 = NULL;

delete []Ind5; Ind5 = NULL;

delete []Ind6; Ind6 = NULL;

delete []Ind7; Ind7 = NULL;

delete []Ind8; Ind8 = NULL;

delete []Ind9; Ind9 = NULL;

delete []IndDegree; IndDegree = NULL;

delete []IndMinus; IndMinus = NULL;

delete []IndEmpty; IndEmpty = NULL;

// Завершение потоков

CloseHandle(hSpeedControlThread); CloseHandle(hTemperatureControlThread);

}

//--------------------------------------------------------------------------

// Функции работы с портами ------------------------------------------------

// Функция ввода байта информации из порта

BYTE inportb(UINT portid)

{

unsigned char value;

_asm

mov edx,portid

in al,dx

mov value,al

}

return value;

}

// Функция вывода байта информации в порт

void outportb(UINT portid, BYTE value)

{

_asm

mov edx,portid

mov al,value

out dx,al

}

}

//--------------------------------------------------------------------------

// Функция потока формирования управляющих воздействий ---------------------

DWORD WINAPI SpeedControlThread(LPVOID lpParam)

{

// Вывод в порт LPT1 импульсного сигнала

for (;;)

{

outportb(0x378, 0x01);

Sleep(3);

outportb(0x378, 0x00);

Sleep(3);

}

}

//--------------------------------------------------------------------------

// Функция потока формирования управляющих воздействий ---------------------

DWORD WINAPI TemperatureControlThread(LPVOID lpParam)

{

// Вывод в порт LPT1 сигнала постоянного напряжения

_asm

Ї

mov edx,0x378

mov al, 0x03

@out: out dx,al

jmp @out

}

}

//--------------------------------------------------------------------------

// Функция выбора файла картинки

void __fastcall TfmMain::SpeedButton1Click(TObject *Sender)

Ї

if (OpenDialog->Execute())

{

// Выведем полный путь к файлу картинки

edInputFile->Text = OpenDialog->FileName;

// Загрузим картинку

bbLoad->Enabled = true;

bbLoadClick(Sender);

}

}

//--------------------------------------------------------------------------

// Функция отображения картинки на экране и запуска процесса распознавания void fastcall TfmMain::bbLoadClick(TObject *Sender)

Ї

// Подготовка к работе

lbMode->Caption = "";

lbResults->Caption = "";

lbMode->Font->Color = clNavy;

lbResults->Font->Color = clNavy;

// Отобразим картинку на экране, если она соответствует формату 1 бит/пиксель

pImage = new Graphics::TBitmap(); pImage->LoadFromFile(edInputFile->Text);

if (pImage->PixelFormat != pf1bit)

{

MessageBox(Handle, "Исходный файл имеет недопустимый формат", "Ошибка!", MB_OK | MB_ICONSTOP | MB_APPLMODAL);

delete pImage; pImage = NULL;

return;

}

imInputImage->Picture->LoadFromFile(edInputFile->Text);

// Рассчитаем размеры исходной картинки

WidthOfImage = pImage->Width;

HeightOfImage = pImage->Height;

// Запустим процесс распознавания

RecognitionAlgorithm(pImage);

}

//--------------------------------------------------------------------------

// Функция удаления лишних байтов из изображения

/* На входе: копия указателя на исходную картинку, высота и ширина изображения

На выходе: копия указателя на конечный контейнер

*/

BYTE *TfmMain::ZipImage(Graphics::TBitmap *pImage,

unsigned int HeightOfImage, unsigned int WidthOfImage)

Ї

Image = new BYTE [HeightOfImage * WidthOfImage]; // Выделение памяти

// Заполнение контейнера

TPixel pixel = Ї0};

unsigned int index = 0;

for (unsigned int y = 0; y < HeightOfImage; y++)

for (unsigned int x = 0; x < WidthOfImage; x++, index++)

{

pixel.pixel4byte = (unsigned int)pImage->Canvas->Pixels[x][y]; Image[index] = pixel.part.low; // младший байт

}

return Image;

}

//--------------------------------------------------------------------------

// Функция интерполяции изображения методом билинейной интерполяции void TfmMain::BilinearInterpolation(BYTE *pImage, BYTE *pFinalImage,

unsigned int oldWidth, unsigned int oldHeight,

unsigned int newWidth, unsigned int newHeight)

Ї

unsigned int i, j; // Индексные переменные

int y, x; // Новые значения пикселей

double dy, dx; // Отклонения от старых значений пикселей

double tmp;

for (j = 0; j oldWidth-2)

x = oldWidth-2;

dx = tmp - x;

pFinalImage[i+j*newWidth] = (1-dx)*(1-dy)*pImage[x+y*oldWidth]+ dx*(1-dy)*pImage[(x+1)+y*oldWidth]+ (1-dx)*dy*pImage[x+(y+1)*oldWidth]+ dx*dy*pImage[(x+1)+(y+1)*oldWidth];

}

}

//--------------------------------------------------------------------------

// Функция определения символа по шаблону из исходного множества шаблонов // На входе: область распознавания в виде копии указателя на массив байтов // На выходе: значение типа TIndicatorSet для идентификации символа TIndicatorSet TfmMain::DefineSymbol(BYTE *pObject)

{

// Массив с результатами сравнения (число отличающихся пикселей) unsigned short numberOfNotEqualPixels[13] = {0};

// 1.

Сравнить попиксельно область с каждым шаблоном и запомнить результат в

// массиве numberOfNotEqualPixels

for (unsigned short i = 0; i < WIDTH_OF_INDICATOR * HEIGHT_OF_INDICATOR; i++)

{

if (pObject[i] != Ind0[i]) numberOfNotEqualPixels[0]++;

if (pObject[i] != Ind1[i]) numberOfNotEqualPixels[1]++;

if (pObject[i] != Ind2[i]) numberOfNotEqualPixels[2]++;

if (pObject[i] != Ind3[i]) numberOfNotEqualPixels[3]++;

if (pObject[i] != Ind4[i]) numberOfNotEqualPixels[4]++;

if (pObject[i] != Ind5[i]) numberOfNotEqualPixels[5]++;

if (pObject[i] != Ind6[i]) numberOfNotEqualPixels[6]++;

if (pObject[i] != Ind7[i]) numberOfNotEqualPixels[7]++;

if (pObject[i] != Ind8[i]) numberOfNotEqualPixels[8]++;

if (pObject[i] != Ind9[i]) numberOfNotEqualPixels[9]++;

if (pObject[i] != IndDegree[i]) numberOfNotEqualPixels[10]++;

if (pObject[i] != IndMinus[i]) numberOfNotEqualPixels[11]++;

if (pObject[i] != IndEmpty[i]) numberOfNotEqualPixels[12]++;

}

// 2.

Найти максимально схожий шаблон

unsigned char index = 0;

for (unsigned short min = numberOfNotEqualPixels[0], i = 1; i < 13; i++)

if (numberOfNotEqualPixels[i] < min)

{

min = numberOfNotEqualPixels[i];

index = i;

}

// 3. Определить его

switch (index)

{

case 0: return ind0; break;

case 1: return ind1; break;

case 2: return ind2; break;

case 3: return ind3; break;

case 4: return ind4; break;

case 5: return ind5; break;

case 6: return ind6; break;

case 7: return ind7; break;

case 8: return ind8; break;

case 9: return ind9; break;

case 10: return degree; break;

case 11: return minus; break;

default: return empty; break;

}

}

//--------------------------------------------------------------------------

// Функция определения наличия/отсутствия символа

// На входе: область распознавания в виде копии указателя на массив байтов,

// размер области в байтах, граничное число черных пикселей

// На выходе: логическое значение: присутствует/не присутствует

bool TfmMain::IsSymbolDefined(BYTE *pObject, unsigned short size, unsigned short limit)

Ї

short blackPixels = 0; // Число черных пикселей

for (unsigned short i = 0; i limit)

return true;

else

return false;

}

//--------------------------------------------------------------------------

// Функция вывода сообщения об ошибке

void TfmMain::ShowErrorMessage(void) Ї

lbMode->Font->Color = clRed; lbMode->Caption = "Неверный режим"; lbResults->Font->Color = clRed;

lbResults->Caption = "Ошибка в показаниях!";

delete []FinalImage; FinalImage = NULL; // Освободить память

}

//--------------------------------------------------------------------------

// Функция алгоритма распознавания картинки

// На входе: копия указателя на исходную картинку

void TfmMain::RecognitionAlgorithm(Graphics::TBitmap* pImage) Ї

// 1. Приведение исходной картинки к виду 1байт/пиксель

Image = ZipImage(pImage, HeightOfImage, WidthOfImage); delete pImage; pImage = NULL; // Освободить память

// 2.

Интерполяция картинки (изменение размеров на 256х91 пикселей) FinalImage = new BYTE [SIZE_OF_FINAL_IMAGE];

BilinearInterpolation(Image, FinalImage, WidthOfImage, HeightOfImage, WIDTH_OF_FINAL_IMAGE, HEIGHT_OF_FINAL_IMAGE);

delete []Image; Image = NULL; // Освободить память

// 3. Бинаризация

for (unsigned short i = 0; i < SIZE_OF_FINAL_IMAGE; i++)

if (FinalImage[i] < 0x7F)

FinalImage[i] = 0;

else

FinalImage[i] = 0xFF;

// 4. Распознавание индикаторов

// Переменные для значений индикаторов

TIndicatorSet Indicator[4];

unsigned short dx, dy; // Смещение области распознавания по осям 0x и 0y

// Определение значения первого индикатора

BYTE *Object = new BYTE [WIDTH_OF_INDICATOR * HEIGHT_OF_INDICATOR];

for (unsigned char j = 0; j < HEIGHT_OF_INDICATOR; j++)

for (unsigned char i = 0; i < WIDTH_OF_INDICATOR; i++)

{

dx = 5; dy = 0;

Object[i+j*WIDTH_OF_INDICATOR] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Indicator[0] = DefineSymbol(Object);

// Определение значения второго индикатора

for (unsigned char j = 0; j < HEIGHT_OF_INDICATOR; j++)

for (unsigned char i = 0; i < WIDTH_OF_INDICATOR; i++) {

dx = 53; dy = 0;

Object[i+j*WIDTH_OF_INDICATOR] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Indicator[1] = DefineSymbol(Object);

// Определение значения третьего индикатора

for (unsigned char j = 0; j < HEIGHT_OF_INDICATOR; j++) for (unsigned char i = 0; i < WIDTH_OF_INDICATOR; i++) {

dx = 101; dy = 0;

Object[i+j*WIDTH_OF_INDICATOR] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Indicator[2] = DefineSymbol(Object);

// Определение значения четвертого индикатора

for (unsigned char j = 0; j < HEIGHT_OF_INDICATOR; j++) for (unsigned char i = 0; i < WIDTH_OF_INDICATOR; i++) {

dx = 149; dy = 0;

Object[i+j*WIDTH_OF_INDICATOR] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Indicator[3] = DefineSymbol(Object); delete []Object; Object = NULL;

// Логические переменные для определения наличия на дисплее других индикаторов

bool Litre(false); // Знак "литры"

bool perHundred(false); // Знак "/100"

bool perHour(false); // Знак "/Н"

bool Kilometre(false); // Знак "километры"

bool Accum(false); // Знак аккумулятора

bool Petrol(false); // Знак заправки

bool Point2(false); // Правая позиция точки

bool Car(false); // Знак автомобиля

bool Point1(false); // Левая позиция точки

bool Park(false); // Знак парковки

bool Alarm(false); // Знак колокольчика

bool Clock(false); // Знак часов

unsigned short w, h; // Ширина и высота области распознавания

// Знак "литры"

w = 13; h = 20;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 201; dy = 9;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Litre = IsSymbolDefined(Object, w*h, limitLitre);

delete []Object; Object = NULL;

// Знак "/100"

w = 40; h = 21;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 214; dy = 9;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

perHundred = IsSymbolDefined(Object, w*h, limitPerHundred); delete []Object; Object = NULL;

// Знак "/Н"

w = 24; h = 27;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 226; dy = 33;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

perHour = IsSymbolDefined(Object, w*h, limitPerHour);

delete []Object; Object = NULL;

// Знак "километры"

w = 33; h = 27;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 193; dy = 33;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Kilometre = IsSymbolDefined(Object, w*h, limitKilometre); delete []Object; Object = NULL;

// Знак аккумулятора

w = 53; h = 25;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 203; dy = 66;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Accum = IsSymbolDefined(Object, w*h, limitAccum);

delete []Object; Object = NULL;

// Знак заправки

w = 52; h = 28;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 140; dy = 61;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Petrol = IsSymbolDefined(Object, w*h, limitPetrol);

delete []Object; Object = NULL;

// Правая позиция точки

w = 10; h = 10;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

{

dx = 141; dy = 48;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE];

}

Point2 = IsSymbolDefined(Object, w*h, limitPoint2); delete []Object; Object = NULL;

// Знак автомобиля

w = 29; h = 26;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

Ї

dx = 113; dy = 63;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Car = IsSymbolDefined(Object, w*h, limitCar); delete []Object; Object = NULL;

// Левая позиция точки

w = 10; h = 10;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

Ї

dx = 93; dy = 48;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Point1 = IsSymbolDefined(Object, w*h, limitPoint1); delete []Object; Object = NULL;

// Знак парковки

w = 52; h = 26;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

Ї

dx = 61; dy = 63;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Park = IsSymbolDefined(Object, w*h, limitPark); delete []Object; Object = NULL;

// Знак колокольчика

w = 18; h = 23;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

Ї

dx = 37; dy = 63;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Alarm = IsSymbolDefined(Object, w*h, limitAlarm); delete []Object; Object = NULL;

// Знак часов

w = 23; h = 25;

Object = new BYTE [w*h];

for (unsigned short j = 0; j < h; j++)

for (unsigned short i = 0; i < w; i++)

Ї

dx = 8; dy = 63;

Object[i+j*w] = FinalImage[(i+dx)+(j+dy)*WIDTH_OF_FINAL_IMAGE]; }

Clock = IsSymbolDefined(Object, w*h, limitClock); delete []Object; Object = NULL;

// 5.

Интерпретация результатов и отображение на экране ,

// Перевод значений индикаторов в цифровую форму char intIndicator[4];

for (unsigned char i = 0; i < 4; i++)

switch (Indicator[i])

{

case ind0: intIndicator[i] = 0; break;

case ind1: intIndicator[i] = 1; break;

case ind2: intIndicator[i] = 2; break;

case ind3: intIndicator[i] = 3; break;

case ind4: intIndicator[i] = 4; break;

case ind5: intIndicator[i] = 5; break;

case ind6: intIndicator[i] = 6; break;

case ind7: intIndicator[i] = 7; break;

case ind8: intIndicator[i] = 8; break;

case ind9: intIndicator[i] = 9; break;

case empty: intIndicator[i] = -1; break;

default: break;

}

// Определение режима работы

if (Clock &&Park &&Car) // Время поездки без учета остановок

{

lbMode->Caption = "Время поездки без учета остановок";

if (Point1)

{

unsigned char minHour(0), secMin(0);

if (intIndicator[1] >= 0) minHour = intIndicator[1];

else {

ShowErrorMessage(); return;

}

if (intIndicator[0] >= 0) minHour += 10*intIndicator[0];

else {

ShowErrorMessage(); return;

}

if (intIndicator[3] >= 0) secMin = intIndicator[3];

else {

ShowErrorMessage(); return;

}

if (intIndicator[2] >= 0) secMin += 10*intIndicator[2];

else {

ShowErrorMessage(); return;

}

if (intIndicator[0] Caption = IntToStr(minHour) + " мин (ч), "+

IntToStr(secMin) + " сек (мин)";

}

if (intIndicator[0] >= 6) // ч/мин

{

lbResults->Caption = IntToStr(minHour) + " ч, " +

IntToStr(secMin) + " мин";

}

}

else if (Point2)

{

unsigned short hour(0); unsigned char tenMinuts(0);

if ((intIndicator[0] < 1) || (intIndicator[3] > 5)) {

ShowErrorMessage(); return;

}

if (intIndicator[2] >= 0) hour = intIndicator[2];

else {

ShowErrorMessage(); return;

}

if (intIndicator[1] >= 0) hour += 10*intIndicator[1]; else Ї

ShowErrorMessage(); return;

}

hour += 100*intIndicator[0];

if (intIndicator[3] >= 0) tenMinuts = intIndicator[3]; else Ї

ShowErrorMessage(); return;

}

lbResults->Caption = IntToStr(hour) + " ч, " +

IntToStr(tenMinuts) + "0 мин"; // ч/10 мин

}

}

else if (Clock &&Park) // Общее время поездки

{

lbMode->Caption = "Общее время поездки";

if (Point1)

{

unsigned char minHour(0), secMin(0);

if (intIndicator[1] >= 0) minHour = intIndicator[1]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[0] >= 0) minHour += 10*intIndicator[0]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[3] >= 0) secMin = intIndicator[3]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[2] >= 0) secMin += 10*intIndicator[2]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[0] Caption = IntToStr(minHour) + " мин (ч), "+

IntToStr(secMin) + " сек (мин)";

}

if (intIndicator[0] >= 6) // ч/мин

{

lbResults->Caption = IntToStr(minHour) + " ч, "+

IntToStr(secMin) + " мин";

}

}

else if (Point2)

{

unsigned short hour(0); unsigned char tenMinuts(0);

if ((intIndicator[0] < 1) || (intIndicator[3] > 5)) Ї

ShowErrorMessage(); return;

}

if (intIndicator[2] >= 0) hour = intIndicator[2]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[1] >= 0) hour += 10*intIndicator[1]; else Ї

ShowErrorMessage(); return;

}

hour += 100*intIndicator[0];

if (intIndicator[3] >= 0) tenMinuts = intIndicator[3]; else Ї

ShowErrorMessage(); return;

}

lbResults->Caption = IntToStr(hour) + " ч, " +

IntToStr(tenMinuts) + "0 мин"; // ч/10 мин

}

}

else if (Indicator[3] == degree) // Температура за бортом

Ї

lbMode->Caption = "Температура за бортом";

char temperature;

if (intIndicator[2] >= 0) temperature = intIndicator[2]; else Ї

ShowErrorMessage(); return;

}

if (intIndicator[1] > 0) temperature += 10*intIndicator[1];

if (Indicator[0] == minus) temperature = -temperature;

else if (Indicator[0] != empty) {

ShowErrorMessage(); return;

}

lbResults->Caption = IntToStr(temperature) + " градусов";

}

else if (Park && Car && Kilometre && perHour && Point2) Ї

// Средняя скорость поездки

lbMode->Caption = "Средняя скорость поездки";

float averSpeed(0);

if ((intIndicator[2] < 0) || (intIndicator[3] < 0)) Ї

ShowErrorMessage(); return;

}

averSpeed = intIndicator[2] + 0.1*intIndicator[3];

if (intIndicator[1] >= 0)

averSpeed += 10*intIndicator[1];

if (intIndicator[0] >= 0)

averSpeed += 100*intIndicator[0];

lbResults->Caption = FloatToStrF(averSpeed, ffFixed, 3, 1) + "км/ч";

}

else if (Alarm && Car && Kilometre && perHour)

Ї

// Мгновенная скорость

lbMode->Caption = "Мгновенная скорость";

unsigned short currentSpeed(0);

if (intIndicator[3] < 0) Ї

ShowErrorMessage(); return;

}

currentSpeed = intIndicator[3];

if (intIndicator[2] >= 0)

currentSpeed += 10*intIndicator[2];

if (intIndicator[1] >= 0)

currentSpeed += 100*intIndicator[1];

lbResults->Caption = IntToStr(currentSpeed) + "км/ч";

}

else if (Alarm && Accum && Point2) // Напряжение бортовой сети

Ї

lbMode->Caption = "Напряжение бортовой сети";

float voltage(0);

if ((intIndicator[2] < 0) || (intIndicator[3] < 0)) Ї

ShowErrorMessage(); return;

}

voltage = intIndicator[2] + 0.1*intIndicator[3];

if (intIndicator[1] >= 0)

voltage += 10*intIndicator[1];

lbResults->Caption = FloatToStrF(voltage, ffFixed, 2, 1) + "В";

}

/* Доп.

режимы функционирования */

delete []FinalImage; FinalImage = NULL; // Освободить память

}

//--------------------------------------------------------------------------

// Для удобства работы

void fastcall TfmMain::edInputFileKeyPress(TObject *Sender, char &Key) Ї

if (Key == 13)

bbLoadClick(Sender);

}

//--------------------------------------------------------------------------

// Функция запуска управляющего воздействия void __fastcall TfmMain::bbRunControlClick(TObject *Sender)

Ї

// Проверить вид управляющего сигнала

if (rbSpeed->Checked)

{

// Создать доп. поток, если еще не создан

dwSpeedCtrlThrdParam = 3;

if (hSpeedControlThread == NULL)

{

hSpeedControlThread = CreateThread(NULL, 0, SpeedControlThread, &dwSpeedCtrlThrdParam,

0, &dwSpeedControlThreadId);

if (hSpeedControlThread == NULL)

{

MessageBox(NULL, "Невозможно формирование управляющих воздействий", "Ошибка", MB_OK);

return;

} SetThreadPriority(hSpeedControlThread, THREAD_PRIORITY_BELOW_NORMAL);

}

else ResumeThread(hSpeedControlThread); // Возобновление работы

потока

}

if (rbTemperature->Checked)

{

// Создать доп. поток, если еще не создан

dwTempCtrlThrdParam = 3;

if (hTemperatureControlThread == NULL)

{ hTemperatureControlThread = CreateThread(NULL, 0, TemperatureControlThread,

&dwTempCtrlThrdParam, 0, &dwTemperatureControlThreadId);

if (hTemperatureControlThread == NULL)

{

MessageBox(NULL, "Невозможно формирование управляющих воздействий", "Ошибка", MB_OK);

return;

} SetThreadPriority(hTemperatureControlThread,

THREAD_PRIORITY_BELOW_NORMAL);

}

else

ResumeThread(hTemperatureControlThread); // Возобновление работы потока

}

/* Доп. режимы управляющих воздействий */

// Отображение смены состояний

rbSpeed->Enabled = false;

rbPetrol->Enabled = false;

rbTemperature->Enabled = false;

rbTemperature2->Enabled = false;

bbRunControl->Enabled = false;

bbStopControl->Enabled = true;

lbControlStatus->Caption = "Включено";

}

//--------------------------------------------------------------------------

// Функция прекращения управляющего воздействия

void __fastcall TfmMain::bbStopControlClick(TObject *Sender)

{

// Определение прекращаемого воздействия

if (rbSpeed->Checked)

SuspendThread(hSpeedControlThread);

if (rbTemperature->Checked)

SuspendThread(hTemperatureControlThread);

// Отображение смены состояний

rbSpeed->Enabled = true;

rbPetrol->Enabled = true;

rbTemperature->Enabled = true;

rbTemperature2->Enabled = true;

bbRunControl->Enabled = true;

bbStopControl->Enabled = false;

lbControlStatus->Caption = "Выключено";

}

148

<< | >>
Источник: Лысенко Ян Александрович. МОДЕЛЬ, МЕТОД И ОПТИКО-ЭЛЕКТРОННОЕ УСТРОЙСТВО ПАРАЛЛЕЛЬНОЙ ОБРАБОТКИ ИЗОБРАЖЕНИЙ ИНДИКАТОРОВ ПАНЕЛИ ПРИБОРОВ. Диссертация на соискание ученой степени кандидата технических наук. Курск - 2019. 2019

Скачать оригинал источника

Еще по теме Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея:

  1. Содержание
  2. Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея