Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея
//--------------------------------------------------------------------------
#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
Еще по теме Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея:
- Содержание
- Приложение В. Текст моделирующей программы определения показаний жидкокристаллического дисплея