Класс Filters.
Класс Filters реализует хранение и расчет данных для фильтрации ЭКГ.
class Filters
{
public:
char Name[10];// названиефильтра
double * Coeficients;//коэффициенты фильтра с плавающей точкой
short * QuantizCoeficients;//целочисленные коэффициенты
BYTE NumCoef;// число коэфициентов
//конструктор
Filters(char * FilterName,BYTE NumCoeficientsdouble,double * Coef = NULL,double * Quant = NULL);
// функциярасчетаКИХфильтров
void GetType_1(short * InBuffer,short * OutBuffer);
// функциярассчетаБИХфильтров
void GetType_2(short * Inbuffer,short * Outbuffer);
// функция рассчета фильтров с приведением
// к целочисленным коэфициентам
void GetQType(short * Inbuffer,short * Outbuffer,BOOL Type,BYTE PreCoef = 0);
~Filters();// деструктор
};
В конструкторе происходит инициализация названия фильтра, числа коэффициентов, самих коэффициентов в зависимости от типа фильтра.
Предварительная обработка сигнала в электрокардиографии заключается, в основном, в цифровой фильтрации сигнала и его усреднении. Цель фильтрации – подавление неблагоприятных факторов, таких как шумы, выделение определенных характеристик сигнала и его коррекция. Наиболее простой в реализации и достаточно эффективной является линейная инвариантная к сдвигу фильтрация. С точки зрения реализации (впрочем, это является общепринятым в теории ЦОС ) разумно разделить линейные цифровые фильтры на 2 типа: фильтры с конечной импульсной характеристикой (КИХ) и фильтры с бесконечной импульсной характеристикой (БИХ). По-другому они называются нерекурсивный и рекурсивный соответственно.
Фильтры с конечным импульсным откликом описываются следующим уравнением:
Соответственно, передаточная функция таких фильтров выглядит следующим образом:
Передаточная функция не имеет полюсов, следовательно, фильтр всегда устойчив, более того, если ряд коэффициентов симметричен, то фильтр имеет линейную ФЧХ. КИХ - фильтры обычно реализуются в такой же форме, как и определяются, т.е. в виде суммы.
Фильтры с бесконечным импульсным откликом описываются следующим выражением:
Передаточная функция имеет вид:
Существует достаточно много типов БИХ фильтров, классифицируемых прежде всего по форме передаточной характеристики: Баттерворта, Чебышева, эллиптический.
Цифровые фильтры обычно проектируются в соответствии с определенными требованиями, предъявляемыми обычно к передаточной функции, которая, естественно, определяется конкретной задачей, для которой разрабатываемый фильтр и предназначен. Идеальные фильтры не реализуемы, поэтому приходится говорить лишь о соответствии фильтра параметрам в рамках допустимой ошибки. Для расчета цифровых фильтров существует несколько методик, требующих различных вычислительных возможностей. В электрокардиографии обычно применяют фильтры какого – либо одного типа и для определенной частоты среза и частоты дискретизации. Поэтому расчет фильтра в реальном времени проводить обычно не требуется, а коэффициенты рассчитываются при помощи какого – либо пакета, позволяющего сделать это визуально и интерактивно (в данном дипломном проекте расчеты проводились в среде Matlab v.6.0).
Функции КИХ и БИХ фильтрации:
//ФункцияКИХфильтрации
void Filters::GetType_1(short * InBuffer,short * OutBuffer)
{
WORD i = 0;
double Temp = 0;
while(i<8000)
{
if(i<NumCoef) OutBuffer[i] = InBuffer[i];
else
{
for(BYTE j = 0;j<NumCoef;j++)
Temp += InBuffer[i-j]*Coeficients[j];
OutBuffer[i] = (short)Temp;
}
Temp = 0.0;
i++;
}
}
//ФункцияБИХфильтрации
void Filters::GetType_2(short * Inbuffer,short * Outbuffer)
{
WORD i = 0;
double Temp = 0;
while(i<8000)
{
if(i<(NumCoef/2 - 1)) Outbuffer[i] = Inbuffer[i];
else
{
for(BYTE j = 0;j<(NumCoef/2);j++)
Temp += (Inbuffer[i-j]*Coeficients[j]
- Outbuffer[i-j]*Coeficients[j+NumCoef/2]);
Outbuffer[i] = (short)Temp;
}
Temp = 0;
i++;
}
}
Если тип фильтра – БИХ, тогда коэффициенты обратной связи ак в конструкторе нужно передавать сразу за коэффициентами bm.
В связи с тем, что последующая реализация тестируемых фильтров будет производиться на микроконтроллере Siemence без реализации арифметики с плавающей точкой, необходимо реализовать фильтрацию с целочисленными коэффициентами. Реализация целочисленных коэффициентов производится в функции GetQType. В конструктор передаются коэффициенты с плавающей точкой, рассчитанные в среде Matlab при условиях квантизации, которые при перемножении на число два в пятнадцатой степени дают целочисленные коэффициенты. Соответственно после фильтрации все точки ЭКГ масштабируются к исходным значениям.
//Функция фильтрации с целочисленными коэффициентами
void Filters::GetQType(short * Inbuffer,short * Outbuffer,BOOL Type,BYTE PreCoef)
{
WORD i = 0;
int Temp = 0;
while(i<8000)
{
if(i<(NumCoef/2 - 1)) Outbuffer[i] = Inbuffer[i];
else
{
for(BYTE j = 0;j<(NumCoef/2);j++)
if(Type == FALSE)
Temp += (int)(Inbuffer[i-j]*(short)QuantizCoeficients[j]);
else
Temp += (Inbuffer[i-j]*QuantizCoeficients[j]
-Outbuffer[i-j]*QuantizCoeficients[j+NumCoef/2]);
if(Temp>0)
Outbuffer[i] = (short)( Temp >> (15+PreCoef) );
else
Outbuffer[i] = -(short)( (-Temp) >> (15+PreCoef) );
}
Temp = 0;
i++;
}
}
Первый параметр функции – входной массив графика, второй параметр – массив в который будут передаваться отфильтрованные значения, третий параметр – тип фильтра (БИХ или КИХ), четвертый параметр – коэффициент масштабирования отфильтрованных значений выходного массива.
Реализация таймера.
При успешной загрузке данных из файла устанавливается системный таймер с временем срабатывания (в миллисекундах), равным 2. Таймеры являются лимитированным глобальным ресурсом системы, поэтому следует проверять код, возвращаемый функцией SetTimer. После установки таймера каждые 2 миллисекунды система будет посылать в очередь сообщений нашего приложения сообщение WM_TIMER. Значение третьего параметра NULL говорит о том, что сообщение будет обрабатываться в оконном классе, а не в специально созданной глобальной функции, адрес которой следовало бы передать третьим параметром. При возникновении прерывания от таймера управление будет передано в функцию OnTimer.
void CNewvisualDlg::OnTimer(UINT nIDEvent)
{
if(Flag == true)
{
if(m_dlgPaint.NPoints == 500)
m_dlgPaint.NPoints = (m_dlgPaint.x2 - m_dlgPaint.x1);
else
{
m_dlgPaint.NPoints+=(m_dlgPaint.x2 - m_dlgPaint.x1);
m_dlgPaint.PointCounter+=(m_dlgPaint.x2 - m_dlgPaint.x1);
}
m_dlgPaint.rect.left = m_dlgPaint.x1-5;
m_dlgPaint.rect.right = m_dlgPaint.x1;
m_dlgPaint.rect.top = m_dlgPaint.y1;
m_dlgPaint.rect.bottom = m_dlgPaint.y2+10;
CRect rect2;rect2.CopyRect(&m_dlgPaint.rect);
rect2.SetRect(0,0,(m_dlgPaint.rect.right-1),
m_dlgPaint.rect.bottom);
m_dlgPaint.InvalidateRect(&rect2);
}
if(m_dlgPaint.rect.right >= m_dlgPaint.x2) Flag = true;
if(m_dlgPaint.Counter < m_dlgPaint.NPoints)
{
m_dlgPaint.Counter+=5;
m_dlgPaint.rect.left+=5;
m_dlgPaint.rect.right+=5;
Flag=false;
}
else Flag = true;
if(m_dlgPaint.NPoints>=8000)
{
Flag = true;
m_dlgPaint.NPoints= 500;
m_dlgPaint.Counter = 0;
m_dlgPaint.PointCounter = 0;
}
m_dlgPaint.InvalidateRect(&m_dlgPaint.rect);
CDialog::OnTimer(nIDEvent);
}
Реализация QRS детектора.
Интеграция в проект QRS детектора была осуществлена при помощи руководителя практики, заголовочный файл и файл реализации были подключены к проекту. Графическая реализация была целиком самостоятельной работой. Для отображения заметок определения QRS, в функцию, рисующую график добавляется параметр (массив из 8000 элементов)
//код заполнения массива для
//последующего отображения в окне просмотра
if(m_dlgPaint.StartOtv[0] == 0) return;
INT disp,amp;
memset(m_dlgPaint.DifFlag,0,8000);
for(i=0;i<8000;i++)
if(CalcPoint(m_dlgPaint.StartOtvFilt[i],&disp,&))
{
m_dlgPaint.DifFlag[i-disp] = 1;
}
Глава 4. Расчет затрат на создание программного продукта
Цель составления любых программ состоит в получении определенных результатов в процессе эксплуатации и оценивается эффективностью программного средства. Поводом для создания рассматриваемого пакета программ послужила необходимость обеспечения входного и межоперационного контроля над физическими параметрами полупроводниковых микросхем, а также повышения точности этого контроля на этапе исследования п/п пластины. Уточним применяемое далее понятие эффективности процесса разработки программного средства. Выбор адекватных показателей эффективности программных средств зависит от их назначения, области применения, а также от ряда характеристик программ, проявляющихся при их применении. Поэтому, для выбора технических решений могут использоваться различные критерии. Целесообразно подразумевать под эффективностью процесса разработки минимум затрат на разработку программ при заданной экономической эффективности применения и качества программных средств. Минимизация затрат на обеспечение жизненного цикла комплекта программ (далее КП) в некоторой степени эквивалентны максимизации разности эффекта и затрат, если предположить, что экономический эффект от применения программ зафиксирован и стабилен. Затраты в жизненном цикле ПО определяются не только этапом разработки, но и этапами эксплуатации и сопровождения, причем затраты на этих этапах могут значительно превосходить затраты на этапе проектирования и разработки и характеризуются своими особыми закономерностями. Обычно, критерии качества изделий используются в совокупности, с разных сторон отражающей основные характеристики функционирования объекта. Тем не менее, во многих случаях доминирует экономический эффект, который наиболее прост, и обобщенно принято описывать суммарным доходом Э от использования изделия в течение его жизненного цикла продолжительностью Тж. В первом приближении это разность между полной идеальной экономической эффективностью программы Эо и суммарными потерями и затратами K, снижающими предельный доход за весь жизненный цикл: