Merge branch 'master' of https://git.c68.spacecorp.ru/ivan-igorevich/bmstu-lectures
|
@ -0,0 +1,508 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\author{Алфимцев Александр Николаевич}
|
||||
\title{Цифровая обработка изображений в информационных системах}
|
||||
\date{2022-02-09}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
\usepackage{subfiles}
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{titlepage}
|
||||
\maketitle
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Введение}
|
||||
Изображения всё больше оцифровываются. Мультимодальность в изображениях заключается в том, что человек много дополняет зрительную информацию (80\%) образами из головы.
|
||||
|
||||
ЦОИ много применяется для медицины (последние годы особенно), полиграфии, оптического приборостроения. Мы будем использовать для распознавания образов. Главная математическая модель для ЦОИ - глубокие нейронные сети, глубокие свёрточные нейронные сети (джефри хилтон). ЦОИ это не только про распознавание, но и про фильтрации для получения дополнительной информации. Цои используется для кавтоматизации контроля производства (конвейерные линии)
|
||||
|
||||
\begin{itemize}
|
||||
\item 1980год Неокогнитрон
|
||||
\item 1990-1995-свёрточные нейросети
|
||||
\item 2012 DL революция в распознавании CNN
|
||||
\end{itemize}
|
||||
|
||||
Джеффри хинтон
|
||||
|
||||
\begin{itemize}
|
||||
\item ЦОИ = изображение - обработка - изображение
|
||||
\item Компьютерное зрение = изображение - обработка - число (вектор, свёртка). данные и алгоритмы.
|
||||
\item Машинное зрение - данные, алгоритмя, аппаратное обеспечение
|
||||
\end{itemize}
|
||||
|
||||
Актуальность ЦОИ:
|
||||
\begin{enumerate}
|
||||
\item изображение - главный источник информации
|
||||
\item средства получения изображений дёшевы и распространены
|
||||
\item последовательность изображений (видеопоток) - это биг дата
|
||||
\item ЦОИ математическими методами и моделями - это простая и понятная иллюстрация их работы
|
||||
\item автоматическая обработка цифровых изображений - самый выразительный пример развития искусственного интеллекта
|
||||
\item Курс ЦОИ – фундаментальная структура современного технологического мировоззрения.
|
||||
\end{enumerate}
|
||||
|
||||
Будем использовать Python, в начале стараемся не использовать OpenCV, хотя им можно закрыть весь курс.
|
||||
|
||||
Литература:
|
||||
\begin{enumerate}
|
||||
\item Gonzalez R., Woods R. Digital Image Processing (4th Edition). London: Pearson. 2018. 1019 p. ( Гонсалес Н., Вудс Р. Цифровая обработка изображений. Уч. пос. М.: Изд. “Техносфера”, 2012. 1104 с.)
|
||||
\item Шапиро Л., Стокман Д. Компьютерное зрение; Пер. с англ.-М.: БИНОМ. Лаборатория знаний, 2006. 752 с.
|
||||
\item Красильников Н. Н. Цифровая обработка 2D- и 3D-изображений : учеб. пособие для вузов / Красильников Н. Н. СПб. : БХВ-Петербург, 2011. 595 с.
|
||||
\item Duda, Hart. Pattern Classification, 2nd edition. Wiley Interscience. 2001.
|
||||
\item Пролетарский А.В., Алфимцев А.Н., Лычков И.И. Практикум по цифровой обработке изображений в компьютерных сетях. М.: МГТУ им. Н.Э. Баумана. 2016. 71 с.
|
||||
\item Laganière R. OpenCV 3 Computer Vision Application Programming Cookbook. 2017.
|
||||
\item Тарантино К. Цифровая фотография. Компьютерная обработка изображений. М.: Омега, 2005.- 142 с.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Вопросы, решаемые курсом}
|
||||
\begin{enumerate}
|
||||
\item понятие цои
|
||||
\item история цои
|
||||
\item области применения цои
|
||||
\item основные этапы цои
|
||||
\item введение в теорию вероятности
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Понятие}
|
||||
изображение - это двумерная функция f(x,y) где x и y это координаты в пространстве (на плоскости). Если величины x, y, f принимают дискретные значения, то изображение является цифровым (I[x,y]).
|
||||
|
||||
\textbf{Цифровой обработкой изображений} называется обработка цифровых изображений с помощью цифровых вычислительных машин. Первое цифровое изображение содержало боксёра, цифровое изображение, полученное с использованием перфоленты это портреь Фрейда. Первые цифровые обработки связаны с фотографиями луны в 1958 и 1964 годах, соответственно.
|
||||
|
||||
Области применения цои - слишком много, поэтому берём базовую идею. в бытовом смысле цои - это работа с видимым спектром. В промышленности (прикладная область цои) использует гораздо больший спектр электромагнитного излучения.
|
||||
\begin{itemize}
|
||||
\item гамма излучение - это медицинская радиология и космическая цои (остатки сверхновой, опухоли, боеголовка ядерной ракеты, рентгены, в том числе печатных плат).
|
||||
\item Ультрафиолет (снимки зёрен, звёзд).
|
||||
\item Инфракрасный диапазон (дистанционное зондирование, астрономия, световая микроскопия, промышленность, правоохранительная деятельность).
|
||||
\item Терагерцевое излучение - между инфракрасным и СВЧ диапазоном. Используется в безопасности, например, просвечивает одежду
|
||||
\item Микроволны. Радиолокация объектов
|
||||
\item Радиоволны (медицина, астрономия), отслеживание спектров излучений.
|
||||
\item Цифровые изображения могут быть получены сейсмически, ультразвуком, электронным микроскопом, фрактальные.
|
||||
\end{itemize}
|
||||
|
||||
База знаний курса, этапы ЦОИ
|
||||
\begin{enumerate}
|
||||
\item регистрация изображений;
|
||||
\item улучшение изображения (improvement) - обработка с целью повысить качество для человека.
|
||||
\item восстановление изображений (enhancement) - мат. Процедура которая основывается на модели шума.
|
||||
\item обработка цветных изображений;
|
||||
\item морфологическая обработка;
|
||||
\item сегментация изображения;
|
||||
\item описание изображения;
|
||||
\item распознавание образов
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Введение в теорию вероятности}
|
||||
Случайная величина (random variable) — это переменная, значения которой представляют собой исходы какого-нибудь случайного события (численное выражение результата случайного события). Вероятность (probability) — степень (относительная мера, количественная оценка) возможности наступления некоторого события.
|
||||
\section{Аудио у Вики}
|
||||
|
||||
\section{Пространственные методы улучшения изображений}
|
||||
пространственные методы - слева-направо-сверху-вниз
|
||||
частотные методы - через преобразование фурье превращается в набор коэффициентов. происходит переход и туда и обратно.
|
||||
|
||||
основные градационные преобразования - работа над чб. $g(x,y) = T[f(x,y)]$. логарифмические формы и обратные лог формы функции это преобразование яркости, либо затемнение (обратный) либо осветление (прямой). Фильтрация происходит в рамках границ.
|
||||
\begin{itemize}
|
||||
\item Преобразование в негатив $s = L - 1 - r$.
|
||||
\item логарифмическое преобразование $s = c\log(1+r)$
|
||||
\item степенные преобразования $s = cr^\gamma$. гамма-преобразование. положительная гамма затемняет, дробная осветляет.
|
||||
\item кусочно-линейные функции преобразования - вырезание диапазона яркостей, усиление контраста. широкие возможности, но есть проблема производительности. вырезание битовых плоскостей
|
||||
\end{itemize}
|
||||
видоизменение гистограммы - отличная визуализация для человека. Гистограмма - это дискретная функция $h(r_k)$. по оси абсцисс если яркость 0-255 где 0 чёрное, то по ординатам будет кол-во пикселей, имеющих такую яркость. гистограммы используют только те пиксели, которые есть в изображении, ничего не домысливая. приёмы:
|
||||
\begin{enumerate}
|
||||
\item Эквализация Г - похожа на нормализацию. формулы пытаются проверить, является ли функция яркости однозначной и монотонной.
|
||||
\item приведени гистограммы. не просто автоматически, а экспертно подбираем функцию. нужно чтобы специально обработать изображение.
|
||||
\item локальное улучшение - любое из предыдущих улучшений, применённое локально. обычно это квадрат или прямоугольник. используется когда глобальная обработка сильно зашумит итоговое изображени
|
||||
\item улучшение основанное на локальных статистиках. происходит сравнение локлаьного значения яркости с глобальным значением яркости, то есть если относительно ярче - делаем более ярким (улучшаем) по сигмаидальной функции отклонения
|
||||
\end{enumerate}
|
||||
арифметико-логические операции улучшения изображений - редкое применение в ЦОИ. поэлементно применяем к изображению. называется функционально-полный базис. операции используются для маскИрования изображения. с точки зрения задач улучшения делается для изолирования области. часто используются в морфологических операциях.
|
||||
\begin{itemize}
|
||||
\item Вычитание изображений - простейший алгоритм для обнаружения движения.
|
||||
\item Усреднение изображения - сложение. используется для улучшения путём избавления от шума (выдержка).
|
||||
\end{itemize}
|
||||
пространственная фильтрация - математическая работа с фильтрами. обычно маски выбираются нечётных размерностей. маски называются свёртками. накрываем область маской. в результате получаем число. что делают с краями? заполняют нулями или дублируют крайние пиксели. Операция свёртки отличается от операции корелляции.
|
||||
|
||||
Известные пространственные фильтры
|
||||
\begin{itemize}
|
||||
\item простейший линейный сглаживающий усредняющий фильтр (нч-фильтр) получает взвешенное среднее по окрестности. полезны для расфокусировки. можно выполнить обратное преобразование
|
||||
\item медианный фильтр - нелинейное преобразование.
|
||||
\item адаптивный медианный фильтр
|
||||
\item пространственный фильтр повышения резкости. используется для увеличения резкости мелких деталей. основывается на пространственном диференцировании. дифференцирование позволяет усилить разрывы в изображения (не затрагивает области медленного изменения яркости).
|
||||
\item улучшение изображений с использованием лапласиан - фильтр повышения резкости второй производной.
|
||||
\item нерезкое маскирование и фильтрация с подъёмом частот.
|
||||
\item градиент (первая производная). обобщение по модулю. на основании градиента получается оператор Собеля.
|
||||
\end{itemize}
|
||||
методы часто комбинируют, поскольку один метод чаще всего не решает задачу. общей теории нет, поэтому комбинации и порядок каждый раз разные.
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Частотные методы улучшения изображений}
|
||||
преобразование фурье и частотная область. любая периодическая функция может быть представлена как сумма синусов и косинусов, которая называется рядом фурье.
|
||||
|
||||
Одномерное преобразование фурье это парные функции. можно применять к функциям двух переменных (ф-лы 3,4). дороговато работать с экспонентой, поэтому использовали ф-лу эйлера (7), что позволило получить привычный вид преобразований.
|
||||
|
||||
дискретное прямое и обратное преобразование фурье (слайд13)
|
||||
|
||||
фильтры и их свойства
|
||||
\begin{enumerate}
|
||||
\item фильтр-пробка 04-17. оптически вырезает начало координат. происходит падение общей яркости.
|
||||
\item фильтр нч и вч. по названию понимаем, какие частоты пропускаются. это центрально-симметричные фильтры. чтобы не терять яркость добавляют дополнительные коэффициенты в фильтры вч.
|
||||
\item гауссов фильтр. прямое и обратное ПФ это гауссовы функции.
|
||||
\item сглаживающие частотные фильтры. ослабляем высокочастотные значения и получаем размытие. Идеальный ФНЧ по сути как фильтр-пробка, очень жёсткий.
|
||||
\item ФНЧ Баттерворта (нечто среднее между идеальным и гауссовым)
|
||||
\item гауссовы ФНЧ - гарантируют, что никакие артефакты после фильтрации не появятся
|
||||
\item фильтры повышения резкости ослабляем низкочастотные колебания. идеальные ФВЧ с очень резким порогом
|
||||
\item Баттерворт
|
||||
\item Гаусс
|
||||
\end{enumerate}
|
||||
|
||||
Лапласиан в частотной области
|
||||
получаем некоторое серое изображение, при наложении на исходное значительно повышаем резкость.
|
||||
|
||||
\section{Обработка цветных цифровых изображений}
|
||||
\subsection{Цветовые модели}
|
||||
Исследование показало, что в цветовом пространстве HSI цвета кожи лежат в одном пространстве, что позволяет осуществлять обработку изображений с камер для управления жестами. В целом существует 6,2 млрд устройств, способных формировать изображения. Цветные изображения в видимом электромагнитном излучении это капля в море. (05-07)
|
||||
|
||||
Цвет это субъективная характеристика. Глаз видит в RGB. Цвет фактически проходит через весь мозг до затылочной зоны. При интерпретации цветов для устройств (печать, например, используется CMYK). Для более-менее объективного представления цветов и определения возможностей цветопередачи, например, устройств, используют диаграммы цветности.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=8cm]{05-col-diag.png}
|
||||
\caption{Диаграмма цветностей}
|
||||
\label{pic:col-diag}
|
||||
\end{figure}
|
||||
|
||||
|
||||
Человеческий фактор в восприятии цвета обычно выражается в сопоставлении цветов явлениям. как, например, объяснить слепому, что такое красный или зелёный. То есть мозг интерпретирует цвета и дополняет эту интерпретацию образами или ощущуениями. Цвета часто дополняют друг друга или чёрно-белые изображения (эксперименты когда смотрим на точку в негативе, меняем на ЧБ изображение и видим цвет).
|
||||
|
||||
Самое простое и частое представление цвета - это RGB. это обычный куб где в обном углу чисто белый в противоположеном чисто чёрный и по оси идут отенки серого. в дополнение к цвету дополняют дальномером для вычитания фона - это rgb-d.
|
||||
|
||||
Обратное цветовое пространство - это cmyk. где cmy = 1 - RGB.
|
||||
|
||||
HSI сразу даёт оценку основному цвету. в РГБ яркость размазана по компонентам, а здесь интенсивность выделена в отдельный компонент. большинство проблем компьютерного зрения решается. Недостаток - это очень дорогой переход из пространства RGB.
|
||||
|
||||
YUV - пространство имеющее свои корни в телевидении. UV это цветность красного и синего. Y - это полутоновые значения. есть некоторая матрица перевода в RGB.
|
||||
|
||||
\subsection{Обработка изображений в псевдоцветах}
|
||||
Полутона это на самом деле трёхмерный объект. Чтобы превратить такое изображение в цвет осуществляют квантование по яркости. Самое распространённое это применение например при метеосводках или а аэропортах для контроля багажа - красим изображение в некоторые цвета. всегда очень много эвристики, надо понимать какие компоненты цвета квантовать.
|
||||
|
||||
Часто псевдоцвета используются в космической отрасли или ДЗЗ. Либо преобразуем всё целиком, либо какую-то одну компоненту.
|
||||
|
||||
Основы преобразований: \textbf{c} есть некоторый вектор в цветовом пространстве \textbf{RGB}
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
c = \Big[\substack{c_R\\c_G\\c_B} \Big] = \Big[\substack{R\\G\\B}\Big]\\
|
||||
c(x,y) = \bigg[\substack{c_R(x,y)\\c_G(x,y)\\c_B(x,y)} \bigg] = \bigg[\substack{R(x,y)\\G(x,y)\\B(x,y)}\bigg]
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
\subsection{Цветовые преобразования}
|
||||
Преобразование цветных изображений задается выражением:
|
||||
\[ g(x,y) = T[f(x,y)] \]
|
||||
Рассмотрим преобразование вида
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
s_i = T_i(r_1,r_2,...,r_n), i=1,2,...,n\\
|
||||
g(x,y)=kf(x,y)\\
|
||||
s_3=kr_3\\
|
||||
s_i=kr_i, i=1,2,3\\
|
||||
s_i=kr_i+(1-k), i=1,2,3
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
в 3 к это коэффициент яркости. все простые цифровые преобразования работают и для цветовых преобразований.
|
||||
|
||||
\begin{enumerate}
|
||||
\item Цветовое дополнение. в полутонах использовали для поднятия яркости. для уветного изображения используется для преобразования в негатив.
|
||||
\item Использование цветовых сочетаний - комплементарное (противоположные по HSI), аналогия (соседние), троичное (треугольник по HSI), сплит-комплементарное (контрастная триада), тетраидное сочетание (прямоугольник в HSI). Используются, например, в кино, для создания эффектов мякгости, уюта, экшна, привлечения внимания, дискотеки.
|
||||
\item вырезание цветового диапазона
|
||||
\item яркостная и цветовая коррекция (модель увета представлена сферой). смысл в том что надо сначала исправить яркость, чтобы работать с цветом. Некоторые цвета заложены в аналогиях в мозге. Мы глазами сразу видим расхождения в цвете, это обусловлено эволюционно.
|
||||
\item Обработка гистограмм (нормализация и эквализация). можем потерять детали
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Сглаживание и повышение резкости}
|
||||
\begin{itemize}
|
||||
\item фильтр усреднения (сглаживание, интеграл).
|
||||
\item повышение резкости с помощью лапласиана
|
||||
\end{itemize}
|
||||
\subsection{Цветовая сегментация}
|
||||
выбираем компоненту которая ближе к искомому объекту, бинаризируем, сглаживаем и выделяем не просто порогом, а трёхмерное пороговое преобразование, которое более точное.
|
||||
|
||||
Обнаружение контуров на цветных изображениях производится также выделением шума, в HSI не очень удобно, компоненты выдяелять сложнее.
|
||||
|
||||
Усиление цвета - частая задача для подводных работ, поскольку цвет на глубине визуально меняется. Короризацию осуществляют нейросетями и свёртками.
|
||||
|
||||
|
||||
\section{Морфологическая обработка изображений}
|
||||
Также называют математической обработкой изображений. Теория множеств позволяет получить базовый математический аппарат, выполняющий обработки.
|
||||
\subsection{Основы морфологической обработки}
|
||||
\begin{itemize}
|
||||
\item Центральное отражение $\hat{B} = \{ w| w=-b, b\in B \}$;
|
||||
\item сдвиг $(A)_z = \{ c|c=a+z,a\in A \}$;
|
||||
\item логические операция (функционально-полный базис) (06-06-13)
|
||||
\item дилатация $A\oplus B = \{ z|(\hat{B}_z \cap A \neq \oslash)\}$ или $A\oplus B = \{ z|[(\hat{B}_z) \cap A] \subseteq A \}$;
|
||||
\item эрозия $A\ominus B = \{z| (\hat{B}_z\subseteq) A\}$ (06-15);
|
||||
\item размыкание в общем случае подсвечивает разрывы, расширяет (06-18)
|
||||
\item замыкание в общем случае заливает узкие места изображения.
|
||||
\item hit or miss transform (06-28)
|
||||
\end{itemize}
|
||||
|
||||
Операции размыкания и замыкания являются двойственными (06-22). Многократное применение операций не имеет действия. Эффект будет только один раз.
|
||||
\subsection{Морфологические алгоритмы}
|
||||
Это некий набор устоявшихся эвристик (комбинаций основных морфологических основ).
|
||||
\begin{enumerate}
|
||||
\setcounter{enumi}{-1}
|
||||
\item (29) Определение отверстий, углов и связных признаков: при правильном выборе свёртки и операции успех/неудача у изображения будут «подсвечены» соответствующие части, например, отверстия, углы или границы;
|
||||
\item (30) Выделение границ $\beta (A) = A - (A \ominus B)$.
|
||||
\item (31) Алгоритм заполнения областей $X_k = (X_{k-1} \oplus B) \cap A^c$. Рекуррентная процедура, находим границу и границы заливки, и объединяем.
|
||||
\item (32) Выделение связных компонент $X_k = (X_{k-1} \oplus B) \cap A$. Также рекуррентная процедура. Связанные компоненты это если между ними есть цепочка пикселей.
|
||||
\item (33) Выпуклая оболочка. полезна для построения описания объектов. Используем 4 примитива, в отличие от остальных. Сама оболочка это объединение четырёх обработок.
|
||||
\item (34) Уточнение. основано на успех/неудаче.
|
||||
\item (35) Утолщение. двойственная операция от утончения. также можно записать серией примитивов
|
||||
\item (36) Построение остова. сильно похож на утончение, применяется для сегментации сложных объектов
|
||||
\item (42) Усечение. позволяет практически «вырастить» исходное изображение из минимального набора данных. область применения - распознавания рукописных знаков. есть допущение, что длина паразитных пикселей не должна быть больше полезной. так можно подавить паразитную ветку. у этого преобразования строго набранные примитивы и применяются в строгом порядке для получения концевых точек.
|
||||
\item (43-48) Морфологическая реконструкция. сходная по работе с усечением. но кроме примитива используется более сложное изображение.
|
||||
\end{enumerate}
|
||||
\subsection{Применение морфологии к полутоновым изображениям}
|
||||
\begin{enumerate}
|
||||
\item дилатация (52)
|
||||
\item эрозия (53)
|
||||
\item (54) размыкание и замыкание применяются для устранения шумов.
|
||||
\end{enumerate}
|
||||
\subsection{Полутоновые морфологические алгоритмы}
|
||||
\begin{enumerate}
|
||||
\item морфологическое сглаживание избавление от шумов
|
||||
\item морфологический градиент ищет границы исходного изображения
|
||||
\item top-hat bottom-hat находит верхний и нижний уровень, коррекция затемнения
|
||||
\item гранулометрия
|
||||
\item текстурная сегментация
|
||||
\item полутоновая морфологическая реконструкция
|
||||
\end{enumerate}
|
||||
Для сложных комбинаций используются нейронные сети и глубокое обучение.
|
||||
\section{Сегментация цифрового изображения}
|
||||
\subsection{Обнаружение областей}
|
||||
Сегментация изображения – это процесс разбиения изображения на множество покрывающих его областей.
|
||||
Две основные цели сегментации:
|
||||
\begin{enumerate}
|
||||
\item Декомпозиция изображения на части, более удобные для дальнейшей обработки.
|
||||
\item Изменение формы описания изображения. (для уменьшения объёма хранения, например).
|
||||
\end{enumerate}
|
||||
|
||||
Ключевой вопрос, можно ли выполнять сегментацию снизу вверх без уч§та особенностей информации. Сегментация также называется бинаризация и возможна при помощи нечёткой логики. Желательные свойства сегментированных областей:
|
||||
\begin{enumerate}
|
||||
\item Области должны быть целостными и однородными по какому-либо признаку. (например по текстуре)
|
||||
\item Внутренние части областей должны иметь простую форму и не содержать большое количество мелких отверстий. (хотя мелкие области могут формировать текстуру)
|
||||
\item Смежные области должны существенно отличаться по значению сегментирующего признака. (по которыми они должны быть неоднородными)
|
||||
\item Границы области должны иметь гладкую форму. (без зазубрин и разрывов)
|
||||
\end{enumerate}
|
||||
|
||||
Рассмотрим следующие алгоритмы сегментации, позволяющие обнаруживать области на цифровом изображении:
|
||||
\begin{enumerate}
|
||||
\item Итерационная кластеризация по математическому ожиданию.
|
||||
|
||||
Кластеризация – это процесс разбиения множества векторов признаков на подмножества, называемые кластерами.
|
||||
(07-08)
|
||||
Будем рассматривать K кластеров $C_1, C_2, ..., C_K$ с математическими ожиданиями $m_z, m_2, ..., m_K$. Квадратичная ошибка определяется выражением
|
||||
\[D = \sum_{k=1}^K \sum_{x_i \in C_k} || x_i - m_k ||^2\]
|
||||
измеряем точки между собой и определяем центры, каждую точку сравниваем с центром полученного кластера и определяем, какая точка принадлежит какому кластеру. Алгоритм точно завершится, но нельзя заранее понять сколько кластеров (нужно задавать руками)
|
||||
Формирование K кластеров на множестве n-мерных векторов.
|
||||
\begin{enumerate}
|
||||
\item присвоить счётчику итераций $ic$ значение 1
|
||||
\item случайным образом выбрать K значений математических ожиданий $m_1(1), m_2(1), ..., m_K(1)$
|
||||
\item для каждого вектора $x_i$ вычислить расстояние $D(x_i, m_k(ic))$ для каждого $k = 1, ..., K$ и поместить $x_i$ в кластер $C_j$ с ближайшим вектором математического ожидания
|
||||
\item увеличить $ic$ на 1 и скорректировать значения математических ожиданий для получения нового множества $m_1(ic), m_2(ic), ..., m_K(ic)$
|
||||
\item повторять шаги 3 и 4 до тех пор, пока при всех $k$ не будет выполняться равенство $C_k(ic) = C_k(ic + 1)$.
|
||||
\end{enumerate}
|
||||
|
||||
\item Алгоритм кластеризации ISODATA.
|
||||
\[x_i = [v_1, v_2, ..., v_n] \]
|
||||
\[m_k = [m_{1k}, m_{2k}, ..., m_{nk}] \]
|
||||
\begin{equation*}
|
||||
\sum_k = \begin{bmatrix}
|
||||
\sigma_{11} & \sigma_{21} & ... & \sigma_{1n} \\[0.3em]
|
||||
\sigma_{12} & \sigma_{22} & ... & \sigma_{2n} \\[0.3em]
|
||||
... & ... & ... & ... \\[0.3em]
|
||||
\sigma_{1n} & \sigma_{2n} & ... & \sigma_{nn}
|
||||
\end{bmatrix}
|
||||
\end{equation*}
|
||||
|
||||
(07-12)
|
||||
развитие евклидовых способов обработки изображений.
|
||||
\item Алгоритм поиска моды гистограммы.
|
||||
Относится к простым гистограммным методам. итерационные идут по исходным данным много раз, а эти один раз, то есть работает значительно быстрее. предназначен для сегментации в пространстве измерений. например, для выбора моды (мода в отличие от средних значений выбирается, а не вычисляется).
|
||||
процедура бинаризации - это всегда преобразование в ч/б.
|
||||
\item Рекурсивный гистограммный метод Оландера.
|
||||
усовершенствование гистограммного метода. сначала ищется мода на полном изображении, а затем на каждом кластере, пока возможно сегментировать.
|
||||
(07-16)
|
||||
связанные компоненты маркируются, и снова вызывается метод. гистограммы не всегда работают на RGB.
|
||||
\item Графовое разбиение Ши.
|
||||
в отличие от предыдущих, работающих на простых изображениях. цель сегментации в нахождении такого количества вершин, чтобы были непересекающиеся множества, максимально отличающихся друг от друга.
|
||||
(07-17,18)
|
||||
\item Алгоритм наращивая областей Харалика
|
||||
ищутся области из связанных пикселей с общим выборочным средним и дисперсией. Если выбрать пиксели с определённой интенсивностью, то область является областью с некоторой степенью свободы, куда может быть добавлена новая область с новым средним и новой дисперсией.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Обнаружение контуров}
|
||||
Рассмотрим следующие алгоритмы сегментации, позволяющие обнаруживать контуры на цифровом изображении:
|
||||
\begin{enumerate}
|
||||
\item Выделение границ областей на маркированном изображении. (24)
|
||||
\item Детектор краев Кэнни. наиболее часто применяемый алгоритм. сначала сглаживаем изображение с сигмой, потом считаем направление градиента для максимального подавления.
|
||||
\item Группировка согласующихся контуров в кривые. (27)
|
||||
\item Преобразование Хафа. (31)
|
||||
ищут обычно дуги окружностей, нелинейные отрезки. параметры выбираются вручную.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Обнаружение моделей сегментов}
|
||||
Рассмотрим подходы, позволяющие обнаруживать модели сегментов на цифровом изображении, в частности подбор прямой.
|
||||
\begin{itemize}
|
||||
\item подбор прямой (37) используется критерий наименьших квадратовПроблемы аппроксимации:
|
||||
1. Выбросы.
|
||||
2. Определения отклонения.
|
||||
3. Нелинейная оптимизация.
|
||||
4. Большая размерность.
|
||||
5. Ограничения аппроксимации.
|
||||
лентой называется продолговатой области, форма которой приблизительно симметрична относительно главной оси. часто, но не всегда края ленты характеризуются симметричным контрастом и фоном.
|
||||
\item обнаружение углов (43) поиск характерных признаков и построение вектора движения, то есть работа уже в 4х мерном прстранстве
|
||||
\end{itemize}
|
||||
|
||||
главная архитектура - это кодер/декодер. главная модель - U-net. изображения сегментируют в базы данных, которые классифицируют.
|
||||
\subsection{Обнаружение высокоуровневых структур}
|
||||
\subsection{Обнаружение согласованного движения}
|
||||
\subsection{Нейронные сети}
|
||||
|
||||
\section{Описание цифрового изображения}
|
||||
возможно представить область через внешние или через внутренние характеристики. Внешнее обычно выбирается если интересна форма, внутренняя если текстура или цвет.
|
||||
1) Коды, линии, границы, области.
|
||||
2) Дескрипторы границ.
|
||||
3) Дескрипторы областей.
|
||||
|
||||
Цепной код. с их помощью граница показывается в виде точек и соединений в одном направлении. важен момент аппроксимации, чтобы потом возможно было восстановить изображение обратно. иногда кодируют не абсолютными значениями, а разницей прошлой точки и следующей.
|
||||
|
||||
Аппроксимация ломанной линией. цель - представить объект как можно меньшим числом линий. используются методы слияния, разбиения на различные отрезки (до выполнения критерия).
|
||||
|
||||
сегменты границы. при декомпозиции упрощается описание за сч§т уменьшения сложности. обычно применяется если есть несколько ярко выраженных вогнутостей. на практике границы областей неровные, поэтому их можно сегментировать и отбросить неважное методами морфологического анализа.
|
||||
|
||||
один из простейших дескрипторов - длина (возможно, с порогом отклонением). также можно использовать диаметр (две экстремальные точки, определяющие диаметр). эксцентриситет - величина границы (кривизна, которая определяется как скорость изменения угла наклона).
|
||||
|
||||
Фурье дескрипторы обходят границу и представляют ея в виде последовательности координат (комплексных чисел). применив дискретное преобразование - получим фигуру с заданной точностью.
|
||||
|
||||
статистические характеристики это средние, дисперсии, и так далее. характеризовать можно не только яркость, но и цвет, и так далее. здесь рассматриваются амплитуды и строятся гистограммы, чтобы наложить изображение на координатную ось, которое можно нормализовать и преобразовать. с точки зрения реализации явно указывается простота.
|
||||
|
||||
дескрипторы областей
|
||||
\begin{itemize}
|
||||
\item площадь (число пикселей внутри)
|
||||
\item периметр (кол-во пикселей на периметре)
|
||||
\item компактность (наличие неровностей)
|
||||
\item среднее значение яркостей пикселей
|
||||
\item медиана яркостей пикселей
|
||||
\end{itemize}
|
||||
|
||||
Топологические дескрипторы
|
||||
если нет разрывов и склеек - это область изучения топологии.
|
||||
|
||||
Текстурные дескрипторы
|
||||
Отсутствует формальное определение, но интуитивно понятно, что есть гладкость, шероховатость, периодичность. Для определения текстуры есть статистический, структурный и спектральный подходы.
|
||||
|
||||
моменты двухмерных функций. с исходным изображением совершили несколько манипуляций и получили несколько инвариантов
|
||||
|
||||
\section{Распознавание образов}
|
||||
Самый популярный способ - машины опорных векторов. в них возможно использовать не только одномерные но и двухмерные (линейные базисные функции). но этот подход неустойчив к шуму. У деревьев решений также есть ряд недостатков: недостаточность данных, многозначные атрибуты.
|
||||
|
||||
Есть также кластерный анализ (как в сегментации).
|
||||
|
||||
SIFT.
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{0}
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Семинар 1 (2022-02-16)}
|
||||
Книга: Dictionary of computer vision and image processing
|
||||
|
||||
Вопросы нам:
|
||||
\begin{itemize}
|
||||
\item \textbf{color quantization}: The quantization (i.e., discretization) of the image sig- nal into a number of bins each rep- resenting a specific level of intensity (i.e., pixel values). Occurs at image capture, at the CCD or CMOS sensor level, within the camera. For RGB color image capture this is facilitated using the Bayer pattern on the sensor itself.
|
||||
Also performed as a secondary process, re-quantization for color reduction or color re-mapping: Coarser quantization allows image compression with fewer bits. [SB11:2.3.2]
|
||||
\item color re-mapping: An image transfor- mation where each original color is replaced by another color from a col- ormap. If the image has indexed col- ors, this can be a very fast opera- tion and can provide special graphical effects for very low processing over- head: [WAF+98]
|
||||
\item Feret’s diameter: The distance between two parallel lines at the extremities of some shape that are tangential to the boundary of the shape. Maximum, minimum and mean values of Feret’s diameter are often used (where every possible pair of parallel tangent lines is considered): [WP:Feret\_diameter]
|
||||
\end{itemize}
|
||||
|
||||
Наши возможные вопросы:
|
||||
\begin{multicols}{2}
|
||||
\includegraphics[width=7cm]{sem-02-illum.png}
|
||||
|
||||
\columnbreak
|
||||
coaxial illumination: Front lighting with the illumination path running along the imaging optical axis. An advantage of this technique is that there are no visible shadows or direct specularities from the camera’s viewpoint.
|
||||
\end{multicols}
|
||||
|
||||
|
||||
|
||||
\subsection{Семинар 2 (2022-03-16)}
|
||||
При МО мы имеем изображения как на входе так и на выходе, то есть в отличие от частотной нет промежуточного результата.
|
||||
|
||||
МО использует математику множеств.
|
||||
множеству можно принадлежать или не принадлежать, множества можно объединять, у множеств бывают пересечения. Множества можно вычитать. Математическое множество можно перевернуть (отражать) и осуществить параллельный перенос.
|
||||
|
||||
В морфологии изображений есть два базовых понятия
|
||||
\begin{itemize}
|
||||
\item Дилатация - это все такие точки З, что перенос отражённого Б в эту точку принадлежит множеству А. Все переносы считаются относительно центра примитива Б.маленький квадрат Б двигаем внутри большого квадрата А и там точно есть хотя бы одна общая точка. Дилатация Б приводит к расширению А.
|
||||
\item Эрозия - наоборот А как-то схлопывается. $A\ominus B = \{z | (B_z) \subseteq A\}$. Так мы можем убирать какие-то помехи и шумы.
|
||||
\end{itemize}
|
||||
|
||||
Из этих базовых операций складываются операции замыкания и размыкания. смыкание для сглаживания контуров. Размыкание - это сначала эрозия, потом дилатация А по Б. Замыкание - обратная операция - сначала дилатация А по Б, затем эрозию А по Б.
|
||||
Если берём А треугольник, а Б круг - при размыкании получим такой же треугольник, но с закруглёнными углами.
|
||||
У размыкания есть свойства. А размыкание Б всегда лежит в А.
|
||||
\begin{enumerate}
|
||||
\item $A\odot B \subseteq A$
|
||||
\item $C \in D, C \odot B \subseteq B \in D \odot B$
|
||||
\item $(A\odot B) \odot B = A\odot B$
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Семинар 3 (2022-04-13)}
|
||||
Вариант 9
|
||||
|
||||
|
||||
1. Поменять местами второй и пятый столбцы матрицы. Нумерация идет слева направо.
|
||||
2. Поменять местами первую и вторую строку. Нумерация идет сверху вниз.
|
||||
3. Выполнить траспонирование матрицы
|
||||
4. Горизонтальный переворот матрицы. Первый столбец становится пятым и т.д.
|
||||
5. Увеличение яркости. К каждому значению RGB прибавить 20.
|
||||
6. Уменьшение яркости. Из каждого значения RGB вычесть 30.
|
||||
7. Выполнить обработку матрицы согласно эффекту сепия.
|
||||
8. Выполнить обработку матрицы согласно эффекту оттенки серого.
|
||||
9. Сделать изображение черно-белым.
|
||||
\subsection{Семинар 4 (2022-04-27)}
|
||||
ForeSight
|
||||
\subsection{Семинар 5 (2022-05-11)}
|
||||
Вариант 9
|
||||
|
||||
Разделы автореферата
|
||||
- степень разработанности проблемы;
|
||||
написано будто задачи поставлены и решены, но явного указания (раздела) нет
|
||||
|
||||
- материал и методы исследования (предмет и объект исследования, методологическая и теоретическая база исследования);
|
||||
методы и инструменты описаны, но раздела с материалом нет
|
||||
|
||||
?+ теоретическая и практическая значимость работы;
|
||||
описана только практическая
|
||||
|
||||
- выводы;
|
||||
(описаны основные результаты работы, но не указаны места сообщений и не сделаны выводы)
|
||||
|
||||
- практические рекомендации;
|
||||
раздел практических рекомендаций также отсутствует
|
||||
|
||||
Подробнее:
|
||||
Актуальность: не указана научная (но значительно раскрыта практическая)
|
||||
Цели+
|
||||
Задачи+
|
||||
Предмет-
|
||||
Объект-
|
||||
Положения на защиту+ но не указан личный вклад (изложение не структурировано, просто перечислены пункты)
|
||||
Научная новизна+ но не соответствует структуре (нет новых проблем, не устанавливаются связи)
|
||||
Практическая значимость формально+ но никакой аналитики нет (экономика, масштабы, итд)
|
||||
Обоснование соответствия диссертации паспорту специальности указано, но не указаны в примерах
|
||||
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,566 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{домашней}{№ 1}{Создание оригинального алгоритма регенерации характерных признаков}{Цифровая обработка изображений}{}{Большаков В.Э.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Задание}
|
||||
\begin{enumerate}
|
||||
\item На языке Python 3.х подключить библиотеку opencv;
|
||||
\item Дать пошаговое описание работы метода Лукаса-Канаде(ЛК);
|
||||
\item Подготовить видеопоток с медленно движущимся объектом по горизонтали;
|
||||
\item Запрограммировать отслеживание объекта с использованием ЛК метода (использовать функцию \code{cv2.calcOpticalFlowPyrLK()});
|
||||
\item Сделать перевод статьи Tracking of Moving Objects With Regeneration of Object Feature Points;
|
||||
\item Подготовить второй видеопоток на основе для создания условий потери характерных точек ЛК при движении объекта;
|
||||
\item Разработать и запрограммировать оригинальный алгоритм регенерации характерных признаков ЛК (по аналогии со статьей).
|
||||
\item Провести эксперимент по регенерации характерных признаков ЛК с визуализацией результатов.
|
||||
\item Провести эксперимент по отслеживанию объектов с визуализацией результатов (в том числе визуализацией применения характерных признаков на изображении). Сравнить надежность отслеживания с регенерацией и без нее.
|
||||
\end{enumerate}
|
||||
\section{Теоретическая часть}
|
||||
Для обнаружения объектов на видео используется несколько методов: Ши-Томаси (поиск опорных точек) и Лукаса-Канаде (слежение за опорными точками в оптическом потоке).
|
||||
\subsection{Метод поиска опорных точек Ши-Томаси}
|
||||
Основная идея заключается в том, что углы могут быть обнаружены путем поиска значительных изменений во всех направлениях. Сначала рассматривается небольшое окно на изображении, затем сканируем всё изображение в поисках углов. Смещение окна в любом направлении приведет к значительному изменению внешнего вида, если это конкретное окно окажется над углом. То есть если мы замечаем, что есть область, в которой происходят значительные изменения, независимо от того, в каком направлении производится сканирование, то есть высокая вероятность, что в этом месте находится угол. Метод Ши-Томаси основан на методе детектирования углов Харриса (подробнее в подразделе \hrf{appendix:harris}) заключается в поиске соседних областей со значительным изменением интенсивности расматриваемого параметра (например, яркости). Метод производит оценку изображения и выставляет коэффициенты изменения областям. Выставление корректного порога оценки является ключевым фактором в правильном определении. Метод Ши-Томаси принципиально отличается только формулой оценки (подробнее в подразделе \hrf{appendix:shi-tomasi}) выбирающей не разницу произведения и суммы $\lambda_1$ и $\lambda_2$, а минимум из этих двух значений.
|
||||
\subsection{Метод Лукаса-Канаде}
|
||||
Оптический поток - это изображение видимого движения объектов, получаемое в результате перемещения объекта относительно наблюдателя. Выборочный поток - поток, который учитывает сдвиг отдельных заданных точек (например, некоторых характерных точек, предварительно найденных одним из алгоритмов детектирования таких точек). Алгоритм Лукаса-Канаде использует выборочный поток на первом кадре и после оценивает их расположение на последующем кадре. Алгоритм использует следующие данные:
|
||||
|
||||
\begin{itemize}
|
||||
\item Два кадра, следующие друг за другом (кадры полученные видео);
|
||||
\item Массив начального набора характеристических точек;
|
||||
\item Массив результирующих точек;
|
||||
\item Массив который показывает статус поиска каждой точки;
|
||||
\item Массив погрешностей для каждой операции поиска;
|
||||
\item Размер окна по которому производится гауссово усреднение;
|
||||
\item Дополнительные флаги, которые можно использовать для установки начального приближения потока или выбрать метод оценки погрешности, а также пороговое значение градиента.
|
||||
\end{itemize}
|
||||
|
||||
Важное допущения, для использования метода Лукаса-Канаде:
|
||||
\begin{itemize}
|
||||
\item Значения пикселей переходят из одного кадра в следующий кадр без изменений. Таким образом, мы делаем допущение, что пиксели, относящиеся к одному и тому же объекту, могут сместиться в какую-либо сторону, но их значение останется неизменным;
|
||||
\item В алгоритме используется только производная первого порядка для аппроксимации функции движения выборочного потока
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Регенерация точек}
|
||||
Мы можем попытаться регенерировать точки после препятствия, потому что предполагаем что точки продолжат движение с вероятностью, которую можно найти, как максимум функции правдоподобия. То есть, из всего пространства возможных элементарных перемещений точек мы выбираем те, при которых функция правдоподобия достигает своего максимума. Функция правдоподобия зависит от значений положения опорных точек до препятствия и после (можно сказать, что это априорное положение опорной точки и апостериорное). Так как явный вид такой функции неизвестен, мы предполагаем что функция плотности вероятности является нормальной случайной величиной и, по этой причине, с вероятностью $\pm34.13\%$ опорная точка продолжит движение со среднеквадратичным отклонением скорости, численно равным средней скорости всех опорных точек до препятствия
|
||||
\section{Практическая часть}
|
||||
Входящими в алгоритм данными является видеофайл (поток из видеокадров) содержащий статический фон (камера не двигается), некоторое препятствие (неподвижный объект, находящийся между камерой и отслеживаемым объектом) и достаточно медленно перемещающийся объект. Результат работы алгоритма - это наложенные поверх видео отметки о характерных точках движущегося объекта. С точки зрения реализации, работа по распознаванию характерных точек в видеокадрах разделена на четыре основные части:
|
||||
\begin{enumerate}
|
||||
\item преобразование изображения в градации серого производится стандартной функцией библиотеки \code{OpenCV}.
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
# ...
|
||||
prevGrayscale = cv2.cvtColor(prevFrame, cv2.COLOR_BGR2GRAY)
|
||||
# ...
|
||||
frameGrayscale = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
|
||||
# ...
|
||||
\end{lstlisting}
|
||||
В результате работы функции алгоритмы будут далее использовать изображения как, например, на рис. \hrf{pic:first}.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=14cm]{01-dip-hw-first.png}
|
||||
\caption{Первый кадр изображения}
|
||||
\label{pic:first}
|
||||
\end{figure}
|
||||
|
||||
\item поиск характерных точек методом Ши-Томаси,
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
# ...
|
||||
p0 = cv2.goodFeaturesToTrack(prevGrayscale, mask=mask_rect, **shiTomasiParameters)
|
||||
# ...
|
||||
\end{lstlisting}
|
||||
Характерные точки ищутся внутри выделенной области (рис. \hrf{pic:bounding-box}). Внутрь функции передаются параметры, представленные в листинге \hrf{src:shi-tomasi-param}.
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,label={src:shi-tomasi-param}]
|
||||
# ...
|
||||
shiTomasiParameters = dict(maxCorners=1000,
|
||||
qualityLevel=0.3,
|
||||
minDistance=5)
|
||||
# ...
|
||||
\end{lstlisting}
|
||||
где
|
||||
\begin{itemize}
|
||||
\item [] \code{maxCorners} - количество углов (точек), которые мы хотим найти;
|
||||
\item [] \code{qualityLevel} - значение порога, ниже которого углы будут отклонены;
|
||||
\item [] \code{minDistance} - расстояние, на котором будут отброшены все менее качественные углы.
|
||||
\end{itemize}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=14cm]{01-dip-hw-manual.png}
|
||||
\caption{Определение окна объекта}
|
||||
\label{pic:bounding-box}
|
||||
\end{figure}
|
||||
|
||||
\item отслеживание характерных точек методом Лукаса–Канаде (рис. \hrf{pic:tracking}) - производится встроенной функцией из библиотеки OpenCV, также на монохромном изображении. Функция принимает на вход предыдущий и текущий кадр, а также параметры, представленные в листинге
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,label={src:lucas-kanade-param}]
|
||||
lucasKanadeParameters = dict(winSize=(10, 10),
|
||||
maxLevel=2,
|
||||
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
# ...
|
||||
p1, st, err = cv2.calcOpticalFlowPyrLK(prevGrayscale, frameGrayscale, p0, None, **lucasKanadeParameters)
|
||||
\end{lstlisting}
|
||||
где
|
||||
\begin{itemize}
|
||||
\item [] \code{winSize} - размеры окна поиска;
|
||||
\item [] \code{maxLevel} - количество уровней пирамиды поиска;
|
||||
\item [] \code{criteria} - критерии окончания поиска итеративным алгоритмом.
|
||||
\end{itemize}
|
||||
|
||||
и для вызова функции
|
||||
\begin{itemize}
|
||||
\item [] \code{prevGrayscale} - предыдущий кадр в градациях серого;
|
||||
\item [] \code{frameGrayscale} - текущий кадр в градациях серого;
|
||||
\item [] \code{p0} - набор из найденных на предыдущем кадре точек;
|
||||
\item [] \code{p1} - набор из найденных (отслеженных) на текущем кадре точек;
|
||||
\item [] \code{st} - вектор статуса точек (1 точка отслежена и подтверждена, 0 точка потеряна).
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=14cm]{01-dip-hw-frame-before.png}
|
||||
\caption{Отслеживание характерных точек}
|
||||
\label{pic:tracking}
|
||||
\end{figure}
|
||||
\item попытка регенерации потерянных из-за наличия препятствия характерных точек по методу Лычкова-Алфимцева-Сакулина. По условию задачи объект двигается горизонтально, его скорость невелика, как и любой иной объект он имеет свойство сохранять своё движение и за препятствием (когда опорные точки явно пропадают из вида), тогда мы можем предположить, что точки продолжат двигаться с некоторой скоростью, которую они имели до попадания объекта за препятствие, так называемая средняя скорость в физике. Применяя это понятие производим суммирование по всем точкам объекта и вычисляем среднюю скорость до попадания за препятствие, делим на количество таких точек, получим среднюю скорость, далее, когда объект окажется за препятствием - добавляем к тем точкам которые прекратили своё движение в горизонтальном направлении (упёрлись в препятствие) эту среднюю скорость, как добавочную, и считаем что они продолжают движение с этой скоростью. Далее как только объект вновь покажется после препятствия, метод Лукаса-Канаде снова найдёт опорные точки в потоке и продолжит следовать за ними (рис \hrf{pic:regeneration}). То есть, делаем экстраполяцию (прогноз) движения опорных точек. Код, осуществляющий такое вычисление представлен в листинге \hrf{src:regeneration}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=14cm]{01-dip-hw-frame-after.png}
|
||||
\caption{Регенерация характерных точек}
|
||||
\label{pic:regeneration}
|
||||
\end{figure}
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,label={src:regeneration}]
|
||||
goodPoints = 0
|
||||
badPoints = 0
|
||||
badPointArray = []
|
||||
|
||||
k = 0.1
|
||||
meanXVelocity = 0.0
|
||||
xVelocity = 0.0
|
||||
for i in range(len(pointsInFrame)):
|
||||
if abs(pointsInFrame[i][0] - pointsInPrevFrame[i][0]) <= k:
|
||||
badPointArray.append(i)
|
||||
badPoints += 1
|
||||
else:
|
||||
goodPoints += 1
|
||||
xVelocity += abs(pointsInPrevFrame[i][0] - pointsInFrame[i][0])
|
||||
if goodPoints != 0:
|
||||
meanXVelocity = xVelocity / goodPoints
|
||||
for i in badPointArray:
|
||||
pointsInFrame[i][0] += meanXVelocity
|
||||
\end{lstlisting}
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\section{Заключение и выводы}
|
||||
В результате выполнения работы были изучены базовые методы цифровой обработки изображений и отслеживания объектов в видеопотоке. Объект был зафиксирован и отслеживался на протяжении всего пути, несмотря на препятствие. При проходе объекта за препятствием без применения регенерации все точки были потеряны, в то время как регенерация позволила сохранить большую их часть. Для увеличения числа сохранённых точек возможно описать более надёжный алгоритм регенерации с учётом направления движения характерной точки и добавления некоторой дельты скоростей (на случай изменения скорости движения объекта, пока он находится вне зоны видимости).
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Asbuk{subsection}}
|
||||
|
||||
\subsection{Полный листинг программы}
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
import numpy as np
|
||||
import cv2
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
def mainScript(videoName):
|
||||
cap = cv2.VideoCapture(videoName)
|
||||
shiTomasiParameters = dict(maxCorners=1000,
|
||||
qualityLevel=0.3,
|
||||
minDistance=7)
|
||||
|
||||
lucasKanadeParameters = dict(winSize=(10, 10),
|
||||
maxLevel=2,
|
||||
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
plt.figure(figsize=(10, 10))
|
||||
ret, prevFrame = cap.read()
|
||||
plt.imshow(prevFrame)
|
||||
plt.show()
|
||||
|
||||
prevGrayscale = cv2.cvtColor(prevFrame, cv2.COLOR_BGR2GRAY)
|
||||
mask_rect = [[0] * int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))] * int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
||||
mask_rect = np.asarray(mask_rect)
|
||||
mask_rect = mask_rect.astype(np.uint8)
|
||||
x0 = 0
|
||||
y0 = 450
|
||||
dx = 130
|
||||
dy = 130
|
||||
mask_rect[y0:y0 + dy, x0:x0 + dx] = 255
|
||||
p0 = cv2.goodFeaturesToTrack(prevGrayscale, mask=mask_rect, **shiTomasiParameters)
|
||||
p0_cor = np.int0(p0)
|
||||
|
||||
plt.figure(figsize=(10, 10))
|
||||
cv2.rectangle(prevFrame, (x0, y0), (x0 + dx, y0 + dy), 255, 2)
|
||||
for i in p0_cor:
|
||||
x, y = i.ravel()
|
||||
cv2.circle(prevFrame, (x, y), 1, 255, -1)
|
||||
plt.imshow(prevFrame)
|
||||
plt.show()
|
||||
|
||||
mask = np.zeros_like(prevFrame)
|
||||
color = np.random.randint(0, 255, (100, 3))
|
||||
|
||||
while True:
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
break
|
||||
frameGrayscale = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
|
||||
p1, st, err = cv2.calcOpticalFlowPyrLK(prevGrayscale, frameGrayscale, p0, None, **lucasKanadeParameters)
|
||||
|
||||
# Select good points
|
||||
pointsInFrame = p1[st == 1]
|
||||
pointsInPrevFrame = p0[st == 1]
|
||||
|
||||
# Regeneration
|
||||
goodPoints = 0
|
||||
badPoints = 0
|
||||
badPointArray = []
|
||||
|
||||
k = 0.1
|
||||
meanXVelocity = 0.0
|
||||
xVelocity = 0.0
|
||||
for i in range(len(pointsInFrame)):
|
||||
if abs(pointsInFrame[i][0] - pointsInPrevFrame[i][0]) <= k:
|
||||
badPointArray.append(i)
|
||||
badPoints += 1
|
||||
else:
|
||||
goodPoints += 1
|
||||
xVelocity += abs(pointsInPrevFrame[i][0] - pointsInFrame[i][0])
|
||||
if goodPoints != 0:
|
||||
meanXVelocity = xVelocity / goodPoints
|
||||
for i in badPointArray:
|
||||
pointsInFrame[i][0] += meanXVelocity
|
||||
# End Regeneration
|
||||
|
||||
# draw the tracks
|
||||
for i, (new, old) in enumerate(zip(pointsInFrame, pointsInPrevFrame)):
|
||||
a, b = new.ravel()
|
||||
c, d = old.ravel()
|
||||
mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)
|
||||
frame = cv2.circle(frame, (int(a), int(b)), 1, color[i].tolist(), -1)
|
||||
img = cv2.add(frame, mask)
|
||||
|
||||
cv2.imshow('frame', img)
|
||||
k = cv2.waitKey(30) & 0xff
|
||||
if k == 27:
|
||||
break
|
||||
|
||||
# Now update the previous frame and previous points
|
||||
prevGrayscale = frameGrayscale.copy()
|
||||
p0 = pointsInFrame.reshape(-1, 1, 2)
|
||||
|
||||
cv2.destroyAllWindows()
|
||||
cap.release()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mainScript('IMG_9680.MOV')
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Детектирование углов Харриса} \label{appendix:harris}
|
||||
\href{https://docs.opencv.org/4.x/dc/d0d/tutorial_py_features_harris.html}{OpenCV: Документация}
|
||||
|
||||
\begin{multicols}{2}
|
||||
Углы — это области изображения с большим разбросом интенсивности во всех направлениях. Одна из первых попыток найти углы в цифровом изображении была предпринята Крисом Харрисом и Майком Стивенсом в их статье «Комбинированный детектор углов и краев» в 1988 году, поэтому теперь она называется детектором углов Харриса. Он описал эту идею в математической форме. В основном, он находит разницу в интенсивности для смещения $(u, v)$ во всех направлениях. Это выражается следующим образом:
|
||||
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
E(u,v)= \\ =\sum_{x,y} w(x,y) [I(x+u,y+v) − I(x,y)]^2
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
где $w(x,y)$ - это оконная функция, $I(x+u,y+v)$ - смещённая интенсивность, $I(x,y)$ - интенсивность. Оконная функция представляет собой либо прямоугольное окно, либо окно Гаусса, которое дает вес пикселям под ним.
|
||||
|
||||
Мы должны максимизировать функцию $E(u,v)$ для обнаружения углов. Это означает, что мы должны максимизировать второй член. Применяя разложение в ряд Тейлора к приведенному выше уравнению и используя некоторые математические шаги, мы получаем окончательное уравнение вида:
|
||||
\begin{equation*}
|
||||
E(u,v)\approx [u,v] M \begin{bmatrix} u\\v \end{bmatrix}
|
||||
\end{equation*}
|
||||
где
|
||||
\begin{equation*}
|
||||
M = \sum_{x,y} w(x,y) \begin{bmatrix}
|
||||
I_xI_x & I_xI_y\\
|
||||
I_xI_y & I_yI_y
|
||||
\end{bmatrix}
|
||||
\end{equation*}
|
||||
|
||||
Здесь $I_x$ и $I_y$ — производные изображения в направлениях $x$ и $y$ соответственно. (Их можно найти с помощью функции \code{cv.Sobel()}).
|
||||
|
||||
Затем идет основная часть. Предварительные действия создали оценочную функцию, то есть, фактически, уравнение, которое определяет, может ли окно содержать угол или нет.
|
||||
\begin{equation*}
|
||||
R = det(M) - k(trace(M))^2
|
||||
\end{equation*}
|
||||
где
|
||||
|
||||
\begin{itemize}
|
||||
\item [] $det(M) = \lambda_1\lambda_2$
|
||||
\item [] $trace(М) = \lambda_1 + \lambda_2$
|
||||
\item [] $\lambda_1$ и $\lambda_2$ — собственные значения оператора M
|
||||
\end{itemize}
|
||||
Таким образом, величины этих собственных значений определяют, является ли область углом, краем или плоскостью.
|
||||
|
||||
\begin{itemize}
|
||||
\item Когда $|R|$ мал, что бывает при малых $\lambda_1$ и $\lambda_2$, область плоская.
|
||||
\item При $R < 0$, что бывает при $\lambda_1 \gg \lambda_2$ или наоборот, область является краевой.
|
||||
\item Когда $R$ велико, что происходит, когда $\lambda_1$ и $\lambda_2$ велики и $\lambda_1 \sim \lambda_2$, область представляет собой угол.
|
||||
\end{itemize}
|
||||
|
||||
Таким образом, результатом Harris Corner Detection является изображение в градациях серого с оценками. Указание корректных пороговых значений для таких оценок даёт углы изображения.
|
||||
\end{multicols}
|
||||
|
||||
\subsection{Детектирование углов Ши-Томаси} \label{appendix:shi-tomasi}
|
||||
\href{https://docs.opencv.org/3.4/d4/d8c/tutorial_py_shi_tomasi.html}{OpenCV: Документация}
|
||||
\begin{multicols}{2}
|
||||
В 1994, J. Shi и C. Tomasi немного изменили метод Харриса, что было отражено в их работе «Good Features to Track» которая показыват лучшие результаты, чем детектор углов Харриса. Оценочная функция в детекторе углов Харриса дана как:
|
||||
|
||||
\begin{equation*}
|
||||
R = \lambda_1\lambda_2 - k(\lambda_1+\lambda_2)^2
|
||||
\end{equation*}
|
||||
|
||||
Вместо этого, Ши-Томаси предложили:
|
||||
\begin{equation*}
|
||||
R = \min(\lambda_1, \lambda_2)
|
||||
\end{equation*}
|
||||
|
||||
Если значение больше порогового, область считается углом.
|
||||
\end{multicols}
|
||||
|
||||
\subsection{Метод вычисления Лукаса-Канаде} \label{appendix:lucas-kanade}
|
||||
\href{http://cecas.clemson.edu/~stb/klt/lucas_bruce_d_1981_1.pdf}{Оригинальная статья}
|
||||
|
||||
\href{https://en.wikipedia.org/wiki/Lucas–Kanade_method}{Wikipedia}
|
||||
\begin{multicols}{2}
|
||||
В компьютерном зрении метод Лукаса-Канаде является широко используемым дифференциальным методом для оценки оптического потока. Он предполагает, что поток практически постоянный в локальной окрестности рассматриваемого пикселя, и решает основные уравнения оптического потока для всех пикселей в этой окрестности по критерию наименьших квадратов. Комбинируя информацию от нескольких соседних пикселей, метод Лукаса-Канаде часто может разрешить присущую обработке оптического потока неоднозначность. Он также менее чувствителен к шуму изображения, чем точечные методы. С другой стороны, поскольку это чисто локальный метод, он не может предоставить информацию о потоках внутри однородных областей изображения.
|
||||
|
||||
Метод Лукаса–Канаде предполагает, что смещение содержимого изображения между двумя близкими моментами (кадрами) мал\'{о} и примерно постоянно в окрестности рассматриваемой точки $p$. Таким образом, можно предположить, что уравнение оптического потока выполняется для всех пикселей в пределах окна с центром в точке $p$. А именно, локальный вектор потока изображения (скорости) $(V_x, V_y)$ должен удовлетворять
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
I_{x}(q_{1})V_{x}+I_{y}(q_{1})V_{y}=-I_{t}(q_{1})\\
|
||||
I_{x}(q_{2})V_{x}+I_{y}(q_{2})V_{y}=-I_{t}(q_{2})\\
|
||||
\vdots \\
|
||||
I_{x}(q_{n})V_{x}+I_{y}(q_{n})V_{y}=-I_{t}(q_{n})\\
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
где
|
||||
|
||||
$q_1, q_2, ..., q_n$ — это пиксели внутри окна, а
|
||||
$I_{x}(q_{i}), I_{y}(q_{i}), I_{t}(q_{i})$ — частные производные изображения $I$ относительно положения $х, у$ и времени $t$, оценённые в точке $q_{i}$ и в настоящее время.
|
||||
|
||||
Эти уравнения можно записать в матричной форме $A_v = b$, где
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
A=
|
||||
\begin{bmatrix}
|
||||
I_{x}(q_{1}) & I_{y}(q_{1}) \\
|
||||
I_{x}(q_{2}) & I_{y}(q_{2}) \\
|
||||
\vdots & \vdots \\
|
||||
I_{x}(q_{n}) & I_{y}(q_{n})
|
||||
\end{bmatrix}
|
||||
v=
|
||||
\begin{bmatrix}
|
||||
V_x \\ V_y
|
||||
\end{bmatrix} \\
|
||||
b =
|
||||
\begin{bmatrix}
|
||||
-I_{t}(q_{1}) \\
|
||||
-I_{t}(q_{2}) \\
|
||||
\vdots \\
|
||||
-I_{t}(q_{n})
|
||||
\end{bmatrix}
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
|
||||
В этой системе больше уравнений, чем неизвестных, и поэтому она обычно переопределена, то есть, метод Лукаса–Канаде позволяет получить компромиссное решение по принципу наименьших квадратов. А именно, решает
|
||||
$2 \times 2$ систему:
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
A^{T}Av=A^{T}b \text{или}\\
|
||||
v = (A^{T}A)^{-1}A^{T}b
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
где
|
||||
$A^{T}$ - транспонированная матрица $A$. То есть он вычисляет
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
\begin{bmatrix}
|
||||
V_x \\ V_y
|
||||
\end{bmatrix} =
|
||||
\begin{bmatrix}
|
||||
\sum_i^nI_x(q_i)^2 & \sum_i^n I_x(q_i)I_y(q_i)\\
|
||||
\sum_i^nI_y(q_i)I_x(q_i) & \sum_i^n I_y(q_i)^2
|
||||
\end{bmatrix}^{-1}\\
|
||||
\begin{bmatrix}
|
||||
\sum_i^n I_x(q_i)I_t(q_i)\\
|
||||
\sum_i^n I_y(q_i)I_t(q_i)
|
||||
\end{bmatrix}
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
где центральная матрица в уравнении является обратной матрицей. Матрицу $A^TA$ часто называют структурным тензором изображения в точке $p$.
|
||||
|
||||
Приведенное выше решение методом наименьших квадратов придает одинаковую важность всем $n$ пикселям $q_{i}$ в окне. На практике обычно лучше придавать больший вес пикселям, расположенным ближе к центральному пикселю $p$. Для этого используется взвешенная версия уравнения наименьших квадратов,
|
||||
\[А^{Т}WАv = А^{Т}Wb\]
|
||||
|
||||
или же
|
||||
\[v = (A ^ {T} WA) ^ {- 1} A^{T} Wb\]
|
||||
|
||||
где $W$ — диагональная матрица $n\times n$, содержащая веса $W_{ii}=w_{i}$, которые должны быть присвоены уравнению пикселя $q_{i}$. То есть вычисляет
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
\begin{bmatrix}
|
||||
V_x \\ V_y
|
||||
\end{bmatrix} = \\
|
||||
\begin{bmatrix}
|
||||
\sum_iw_iI_x(q_i)^2 & \sum_i w_iI_x(q_i)I_y(q_i)\\
|
||||
\sum_iw_iI_x(q_i)I_y(q_i) & \sum_i w_iI_y(q_i)^2
|
||||
\end{bmatrix}^{-1}\\
|
||||
\begin{bmatrix}
|
||||
\sum_i w_iI_x(q_i)I_t(q_i)\\
|
||||
\sum_i w_iI_y(q_i)I_t(q_i)
|
||||
\end{bmatrix}
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
|
||||
Вес $w_{i}$ обычно устанавливается как функция Гаусса от расстояния между $q_{i}$ и $p$.
|
||||
|
||||
\paragraph{Условия использования и методы}
|
||||
Чтобы уравнение $A^{T}Av=A^{T}b$ было разрешимо, $A^{T}A$ должно быть обратимым, или собственные значения $A^{T}A$ должны удовлетворять $\lambda _{1} \geq \lambda _{2} > 0$. Чтобы избежать проблем с шумом, обычно требуется, чтобы $\lambda_{2}$ не было слишком маленьким. Кроме того, если $\lambda_{1}/\lambda_{2}$ слишком велико, это означает, что точка $p$ находится на ребре, и этот метод страдает от проблемы с апертурой. Таким образом, для правильной работы этого метода необходимо, чтобы $\lambda_{1} и \lambda_{2}$ были достаточно большими и имели одинаковую магнитуду. Это условие также относится к обнаружению углов. Это наблюдение показывает, что можно легко определить, какой пиксель подходит для работы метода Лукаса-Канаде, проверив одно изображение.
|
||||
|
||||
Одним из основных предположений для этого метода является то, что движение небольшое (например, менее 1 пикселя между двумя изображениями). Если движение велико, один из методов состоит в том, чтобы сначала уменьшить разрешение изображений, а затем применить метод Лукаса-Канаде. Чтобы добиться отслеживания движения с помощью этого метода, его можно итеративно применять к вектору потока и пересчитывать до тех пор, пока не будет достигнут некоторый порог, близкий к нулю, после чего можно предположить, что окна изображения очень близки по подобию (движутся достаточно медленно). Делая это для каждого последовательного окна отслеживания, точка может отслеживаться на нескольких изображениях, пока она либо не будет скрыта, либо не выйдет за пределы кадра.
|
||||
\end{multicols}
|
||||
|
||||
\subsection{Отслеживание движущихся объектов с регенерацией характерных точек объекта} \label{appendix:alfimtsev-lychkov}
|
||||
\begin{multicols}{2}
|
||||
\textbf{Аннотация. Эта статья посвящена отслеживанию движущихся объектов в видео, основанному на технике разреженного оптического потока. Текущие оптические методы отслеживания потока страдают от потери характерных точек. Мы расширили существующий метод отслеживания разреженного оптического потока с помощью новой функции автоматического восстановления характерных точек, использующей принцип биологической регенерации. Кроме того, мы улучшили метод отслеживания для работы с преобразованиями вращения и масштабирования объекта. Мы применили улучшенный метод отслеживания к реальному видео и заметили приемлемую производительность отслеживания. Наш эксперимент показал, что предложенный метод слежения с восстановлением характерных точек обеспечивает более высокую точность отслеживания, чем оригинальный метод отслеживания без восстановления характерных точек когда движущийся объект частично закрыт препятствием.
|
||||
Ключевые слова - отслеживание движущихся объектов, видеопоток, перекрытие объекта, обнаружение характерных точек, биологическая регенерация.}
|
||||
|
||||
\paragraph{1. Введение}
|
||||
Автоматическое отслеживание движущихся объектов на видео — важная задача, возникающая в таких областях, как безопасность, оборона, робототехника и др. Она заключается в вычислении положения движущегося объекта в последовательности видеокадров по заданному его положению в первом видеокадре последовательности. Автоматическое отслеживание движущихся объектов — сложная задача для видео с окклюзией (перекрытием) объектов и плохим освещением.
|
||||
|
||||
\paragraph{2. Обзор литературы}
|
||||
Можно выделить пять основных подходов к отслеживанию движущихся объектов: отслеживание блобов, отслеживание на основе контуров, отслеживание оптического потока, отслеживание на основе моделей и отслеживание нейронной сети. Отслеживание блоба использует методы вычитания фона и не подходит для видео, записанных движущейся камерой. Отслеживание нейронной сети требует больших обучающих наборов данных, которые можно найти только для определенных категорий объектов и только для обычных видео. Трудно подготовить большие обучающие наборы данных для видеороликов, производимых инфракрасными камерами или электронными оптическими преобразователями приборов ночного видения. Отслеживание на основе контуров, отслеживание на основе 3D-моделей и отслеживание плотного оптического потока требуют больших вычислительных мощностей, поэтому эти методы не подходят для приложений реального времени. В этой работе мы улучшаем существующий метод отслеживания разреженного оптического потока, основанный на оптическом потоке Лукаса-Канаде, который устраняет необходимость обучения и подходит для приложений в реальном времени.
|
||||
|
||||
\paragraph{3. Постановка задачи}
|
||||
Отслеживание разреженного оптического потока заключается в обнаружении характерных точек в видеокадре и последующем отслеживании обнаруженных характерных точек в серии видеокадров. Из-за несовершенства алгоритмов отслеживания некоторые характерные точки могут быть потеряны. Первоначально в контуре движущегося объекта можно обнаружить несколько характерных точек. Значительная часть пятна изображения вокруг такой характерной точки приходится на фон. Во время отслеживания, эта характерная точка может покинуть область объекта и войти в область фона, что вносит неопределенность в отслеживание движущегося объекта. Кроме того, непрозрачные препятствия могут скрывать некоторые части движущегося объекта и затруднять его правильное отслеживание. Для повышения точности слежения предлагается метод автоматического восстановления потерянных характерных точек путем обнаружения новых характерных точек в пределах области объекта. Основная идея метода восстановления основана на использовании принципов биологической регенерации.
|
||||
|
||||
\paragraph{4. Восстановление характерных точек, основанное на биологической регенерации}
|
||||
Регенерация – это особая способность биологического организма восстанавливать утраченные части своего тела. Рассмотрим три известных принципа биологической регенерации: эпиморфоз, моральфаллакс и эндоморфоз. Эпиморфоз заключается в редукции тканей тела, прилежащих к повреждённой поверхности, разрастании клеток и их последующей дифференцировке. Моральфалакс во многом похож на эпиморфоз, за исключением того, что остальные клетки организма подлежат перестройке. Эндоморфоз заключается в восстановлении поврежденной массы органа за счет деления и гипертрофии клеток.
|
||||
|
||||
Вышеупомянутые принципы регенерации могут быть адаптированы для восстановления потерянных характерных точек в задаче отслеживания объектов следующим образом. Эпиморфозы сохраняют исходные геометрические параметры движущихся объектов. Основным критерием для присвоения характерной точки движущемуся объекту является расстояние от этой характерной точки до ближайшего центра объекта. Основная идея моральфаллакса во многом похожа на эпиморфоз, за исключением того, что осуществляется дальнейшая оптимизация, чтобы уменьшить количество плохо отслеживаемых характерных точек. Эндоморфоз учитывает количество характерных точек, которые в настоящее время отслеживаются в ограничивающей рамке объекта.
|
||||
|
||||
В данной работе мы предлагаем использовать эпиморфоз в качестве базового принципа восстановления характерных точек. Пользователь задает порог количества отслеживаемых характерных точек в качестве входного параметра метода. Характерные точки изображения отслеживаются в каждом видеокадре с использованием разреженного оптического потока Лукаса-Канаде, а ограничивающие рамки объектов вычисляются с помощью метода отслеживания движущихся объектов, представленного в следующем разделе. Когда количество характерных точек в ограничивающей рамке объекта уменьшится ниже заданного пользователем порога, новые характерные точки будут обнаружены следующим образом. Сначала мы применяем детектор характерных точек Ши-Томаси для обнаружения новых характерных точек в ограничивающей рамке объекта. Во-вторых, мы отбрасываем характерные точки, расположенные на расстоянии менее 5 пикселей от исходных характерных точек объекта, которые в настоящее время отслеживаются. Наконец, мы выбираем необходимое количество характерных точек, которые находятся ближе всего к центру ограничивающей рамки объекта в текущем видеокадре.
|
||||
|
||||
\paragraph{5. Метод отслеживания объекта в видео}
|
||||
Главная проблема отслеживания характерных точек на основе разреженного оптического потока состоит в миграции отдельных характерных точек из области изображения движущегося объекта в область фонового изображения, что вносит ошибки в результаты отслеживания. Чтобы добиться надежного отслеживания движущихся объектов, нам необходимо различать и отбрасывать потерянные характерные точки. Метод слежения за движущимися объектами на основе сети относительного движения позволяет сопоставлять наблюдаемые положения объектов в текущем видеокадре с траекториями объектов в последовательности видеокадров по их относительным смещениям. Для составления оптимального совпадения используется принцип максимального правдоподобия. Оригинальный метод слежения предполагает, что отдельный объект представлен одной характерной точкой в видеокадре, имеет дело только с поступательным движением и не учитывает вращение и масштабирование изображения объекта в кадре во время его движения. В этой работе мы предлагаем модификацию исходного метода отслеживания для работы с вращением и масштабированием объекта.
|
||||
|
||||
Входящие данные метода включают набор кадров $Z_t = \{z_t^k\}$ полученный с использованием техники оптического потока, где $t$ это индекс видеокадра, $k$ - индекс характерной точки, $z_t^k = [z_{ut}^k, z_{vt}^k]$ - вектор обзора с координатами $z_{ut}^k$ и $z_{vt}^k$.
|
||||
Текущее состояние отслеживаемых движущихся объектов представлено набором состояний $X_t = \{(x_t^i, h_t^i)\}$, где $t$ - индекс видеокадра, $i$ - индекс движущегося объекта ($i = 0$ означает фон), $x_t^i = [x_{ut}^i, x_{vt}^i]$ - вектор центров $i$-ых объектов внутри $t$-ого видеокадра, $h_t^i = [h_{ut}^i, h_{vt}^i]$ представляет размер границ распознанного $i$-го объекта.
|
||||
Для расчёта положения центра объекта и относительного положения различных характерных точек мы составляем относительную модель движения $R_t = \{ (m_j^i, n_j^i), \pi_i \}$, где $(m_j^i,n_j^i), j = 1 : 2N$ это список индексов соответствующих пар характерных точек для $i$-го объекта, $\pi_i$ обозначает индексы основной соответствующей пары характерных точек $(m_{πi}^i, n_{πi}^i)$ которая используется для отслеживания $i$-го объекта на $t$-ом видеокадре. Для начального видеокадра $t = 0$ список индексов объединяется с использованием случайной выборки $2N$ пар характерных точек из общего набора обнаруженных характерных точек.
|
||||
Затем мы сопоставляем характерные точки с движущимися объектами и находим основные опорные характерные точки объектов по принципу максимального правдоподобия:
|
||||
|
||||
\begin{equation}
|
||||
\begin{gathered}
|
||||
p(Z_t|X_t,R_{t-1}) = \\ = \max\limits_{A, \pi}\prod_{i,k} p(z_t^k|x_t^i,R_{t-1}^\pi)^{a^{i,k}}
|
||||
\end{gathered}
|
||||
\label{eq:likehood}
|
||||
\end{equation}
|
||||
|
||||
где $R_{t-1}$ это модель относительного движения для предыдущего видеокадра, $R_{t-1}^\pi$ это модель относительного движения с измененными индексами пар основных опорных точек всех объектов, $A = \{a^{i,k}\}$ и $a^{i,k} \in \{0, 1\}$ представляют совпадающие соответствия точек признаков объектам, $p(z_t^k|x_t^i,R_{t-1}^\pi)$ функция частичного совпадения.
|
||||
|
||||
Чтобы упростить проблему оптимизации возможно применить функцию логарифма к правой части (\hrf{eq:likehood}):
|
||||
\begin{equation}
|
||||
\begin{gathered}
|
||||
p(Z_t|X_t,R_{t-1}) \sim \\ \sim \max\limits_{A, \pi}\prod_{i,k} a^{i,k} \ln p(z_t^k|x_t^i,R_{t-1}^\pi)
|
||||
\end{gathered}
|
||||
\label{eq:likehood-ln}
|
||||
\end{equation}
|
||||
|
||||
Модель относительного движения настраивается следующим образом. Решение задачи оптимизации (\hrf{eq:likehood-ln}) дает оптимальные значения элементов матрицы $A$. Можно выбрать пару лучших опорных точек модели $R_{t–1}$ при условии глобального оптимума (\hrf{eq:likehood-ln}) и $(N – 1)$ лучших опорных точек при условии локального максимума правдоподобия для $i$-го объекта:
|
||||
|
||||
\begin{equation}
|
||||
\begin{gathered}
|
||||
\pi_{i\max} = \\ = \arg \max\limits_{A, \pi}\prod_{i,k} a^{i,k} \ln p(z_t^k|x_t^i,R_{t-1}^\pi)
|
||||
\end{gathered}
|
||||
\label{eq:likehood-ln-max}
|
||||
\end{equation}
|
||||
|
||||
Остальные $N$ пар выбираются методом случайной выборки из набора характерных точек $i$-го объекта в $t$-м видеокадре. Функция частичного правдоподобия представляется в виде
|
||||
|
||||
\begin{equation}
|
||||
p(z_t^k|x_t^i,R_{t-1}^\pi) = G(z_\tau^k, y_\tau^k)
|
||||
\label{eq:likehood-partial}
|
||||
\end{equation}
|
||||
|
||||
где $G$ - это двумерный Гауссиан
|
||||
|
||||
\begin{equation}
|
||||
\begin{gathered}
|
||||
G(v, v_0) = \\ = \exp \left\{ -\frac{1}{2}(v-v_0)^T C(v-v_0) \right\}
|
||||
\end{gathered}
|
||||
\label{eq:gaussian}
|
||||
\end{equation}
|
||||
|
||||
с ковариационной матрицей
|
||||
|
||||
\begin{equation}
|
||||
C=\begin{bmatrix}
|
||||
\sigma_u^2 & \sigma_u\sigma_v\\
|
||||
\sigma_u\sigma_v & \sigma_u^2
|
||||
\end{bmatrix}
|
||||
\label{eq:covariance-matrix}
|
||||
\end{equation}
|
||||
|
||||
и стандартными отклонениями для различных координат
|
||||
|
||||
\begin{equation}
|
||||
3\sigma_u = \frac{1}{2}h_{u\tau}^i, 3\sigma_v = \frac{1}{2}h_{v\tau}^i
|
||||
\label{eq:coord-deviations}
|
||||
\end{equation}
|
||||
|
||||
которые зависят от размера $i$-го объекта и времени $\tau$ обнаружения $k$-й характерной точки.
|
||||
|
||||
$y_\tau^k = [y_{u\tau}^k, y_{v\tau}^k]^T$ в (\hrf{eq:likehood-partial}) - это прогнозируемое положение $k$-й характерной точки в $\tau$-м видеокадре, предполагая, что $k$-я характерная точка назначена $i$-му объекту, а модель относительного движения $i$-й характерной точки объекта представляет собой модель аффинного преобразования.
|
||||
|
||||
Матрица аффинного преобразования $M_{ti} \in R^{2\times3}$ для $i$-го движущегося объекта определяется использованием следующей системой уравнений
|
||||
|
||||
\begin{equation}
|
||||
\begin{cases}
|
||||
[z_{u\tau}^{p1} z_{v\tau}^{p1}]^Τ = M_{ti} \cdot [z_{u\tau}^{p1} z_{v\tau}^{p1} 1]^Τ\\
|
||||
[z_{u\tau}^{p2} z_{v\tau}^{p2}]^Τ = M_{ti} \cdot [z_{u\tau}^{p2} z_{v\tau}^{p2} 1]^Τ,\\
|
||||
[z_{u\tau}^{p3} z_{v\tau}^{p3}]^Τ = M_{ti} \cdot [z_{u\tau}^{p3} z_{v\tau}^{p3} 1]^Τ
|
||||
\end{cases}
|
||||
\label{eq:affine-matrix}
|
||||
\end{equation}
|
||||
где $p1, p2, p3$ это индексы характерных точек, присвоенных $i$-му движущемуся объекту.
|
||||
|
||||
Предсказанное положение $k$-й характерной точки в $\tau$-м видеокадре вычисляется с использованием матрицы аффинного преобразования $M_{ti}$.
|
||||
\begin{equation}
|
||||
y_{k\tau} = M_{ti} \cdot [z_{u\tau}^{k} z_{v\tau}^{k} 1]^Τ
|
||||
\label{eq:affine-equation}
|
||||
\end{equation}
|
||||
Характерная точка, переместившаяся из области движущегося объекта в фоновую область, уйдет далеко от движущегося объекта. Её функция частичного правдоподобия (\hrf{eq:likehood-partial}) принимает б\'{о}льшие значения, если характерная точка отнесена к фону, и меньшие значения, если характерная точка отнесена к движущемуся объекту. Таким образом, оптимальное решение для (\hrf{eq:likehood-ln}) дает нам разумное соответствие точек признаков движущимся объектам или фону.
|
||||
|
||||
\paragraph{6. Устройство эксперимента и результаты}
|
||||
Мы записали оригинальное видео с частотой кадров 25 кадров в секунду, продолжительностью 50 секунд и разрешением 720$\times$576 пикселей, которое представляет дорожное движение на дороге. Мы использовали предложенный метод отслеживания объектов для извлечения опорных траекторий для 14 движущихся автомобилей из исходного видео. Начальные точки траектории задавались вручную. Для имитации перекрытия движущихся объектов препятствием мы нанесли на все видеокадры 4 вертикальные серые полосы (каждая полоса шириной 12 пикселей), получив модифицированное видео. Мы применили предложенный метод отслеживания объектов к модифицированному видео, таким образом, получив результирующие траектории для 14 движущихся автомобилей в модифицированном видео для двух случаев. В первом случае восстановление характерных точек не производилось, а во втором случае восстановление характерных точек осуществлялось по предложенному способу регенерации. Координатам начальной точки траектории присваивались те же значения, что и для соответствующих опорных траекторий. Затем мы сопоставили полученные траектории с эталонными траекториями и рассчитали две метрики производительности: процент успешно отслеженных объектов и отклонение слежения. Движущийся объект считался успешно отслеженным, если расстояние его положения на результирующей траектории от его положения на опорной траектории не превышает заданного максимального порога расстояния для каждого видеокадра. Порог максимального расстояния задавался вручную в процентах от размера ограничивающей рамки объекта. Процент успешно отслеженных объектов рассчитывался как количество успешно отслеженных объектов, делённый на общее количество опорных траекторий. Отклонение слежения вычислялось как среднее стандартное отклонение полученных траекторий от эталонных траекторий среди всех успешно отслеженных объектов. Количество отслеживаемых характерных точек объекта было установлено вручную равным 10. Результаты эксперимента представлены в таблице в оригинале статьи. Когда пороговое значение максимального расстояния устанавливалось равным 0,5 размера ограничивающей рамки объекта, отслеживание с восстановлением потерянных характерных точек обеспечивало меньшее отклонение отслеживания, чем отслеживание без восстановления потерянных характерных точек. Когда порог максимального расстояния устанавливался на 0,75 размера ограничивающей рамки объекта, отслеживание с восстановлением потерянных характерных точек обеспечивало более высокий процент успешно отслеженных объектов, чем отслеживание без восстановления потерянных характерных точек.
|
||||
|
||||
\paragraph{7. Выводы}
|
||||
В данной работе мы расширили существующий метод отслеживания движущихся объектов в видеороликах функцией автоматического восстановления потерянных характерных точек, основанной на принципе биологической регенерации. Эксперимент, проведенный на реальном видео, показал, что автоматическое восстановление потерянных характерных точек позволяет повысить точность слежения в случае перекрытия движущегося объекта неподвижным препятствием. Использование аффинной модели движения позволяет иметь дело с поворотными и масштабными преобразованиями движущегося объекта при отслеживании.
|
||||
\end{multicols}
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,510 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{2}{Распознавание объекта по цвету}{Цифровая обработка изображений}{}{Большаков В.Э.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\sloppy
|
||||
\section{Цель}
|
||||
Основной целью лабораторной работы является изучение методов распознания объекта по цвету с помощью библиотеки цифровой обработки изображений scikit-image, а также разработка программы распознавания блюд на подносе.
|
||||
\section{Задание}
|
||||
\begin{itemize}
|
||||
\item Подготовить выборку 10 цветных цифровых изображений блюд бауманской столовой (по аналогии с примером).
|
||||
\item В среде Spyder (сборка Anaconda) на языке Python (3.5 и старше) создать проект и подключить библиотеку scikit-image.
|
||||
\item Из л.р. 1 взять модуль загрузки цветного цифрового изображения и модуль обработки пикселей.
|
||||
\item Запрограммировать формулу перевода цветного цифрового изображения в цветовое пространство в соответствии с вариантом (В1: RGB, В2: HSV, В3: CMYK, В4: YUV, В5: Hough Circle+HSV, В6: Hough Circle +HSL)
|
||||
\item Создать классификацию блюд из цифровых изображений.
|
||||
\item Для каждого блюда определить цветовые характеристики. Задать распределение значений каждого цвета.
|
||||
\item Провести эксперимент по распознаванию блюд с визуализацией результатов.
|
||||
\end{itemize}
|
||||
|
||||
Вариант (по номеру в списке группы) 9, то есть цветовое пространство CMYK. Для распознавания разрешается использовать только цвет.
|
||||
\section{Теоретическая часть}
|
||||
\subsection{Цветовое пространство CMYK}
|
||||
Система CMYK создана и используется для типографической печати. Аббревиатура \textbf{CMYK} означает названия основных красок, использующихся для четырехцветной печати: голубой (Сyan), пурпурный (Мagenta) и жёлтый (Yellow). Буквой К обозначают черную краску (BlacK), позволяющую добиться насыщенного черного цвета при печати. Используется последняя, а не первая буква слова, чтобы не путать CMYK Black и RGB Blue. На рисунке \hrf{pic:cmyk-rgb} показана цветовая палитра CMYK вместе с RGB.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{02-dip-lab02-cmyk-rgb.png} \caption{Цветовые пространства CMYK и RGB}
|
||||
\label{pic:cmyk-rgb}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Особенность формирования цвета}
|
||||
Каждое из чисел, определяющее цвет в CMYK, представляет собой процент краски данного цвета, составляющей цветовую комбинацию. Например, для получения тёмно-оранжевого цвета следует смешать 30\% голубой краски, 45\% пурпурной краски, 80\% жёлтой краски и 5\% чёрной. Это можно обозначить следующим образом: CMYK(30/45/80/5).
|
||||
|
||||
\subsection{Перевод из RGB в CMYK}
|
||||
Для того, чтобы перевести пиксель RGB в пиксель CMYK можно применить формулу, описанную на языке Java и представленную в таблице \hrf{code:rgb-cmyk}.
|
||||
\begin{lstlisting}[language=Java, style=JCodeStyle, caption={Формула перевода из RGB в CMYK}, label={code:rgb-cmyk}]
|
||||
int black = Math.min(Math.min(255 - red, 255 - green), 255 - blue);
|
||||
if (black!=255) {
|
||||
int cyan = (255-red-black)/(255-black);
|
||||
int magenta = (255-green-black)/(255-black);
|
||||
int yellow = (255-blue-black)/(255-black);
|
||||
return new int[] {cyan,magenta,yellow,black};
|
||||
} else {
|
||||
int cyan = 255 - red;
|
||||
int magenta = 255 - green;
|
||||
int yellow = 255 - blue;
|
||||
return new int[] {cyan,magenta,yellow,black};
|
||||
}
|
||||
\end{lstlisting}
|
||||
Пример полученного изображения с использованием преобразования пикселей представлен на рисунке \hrf{pic:trans}. При преобразовании таким методом исходного изображения (\hrf{pic:trans-rgb}) будет получено изображение не естественных цветов (\hrf{pic:trans-cmyk}).
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-lab02-trans-rgb.png}
|
||||
\caption{Исходное изображение в пространстве RGB}
|
||||
\label{pic:trans-rgb}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-lab02-trans-cmyk.png}
|
||||
\caption{Преобразованное изображение CMYK}
|
||||
\label{pic:trans-cmyk}
|
||||
\end{subfigure}
|
||||
\caption{Пример попиксельного перевода изображения}
|
||||
\label{pic:trans}
|
||||
\end{figure}
|
||||
|
||||
Данные результаты не являются правильными. Для более точного преобразования следует использовать ICC профили, описывающие как должен отображаться цвет на мониторе и бумаге.
|
||||
|
||||
\subsection{Цветовое профилирование}
|
||||
Для достоверного управления цветом необходимы ICC-совместимые профили всех цветовоспроизводящих устройств. Например, без точного профиля сканера хорошо отсканированное изображение может отображаться в другой программе неправильно из-за различий между алгоритмами отображения, используемыми сканером и программой. Недостоверность цветопередачи может привести к внесению в хорошее изображение ненужных и, возможно, вредных "улучшений". При наличии точного профиля программа, импортирующая изображение, способна скорректировать разницу с устройством и воспроизвести достоверные цвета отсканированного изображения.
|
||||
|
||||
Профили документов описывают конкретное цветовое пространство, используемое в документе. Путем назначения профиля, или пометки документа профилем, приложение определяет фактические цвета документа. Например, запись R = 127, G = 12, B = 107 — это просто набор чисел, которые разные устройства будут отображать по-разному. Однако при пометке цветовым пространством Adobe RGB эти числа определяют фактический цвет или длину световой волны. На рисунке \hrf{pic:icc-profile} представлена назначение профилей ICC.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=5cm]{02-dip-lab02-icc-profile.png}
|
||||
\caption{Пример использования профилей ICC}
|
||||
\label{pic:icc-profile}
|
||||
\end{figure}
|
||||
|
||||
При использовании профилей преобразованные изображения получаются более правдоподобными. На рисунке \hrf{pic:icc-trans} представлено такое преобразование, \hrf{pic:icc-trans-rgb} пространство RGB, \hrf{pic:icc-trans-cmyk} пространство CMYK.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-lab02-trans-rgb.png}
|
||||
\caption{Исходное изображение в пространстве RGB}
|
||||
\label{pic:icc-trans-rgb}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-lab02-trans-rgb.png}
|
||||
\caption{Преобразованное изображение CMYK}
|
||||
\label{pic:icc-trans-cmyk}
|
||||
\end{subfigure}
|
||||
\caption{Пример преобразования с использованием профилей}
|
||||
\label{pic:icc-trans}
|
||||
\end{figure}
|
||||
|
||||
\section{Практическая часть}
|
||||
\subsection{Состав исполняемых файлов}
|
||||
Программа по распознаванию изображений состоит из двух скриптов:
|
||||
\begin{itemize}
|
||||
\item основного скрипта для выполнения программы \code{main.py};
|
||||
\item скрипта для обработки изображений \code{colorFoodView.py}.
|
||||
\end{itemize}
|
||||
|
||||
Основной скрипт для тренировки принимает 2 аргумента для запуска:
|
||||
\begin{itemize}
|
||||
\item \code{-c}, файл конфигурации программы в формате json;
|
||||
\item \code{-f}, файл описывающий блюда и их цвета.
|
||||
\end{itemize}
|
||||
|
||||
Например, скрипт для запуска тренировки может выглядеть следующим образом:
|
||||
\begin{lstlisting}[style=CCodeStyle]
|
||||
main.py -c "./configs.json" -f "./foods.json"
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Конфигурационные файлы}
|
||||
Для корректной работы программы, ей необходимо передать два файла в формате json:
|
||||
\begin{enumerate}
|
||||
\item файл конфигурации (далее \code{config.json});
|
||||
\item файл описания блюд (далее \code{food.json}).
|
||||
\end{enumerate}
|
||||
|
||||
Параметры файла \code{config.json} представлены в таблице \hrf{table:config-json}, а пример заполненного файла в листинге \hrf{code:conf-json}.
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|l|p{100mm}|}
|
||||
\hline
|
||||
Наименование параметра & Описание \\ \hline
|
||||
\code{RGB_profile} & Путь до профиля ICC RGB описывающего цветовое пространство исходного изображения \\ \hline
|
||||
\code{CMYK_profile} & Путь до профиля ICC CMYK в чье цветовое пространство должно быть переведено изображение \\ \hline
|
||||
\code{Path_to_food} & Путь до папки с изображениями \\ \hline
|
||||
\code{Delta_for_color} & Процент погрешности для пикселей \\ \hline
|
||||
\code{Color_swap} & Цвет в формате CMYK в который необходимо преобразовать найденные пиксели \\ \hline
|
||||
\code{Mode} & Режим работы программы. Если режим работы Test, то в консоль будет выводиться количество найденных пикселей для искомого блюда\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Параметры конфигурации}
|
||||
\label{table:config-json}
|
||||
\end{table}
|
||||
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle, caption={Пример настроек параметров в программе}, label={code:conf-json}]
|
||||
{
|
||||
"RGB_profile": "./AdobeICCProfiles/RGB/AdobeRGB1998.icc",
|
||||
"CMYK_profile": "./AdobeICCProfiles/CMYK/WebCoatedSWOP2006Grade5.icc",
|
||||
"Path_to_food": "./WorkFood",
|
||||
"Delta_for_color": 5,
|
||||
"Color_swap": [100, 78, 0, 0],
|
||||
"Mode": "Product"
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Параметры файла \code{food.json} представлены в таблице \hrf{table:food-json}, а пример заполненного файла в листинге \hrf{code:food-json}. Файл описывает список блюд, а именно параметры каждого из элементов списка.
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|l|p{100mm}|}
|
||||
\hline
|
||||
Наименование параметра & Описание \\ \hline
|
||||
Name & Наименование блюда \\ \hline
|
||||
CMYK & Пиксели которые описывают данное блюдо \\ \hline
|
||||
Count & Минимальное количество пикселей, которое должно быть у изображения для того, чтобы можно было говорить о том, что на изображении присутствует искомое блюдо. Данное значение можно получить в тестовом режиме \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Параметры конфигурации}
|
||||
\label{table:food-json}
|
||||
\end{table}
|
||||
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle, caption={Пример настроек параметров в программе}, label={code:food-json}]
|
||||
{
|
||||
"Foods": [
|
||||
{
|
||||
"Name": "Банан в шоколаде",
|
||||
"CMYK": [
|
||||
{ "C": 23, "M": 29, "Y": 44, "K": 7 },
|
||||
{ "C": 29, "M": 40, "Y": 57, "K": 11 },
|
||||
{ "C": 34, "M": 61, "Y": 63, "K": 40 }
|
||||
],
|
||||
"Count": 2000
|
||||
},
|
||||
{
|
||||
"Name": "Сосиска",
|
||||
"CMYK": [
|
||||
{ "C": 27, "M": 65, "Y": 76, "K": 25 },
|
||||
{ "C": 14, "M": 47, "Y": 67, "K": 3 },
|
||||
{ "C": 24, "M": 65, "Y": 85, "K": 20 },
|
||||
{ "C": 28, "M": 83, "Y": 99, "K": 30 }
|
||||
],
|
||||
"Count": 9000
|
||||
},
|
||||
//...
|
||||
]
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Описание алгоритма работы программы}
|
||||
Алгоритм работы основной программы заключается в загрузке и настройки конфигурации и передаче их в скрипт обработки изображения. После выполнения поиска блюд и перед началом нового цикла работа можно скорректировать \code{json} файлы конфигурации и изменения будут применены без необходимости перезапуска программы.
|
||||
В скрипте обработки изображения используется следующий алгоритм работы:
|
||||
\begin{itemize}
|
||||
\item преобразовать все изображения в цветовое пространство, описанное профилем CMYK;
|
||||
\item для каждого изображения найти пиксели из выбранного блюда;
|
||||
\item если пиксель найден, то его цвет меняется на цвет, заданный в настройках;
|
||||
\item проверяется количество найденных пикселей, если их меньше порогового значения, то изображение отбрасывается;
|
||||
\item изображения, прошедшие проверку, возвращаются в основную программу для дальнейшей работы.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Выборка для тестирования}
|
||||
Для тестирования была подготовлена выборка из десяти подносов с едой. Каждая картинка была приведена к разрешению 400х300 пикселей. Изначальный размер изображений (более 4000х3000 пикселей) не позволяет добиться приемлемых результатов с использованием только цвета как характеристики для поиска изображений на фото. На рисунке \hrf{pic:food-src} представлена подготовленная для работы выборка.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb1.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb2.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb3.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb4.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb5.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb6.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb7.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb8.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb9.jpg}
|
||||
\includegraphics[width=3cm]{01-dip-lab02-rgb10.jpg}
|
||||
\caption{Исходная выборка изображений}
|
||||
\label{pic:food-src}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Подготовка данных}
|
||||
Для анализа изображений на предмет присутствия искомых пикселей они должны быть правильно заданы. Для этого используется скрипт \code{converter.py} преобразующий рабочее изображение в пространство CMYK. В дальнейшем с помощью дополнительного инструментария\footnote{онлайн пикер цвета https://www.ginifab.com/feeds/pms/color\_picker\_from\_image.php}, возможно узнать цвет пикселей в пространстве CMYK и внести в \code{food.json}.
|
||||
|
||||
\section{Результат работы}
|
||||
\subsection{Листинг}
|
||||
Исходный код скриптов \code{main.py}, \code{colorFoodView.py} и \code{converter.py} представлены в приложениях \hrf{app:main}, \hrf{app:find} и \hrf{app:conv} соответственно.
|
||||
|
||||
\subsection{Интерфейс и измерения}
|
||||
Программа использует терминальный текстовый интерфейс для взаимодействия с пользователем. На основе содержания \code{food.json} строятся возможные варианты выбора в основном меню. Предусмотрен контроль ошибок ввода. В результате измерений программа вернет изображения где, по её мнению, присутствуют искомые продукты. Найденные пиксели будут закрашены в заданный в конфигурации цвет. Результат работы для поиска яичницы приведен на рисунке \hrf{pic:result}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{01-dip-lab02-result.png}
|
||||
\caption{Результат работы программы}
|
||||
\label{pic:result}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Ошибки}
|
||||
В ходе вычислений программа допускает некоторое количество ошибок. Чем качественнее изображение, тем больше шансов что искомый пиксель будет присутствовать на изображении в неожиданных местах. Рабочая выборка подверглась минимальной предварительной обработке и часто в искомую область попадают объекты, не связанные с продуктами, такие как стол или поднос. В таблице \hrf{table:errors} представлены ошибки первого и второго рода для измерений.
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{||r|c|c||}
|
||||
\hline
|
||||
\multirow{2}{*}{Результаты} & \multicolumn{2}{c|}{Верная гипотеза} \\
|
||||
\cline{2-3}
|
||||
& H0 & H1 \\
|
||||
\hline
|
||||
H0 & 27 & 36 \\
|
||||
\hline
|
||||
H1 & 0 & 524 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Ошибка первого и второго рода}
|
||||
\label{table:errors}
|
||||
\end{table}
|
||||
\begin{itemize}
|
||||
\item [] Ошибка первого рода: $0\%$
|
||||
\item [] Ошибка второго рода: $36 / 524 * 200 = 7\%$
|
||||
\end{itemize}
|
||||
Данные результаты легко объяснить. Коэффициенты для срабатывания определения блюда настроены таким образом, чтобы находить блюдо в наборе. И программа хорошо справляется с этой задачей. Ошибки второго рода могут возникнуть, когда цвет блюда очень общий для изображения и срабатывает в нем во многих местах. Таких ситуаций не много, однако они имеют место быть. Основная масса ошибок второго рода отсекаются настраиваемым коэффициентом для каждого блюда.
|
||||
|
||||
\section{Заключение}
|
||||
В ходе выполнения задания были изучены методы по обработке изображения и работы с цветом. Исходя из результатов тестирования можно сделать вывод, что использование только цвета для поиска объектов на картинке не является достаточным, а подготовке рабочей выборки нужно уделять большое внимание. Разный источник света и разные условия сьемки сильно изменяют цвета, которые можно использовать для идентификации объектов.
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Asbuk{subsection}}
|
||||
|
||||
\subsection{Основная программа}
|
||||
\label{app:main}
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
import argparse
|
||||
|
||||
# Парсим аргументы вызова скрипта
|
||||
import codecs
|
||||
import json
|
||||
import sys
|
||||
|
||||
from ColorFoodView import find_food
|
||||
|
||||
|
||||
def create_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-c', '--configs')
|
||||
parser.add_argument('-f', '--foods')
|
||||
return parser
|
||||
|
||||
|
||||
def menu(foods):
|
||||
print("Допустимый выбор:")
|
||||
print("0 : Выход")
|
||||
i = 1
|
||||
for food in foods["Foods"]:
|
||||
print(i, ":", food["Name"])
|
||||
i += 1
|
||||
print("Введите команду:")
|
||||
i -= 1
|
||||
while 1:
|
||||
try:
|
||||
chose = int(input())
|
||||
if 0 > chose or chose > i:
|
||||
print("Данной команды не существует. Выберите из предложенного набора и попробуйте еще раз.")
|
||||
continue
|
||||
return chose
|
||||
except:
|
||||
print("Необходимо ввести число соответсвующее вашему выбору. Попробуйте еще раз")
|
||||
|
||||
|
||||
# поиск продуктов
|
||||
def food_name(foods, chose):
|
||||
return foods["Foods"][chose - 1]
|
||||
|
||||
|
||||
namespace = create_parser().parse_args(sys.argv[1:])
|
||||
|
||||
while 1:
|
||||
# получение конфигурационных данных
|
||||
configs = json.loads(codecs.open(namespace.configs, 'r', encoding='utf-8').read())
|
||||
# получение данных для справочника продуктов
|
||||
foods = json.loads(codecs.open(namespace.foods, 'r', encoding='utf-8').read())
|
||||
# меню выбора
|
||||
chose = menu(foods)
|
||||
if chose == 0:
|
||||
break
|
||||
# запрос на поиск продуктов
|
||||
images_food = find_food(configs, food_name(foods, chose))
|
||||
for image in images_food:
|
||||
image.show()
|
||||
print("Нажмите любую кнопку чтобы продолжить.")
|
||||
input()
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Поиск объектов по цвету}
|
||||
\label{app:find}
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
import os
|
||||
|
||||
import re
|
||||
|
||||
from PIL import Image
|
||||
from PIL.ImageCms import profileToProfile
|
||||
|
||||
color_swap = [0, 0, 0, 255]
|
||||
delta_for_color = 0
|
||||
mode = "Product"
|
||||
|
||||
|
||||
# Возвращает список изображений в цветовом пространтстве CMYK
|
||||
def get_list_cmyk_image(path, rgb_profile, cmyk_profile):
|
||||
list_image = []
|
||||
for d, dirs, files in os.walk(path): # Достаем все каталоги по пути
|
||||
for f in files: # Достаем все файлы
|
||||
if re.search(".jpg", f): # Сортировка по типу
|
||||
path = os.path.join(d, f) # Получаем путь до изображения
|
||||
im = Image.open(path)
|
||||
picture_cmyk = profileToProfile(im, rgb_profile, cmyk_profile, outputMode='CMYK')
|
||||
list_image.append(picture_cmyk) # Добавляем полученное изображение в список
|
||||
return list_image
|
||||
|
||||
|
||||
# переводит список процентов в соответствующее значение [0..255]
|
||||
def percent_to_scale_list(percent):
|
||||
list = []
|
||||
for p in percent:
|
||||
list.append(percent_to_scale(p))
|
||||
return list
|
||||
|
||||
|
||||
# преобразует процент в соответветсвующее значение [0..255]
|
||||
def percent_to_scale(percent):
|
||||
return int(percent / 100 * 255)
|
||||
|
||||
|
||||
# получение минимум
|
||||
# значение пикселя - процент погрешности
|
||||
def get_min(param):
|
||||
result = param - delta_for_color
|
||||
if result < 0:
|
||||
return 0
|
||||
else:
|
||||
return result
|
||||
|
||||
|
||||
# получение максимума
|
||||
# значение пикселя + процент погрешности
|
||||
def get_max(param):
|
||||
result = param + delta_for_color
|
||||
if result > 255:
|
||||
return 255
|
||||
else:
|
||||
return result
|
||||
|
||||
|
||||
# проверка входит ли значение пикселя в заданные границы
|
||||
def pixel_equal(pixel, mask_pixel):
|
||||
min_c = get_min(pixel)
|
||||
max_c = get_max(pixel)
|
||||
return min_c <= mask_pixel <= max_c
|
||||
|
||||
|
||||
# проверка пикселя на соответсвие искомого
|
||||
def range_equal(pixel, mask_pixel):
|
||||
c = pixel_equal(pixel[0], mask_pixel[0])
|
||||
m = pixel_equal(pixel[1], mask_pixel[1])
|
||||
y = pixel_equal(pixel[2], mask_pixel[2])
|
||||
k = pixel_equal(pixel[3], mask_pixel[3])
|
||||
|
||||
if c and m and y and k:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
# ищем пиксели из изображения и сравниваем с искомыми
|
||||
# если поиск был успешен, то заменяем его на заданные в конфигурации цвет
|
||||
def swap_pixel(image, mask_pixels, color_count):
|
||||
count = 0
|
||||
for i in range(image.width):
|
||||
for j in range(image.height):
|
||||
pixel = image.getpixel((i, j))
|
||||
for mask_pixel in mask_pixels:
|
||||
if range_equal(pixel, mask_pixel):
|
||||
image.putpixel((i, j), tuple(color_swap))
|
||||
count += 1
|
||||
if mode == "Test":
|
||||
print(count)
|
||||
|
||||
if count > color_count:
|
||||
return image
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
# Получение списка пикселей для дальшейшего их поиска в изображении
|
||||
def get_mask_pixel(food_name):
|
||||
list_tuple = []
|
||||
for pixel in food_name["CMYK"]:
|
||||
c = percent_to_scale(pixel["C"])
|
||||
m = percent_to_scale(pixel["M"])
|
||||
y = percent_to_scale(pixel["Y"])
|
||||
k = percent_to_scale(pixel["K"])
|
||||
list_tuple.append(tuple([c, m, y, k]))
|
||||
return list_tuple
|
||||
|
||||
|
||||
# поиск блюд на изображении
|
||||
def find_food_on_image(cmyk_image_list, food_name):
|
||||
list_found_image = []
|
||||
for image in cmyk_image_list:
|
||||
mask_pixel = get_mask_pixel(food_name)
|
||||
image_swap_pixel = swap_pixel(image, mask_pixel, food_name["Count"])
|
||||
if image_swap_pixel is not None:
|
||||
list_found_image.append(image_swap_pixel)
|
||||
return list_found_image
|
||||
|
||||
|
||||
# точка входа в скрипт, настройка параметров и вызов функций
|
||||
def find_food(configs, food_name):
|
||||
global delta_for_color, color_swap, mode
|
||||
delta_for_color = percent_to_scale(configs["Delta_for_color"])
|
||||
color_swap = percent_to_scale_list(configs["Color_swap"])
|
||||
mode = configs["Mode"]
|
||||
cmyk_image_list = get_list_cmyk_image(configs["Path_to_food"], configs["RGB_profile"], configs["CMYK_profile"])
|
||||
food_on_image_list = find_food_on_image(cmyk_image_list, food_name)
|
||||
return food_on_image_list
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Конвертер изображений}
|
||||
\label{app:conv}
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
from PIL import Image
|
||||
from PIL.ImageCms import profileToProfile
|
||||
|
||||
RGB_profile = "./AdobeICCProfiles/RGB/AdobeRGB1998.icc"
|
||||
CMYK_profile = "./AdobeICCProfiles/CMYK/WebCoatedSWOP2006Grade5.icc"
|
||||
|
||||
for i in range(1, 11):
|
||||
image_path = "./WorkFood/" + str(i) + ".jpg"
|
||||
im = Image.open(image_path)
|
||||
converted_image = profileToProfile(im, RGB_profile, CMYK_profile, outputMode='CMYK')
|
||||
converted_image.save("./CMYK_Food/" + str(i) + ".jpg")
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,652 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{4}{Разработка программы для классификации изображений с использованием свёрточной нейронной сети}{Цифровая обработка изображений}{}{Большаков В.Э.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\sloppy
|
||||
\section{Цель}
|
||||
Основной целью лабораторной работы является изучение методов распознания объекта с использованием свёрточной нейронной сети (CNN) и определение лучшей архитектуры сети для такого распознавания.
|
||||
\section{Задание}
|
||||
\begin{itemize}
|
||||
\item Подключить библиотеку scikit-learn, tensorflow или pytorch;
|
||||
\item Дополнить наборы картинок по варианту. Минимум 20 картинок для каждого класса (при неудовлетворительной классификации добавить ещё). Картинки намеренно должны быть схожими;
|
||||
\item Выбрать реализацию и обучить свёрточную нейронную сеть (CNN) для классификации в соответствии с вариантом;
|
||||
\item Провести эксперимент по распознаванию изображений с визуализацией результатов;
|
||||
\item Провести информационный поиск в Интернете. Попробовать несколько вариантов архитектур CNN. Выбрать лучшую архитектуру как минимум из двух. Построить график ошибок первого и второго рода по результатам распознавания;
|
||||
\item Прислать программу и подготовленные изображения преподавателю;
|
||||
\item Подготовить и прислать отчет.
|
||||
\end{itemize}
|
||||
|
||||
Вариант (по номеру в списке группы) 9, то есть «плантан и утёнок».
|
||||
\section{Теоретическая часть}
|
||||
\subsection{Свёрточная нейронная сеть}
|
||||
Сверточная нейронная сеть основана на универсальных математических операциях с матрицами\cite[c. 665]{dsa:cormen}. В общем случае, это последовательное применение операции сложения и/или умножения подматрицы основной матрицы для получения значения свёртки (рис. \hrf{pic:convolution-idea}). Свёртка - это линейное преобразование.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{100mm}
|
||||
\input{pics/02-dip-04-lab-cnn-idea.pdf_tex}
|
||||
\caption{Схема преобразвоания матрицы 3х5 в свёртку 1х3}
|
||||
\label{pic:convolution-idea}
|
||||
\end{figure}
|
||||
|
||||
Двумерная свертка — это операция для которой формируется ядро, представляющее из себя матрицу весов (weight matrix). Ядро проходит над двумерным изображением, поэлементно выполняя операцию умножения с той частью входных данных, над которой оно сейчас находится, и суммирует все полученные значения в одно, выходное.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{130mm}
|
||||
\input{pics/02-dip-04-lab-cnn-weight.pdf_tex}
|
||||
\caption{Добавление к свёртке весов}
|
||||
\label{pic:convolution-weight}
|
||||
\end{figure}
|
||||
|
||||
Ядро повторяет эту процедуру с каждой локацией, над которой оно проходит, преобразуя двумерную матрицу в другую, всё ещё двумерную матрицу признаков. Признаки на выходе являются взвешенными суммами признаков на входе, расположенных примерно в том же месте, что и выходной пиксель на входном слое. Независимо от того, попадает ли входной признак в «примерно то же место», он определяется в зависимости от того, находится он в зоне ядра, создающего выходные данные, или нет. Это значит, что размер ядра сверточной нейронной сети определяет количество признаков, которые будут объединены для получения нового признака на выходе.
|
||||
|
||||
Например, имея $5*5=25$ признаков на входе и $3*3=9$ признаков на выходе для стандартного слоя (standard fully connected layer) мы бы имели весовую матрицу $25*9=225$ параметров, а каждый выходной признак являлся бы взвешенной суммой всех признаков на входе. Свертка позволяет произвести такую операцию с всего 9-ю параметрами, ведь каждый признак на выходе получается анализом не каждого признака на входе, а только одного входного, находящегося в «примерно том же месте».
|
||||
|
||||
Часто используемые техники: Padding и Striding.
|
||||
\paragraph{Padding.} При проходе весовой матрицы по краю изображения, самые крайние пиксели, фактически, обрезаются, преобразуя матрицу признаков размером $5*5$ в матрицу $3*3$. Крайние пиксели никогда не оказываются в центре ядра, потому что тогда ядру не над чем будет проходить за краем. Padding добавляет к краям поддельные пиксели (обычно нулевые).
|
||||
|
||||
\paragraph{Striding.} Часто бывает, что при работе со сверточным слоем, нужно получить выходные данные меньшего размера, чем входные. Идея stride заключается в том, чтобы пропустить некоторые области, над которыми проходит ядро. Шаг 1 означает, что берутся области «через пиксель», то есть, по факту, стандартная свертка. Шаг 2 означает, что берутся области через каждые два пикселя, пропуская все другие области в процессе и уменьшая их количество примерно в два раза, шаг 3 означает пропуск трёх пикселей, сокращая количество в 3 раза и т.д.
|
||||
|
||||
\subsection{Архитектура нейронной сети и обучение}
|
||||
\label{subsect:arch}
|
||||
В работе не применяются поддельные пиксели ни в одной из архитектур. Пропускание шагов свёртки также не используется (области анализа следуют без разрывов). Для увеличения количества обучающих примеров была применена \textit{аугментация данных} (добавление шумов, деформация изображения, приближение в случайную точку изображения и произвольный поворот изображений). Пример аугментации приведён на рисунке \hrf{pic:augment}, а код, который деформирует изображения в листинге \hrf{lst:augment}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.45\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-04-lab-pic-src.png}
|
||||
\caption{Исходное изображение}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.45\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-04-lab-pic-aug.png}
|
||||
\caption{Изменённое изображение}
|
||||
\end{subfigure}
|
||||
\caption{Аугментация изображений}
|
||||
\label{pic:augment}
|
||||
\end{figure}
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,label={lst:augment}]
|
||||
data_augmentation = keras.Sequential(
|
||||
[
|
||||
layers.RandomFlip("horizontal_and_vertical",
|
||||
input_shape=(img_height,
|
||||
img_width,
|
||||
3)),
|
||||
layers.RandomRotation(0.3),
|
||||
layers.RandomZoom(-0.3),
|
||||
layers.Rescaling(0.3),
|
||||
]
|
||||
)
|
||||
\end{lstlisting}
|
||||
|
||||
В обучении всех архитектур, кроме одной, использовались пакеты по 8 изображений, а в единственном случае, 32. Пример изображений внутри пакета из 32 изображений приведён на рисунке \hrf{pic:pack-sample}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=11cm]{02-dip-04-lab-pack-sample.png}
|
||||
\caption{Пример пакета для обучения нейросети}
|
||||
\label{pic:pack-sample}
|
||||
\end{figure}
|
||||
|
||||
В работе были применены разные архитектуры, обучавшиеся каждая по 1000 эпох. Каждая архитектура включает в себя специальные свёрточные слои и один примитивный слой (обычный персептрон). Структуры нейронных сетей приведены в таблице \hrf{table:arch-diff}. Построенные автоматизированно диаграммы нейронных сетей в приложении \hrf{appendix:architectures}.
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\begin{tabular}{|p{15mm}|p{30mm}|p{40mm}|p{30mm}|p{15mm}|p{15mm}|}
|
||||
\hline
|
||||
Номер архитектуры & Метод обучения & Количество нейронов свёрточного слоя & Количество нейронов примитивного слоя & Размер пакета & Эпох \\ [0.5ex]
|
||||
\hline
|
||||
1(\hrf{pic:arch-1}) & ADAM & 16/32/64 & 256 & 8 & 1000 \\
|
||||
2(\hrf{pic:arch-1}) & SGD & 16/32/64 & 256 & 8 & 1000 \\
|
||||
3(\hrf{pic:arch-1}) & ADAM & 16/32/64 & 256 & 32 & 1000 \\
|
||||
4(\hrf{pic:arch-1}) & ADAM & 16/32/64 & 256 & 8 & 10000 \\
|
||||
5(\hrf{pic:arch-5}) & ADAM & 16/32/64/128/64/32 & 256 & 8 & 1000 \\
|
||||
6(\hrf{pic:arch-6}) & ADAM & 32/64/128 & 512 & 8 & 1000 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Свойства архитектур нейронных сетей, применённых в работе}
|
||||
\label{table:arch-diff}
|
||||
\end{table}
|
||||
|
||||
\textbf{SGD (Stochastic Gradient Descent)} - тренировка нейронной сети заключается в подборе параметров (весов модели) таким образом, чтобы минимизировать ошибку нейронной сети на тренировочном наборе. Если значение ошибки нейросети не минимальное, но и незначительно изменяется между эпохами обучения, то алгоритм метода принимает решение об изменении поправок к весам нейронов.
|
||||
|
||||
\textbf{ADAM (ADAptive Moment estimation)} - это алгоритм оптимизации, который можно использовать вместо классической процедуры SGD для итеративного обновления весов сети на основе обучающих данных. SGD поддерживает единую скорость обучения (называемую альфа) для всех обновлений веса, и скорость обучения не изменяется во время тренировки. В то время как в методе Adam скорость обучения поддерживается для каждого веса сети (параметра) и отдельно адаптируется по мере развития обучения. Метод вычисляет индивидуальные адаптивные скорости обучения для различных параметров из оценок первого и второго моментов градиентов.
|
||||
|
||||
Каждая архитектура содержит специальный слой, препятствующий переобучению сети. Такой слой в терминах TensorFlow называется DropOut. Это виртуальный слой, не строгое понятие, некоторая абстракция, между двумя смежными слоями, этому слою передается число от 0 до 1 - вероятность срабатывания. Дропаут представляет собой "выключение" нейрона из смежного слоя (рис. \hrf{pic:dropout}).
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{100mm}
|
||||
\input{pics/02-dip-04-lab-dropout.pdf_tex}
|
||||
\caption{Принцип работы dropout}
|
||||
\label{pic:dropout}
|
||||
\end{figure}
|
||||
|
||||
\section{Практическая часть}
|
||||
Приложение состоит из набора пресетов свёрточных нейронных сетей, функций создания обучающей и валидационной выборки, терминального интерфейса пользователя и функции тестирования нейросети на наборе изображений из исходного задания.
|
||||
|
||||
\subsection{Пользовательский интерфейс}
|
||||
Пользовательский интерфейс предполагает выбор количества обучающих эпох и выбор одной из шести архитектур нейронной сети.
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,caption={Запрос аргументов и настройка нейросети},label={src:learn}]
|
||||
def create_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-e', '--epoch')
|
||||
parser.add_argument('-b', '--batch')
|
||||
parser.add_argument('-a', '--arch')
|
||||
parser.add_argument('-m', '--method')
|
||||
return parser
|
||||
|
||||
namespace = create_parser().parse_args(sys.argv[1:])
|
||||
|
||||
if __name__ == '__main__':
|
||||
#Создание и обучение сети
|
||||
mainFunction(int(namespace.epoch), int(namespace.batch), int(namespace.arch), namespace.method)
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Архитектуры нейросетей}
|
||||
В листинге \hrf{src:archpick} приведён пример создания архитектуры свёрточной нейросети и функция выбора архитектуры для дальнейшего применения в приложении. Полностью, функции создания всех архитектур приведены в приложении \hrf{appendix:main}.
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,caption={Создание архитектуры по умолчанию},label={src:archpick}]
|
||||
def DefaultArchitecture():
|
||||
return Sequential([
|
||||
data_augmentation,
|
||||
layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
|
||||
layers.Conv2D(32, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(64, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(128, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Flatten(),
|
||||
layers.Dropout(0.2),
|
||||
layers.Dense(256, activation='relu'),
|
||||
layers.Dense(num_classes)
|
||||
])
|
||||
|
||||
architectureType = {
|
||||
1 : DefaultArchitecture,
|
||||
2 : DefaultArchitecture,
|
||||
3 : DefaultArchitecture,
|
||||
4 : DefaultArchitecture,
|
||||
5 : FiveArchitecture,
|
||||
6 : SixArchitecture
|
||||
}
|
||||
|
||||
def GetModelArchitecture(type):
|
||||
num_classes = len(class_names)
|
||||
return architectureType[type]
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Обучение}
|
||||
Для обучения была сформирована выборка из похожих изображений. Формирование более широкой выборки для обучения нейросетей подробно описано в подразделе «\hRf{subsect:arch}». Код, осуществляющий формирование обучающей и валидационной выборки представлен в листинге \hrf{src:learn}.
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,caption={Функция создания выборок и функция обучения},label={src:learn}]
|
||||
def CreateTrainAndValidDataSet(batch_size):
|
||||
train_ds = tf.keras.utils.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="training",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
|
||||
val_ds = tf.keras.utils.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="validation",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
return [train_ds, val_ds]
|
||||
|
||||
def TrainNetwork(model, train_ds, val_ds, epochs):
|
||||
return model.fit(
|
||||
train_ds,
|
||||
validation_data=val_ds,
|
||||
epochs=epochs
|
||||
)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Выборка для тестирования}
|
||||
Для тестирования была использована выборка из задания, показанная на рисунке \hrf{pic:testing-set}. Тестирование нейросети и демонстрация результатов производилось скриптом, представленным в листинге \hrf{src:testing}. Скрипт разбивает исходное изображение на 16 изображений объектов и последовательно классифицирует каждое с последующим выводом результатов на экран. Результаты работы скрипта для каждой из архитектур представлены в разделе \hrf{sec:results}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=16cm]{01-dip-lab04-testing.jpg}
|
||||
\caption{Исходная выборка из задания}
|
||||
\label{pic:testing-set}
|
||||
\end{figure}
|
||||
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle,caption={Разбиение тестовой выборки и классификация},label={src:testing}]
|
||||
valid_image = PIL.Image.open('plantain_vs_duckling.jpg')
|
||||
matrix_valid_image = np.array(valid_image)
|
||||
plt.figure(figsize=(10, 10))
|
||||
dx = int(matrix_valid_image.shape[0] / 4)
|
||||
dy = int(matrix_valid_image.shape[1] / 4)
|
||||
count = 1
|
||||
for j in range(0, matrix_valid_image.shape[1] - dy, dy):
|
||||
for i in range(0, matrix_valid_image.shape[0] - dx, dx):
|
||||
ax = plt.subplot(4, 4, count)
|
||||
plt.imshow(matrix_valid_image[j:j + dy,i:i + dx].astype("uint8"))
|
||||
plt.axis("off")
|
||||
count += 1
|
||||
|
||||
plt.figure(figsize=(10, 10))
|
||||
dx = int(matrix_valid_image.shape[0] / 4)
|
||||
dy = int(matrix_valid_image.shape[1] / 4)
|
||||
count = 1
|
||||
for j in range(0, matrix_valid_image.shape[1] - dy, dy):
|
||||
for i in range(0, matrix_valid_image.shape[0] - dx, dx):
|
||||
ax = plt.subplot(4, 4, count)
|
||||
plt.imshow(matrix_valid_image[j:j + dy, i:i + dx].astype("uint8"))
|
||||
img = (PIL.Image.fromarray(np.uint8(matrix_valid_image[j:j + dy, i:i + dx]))).resize((img_height, img_width))
|
||||
img_array = tf.keras.utils.img_to_array(img)
|
||||
img_array = tf.expand_dims(img_array, 0)
|
||||
predictions = model.predict(img_array)
|
||||
score = tf.nn.softmax(predictions[0])
|
||||
plt.title(class_names[np.argmax(score)] + "\nТочность = " + str(int(100 * np.max(score))) + " %")
|
||||
plt.axis("off")
|
||||
count += 1
|
||||
plt.subplots_adjust(wspace=0.1, hspace=1)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Результат работы}
|
||||
\label{sec:results}
|
||||
Нейросети определили на изображениях объекты с некоторой вероятностью. Пример результата работы нейросети для первой архитектуры представлен в таблице \hrf{table:results}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|c|c|c|c|}
|
||||
\hline
|
||||
Номер & Изображено & Попадание & Точность \\ [0.5ex]
|
||||
\hline
|
||||
1 & Плантан & да & 100 \\
|
||||
2 & Утёнок & да & 99 \\
|
||||
3 & Плантан & да & 100 \\
|
||||
4 & Утёнок & да & 100 \\
|
||||
5 & Плантан & да & 100 \\
|
||||
6 & Плантан & нет & 88 \\
|
||||
7 & Утёнок & да & 100 \\
|
||||
8 & Плантан & да & 100 \\
|
||||
9 & Утёнок & да & 100 \\
|
||||
10 & Утёнок & да & 99 \\
|
||||
11 & Плантан & да & 99 \\
|
||||
12 & Плантан & нет & 99 \\
|
||||
13 & Плантан & да & 100 \\
|
||||
14 & Утёнок & да & 100 \\
|
||||
15 & Плантан & нет & 100 \\
|
||||
16 & Утёнок & да & 99 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Результат работы нейросети №1}
|
||||
\label{table:results}
|
||||
\end{table}
|
||||
|
||||
В результате классификации (после обучения и тестирования) были получены данные представленные на рисунке \hrf{pic:net-test}. Графики процессов обучения (наличие ошибок и точность классификации представлены в приложении \hrf{appendix:graphics})
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{02-dip-04-lab-1network-valid.png}
|
||||
\caption{Результаты классификации изображений нейронной сетью}
|
||||
\label{pic:net-test}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Ошибки}
|
||||
В результате работы нейросетями были допущены ошибки первого и второго рода (ложноположительные и ложноотрицательные заключения). Ошибка первого рода ($\alpha$-ошибка) - это ситуация, когда отвергнута верная гипотеза, а ошибка второго рода ($\beta$-ошибка) - это ситуация, когда принята неверная гипотеза. Можно предположить, что неуверенность (ниже 98\%) сети в верном результате классификации - это ошибка первого рода, а некорректная классификация с любым уровнем точности - ошибка второго рода. Такие допущения введены из-за малого размера обучающих наборов. Сводная таблица \hrf{table:mistakes} содержит результаты классификации изображений, а результаты работы каждой сети представлены в приложении \hrf{appendix:result-pics}.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|c|c|c|}
|
||||
\hline
|
||||
Архитектура & $\alpha$-ошибки & $\beta$-ошибка \\
|
||||
\hline
|
||||
1 & 0/16 & 3/16 \\
|
||||
2 & 2/16 & 1/16 \\
|
||||
3 & 8/16 & 2/16 \\
|
||||
4 & 1/16 & 1/16 \\
|
||||
5 & 4/16 & 2/16 \\
|
||||
6 & 1/16 & 2/16 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Сводная таблица ошибок}
|
||||
\label{table:mistakes}
|
||||
\end{table}
|
||||
\section{Заключение}
|
||||
В ходе выполнения задания были изучены принципы работы CNN и их основные архитектуры. Исходя из результатов тестирования можно сделать вывод, что использование небольших датасетов для обучения является основной проблемой для распознавания изображений, то есть при достаточном расширении обучающей выборки или увеличении количества эпох нейросеть можно обучить для достаточно точного определения объекта на изображении.
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Asbuk{subsection}}
|
||||
|
||||
\subsection{Полный текст программы}
|
||||
\label{appendix:main}
|
||||
\begin{lstlisting}[language=Python,style=PyCodeStyle]
|
||||
import argparse
|
||||
import codecs
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
import PIL
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
from tensorflow import keras
|
||||
from tensorflow.keras import layers
|
||||
from tensorflow.keras.models import Sequential
|
||||
|
||||
img_height = 180
|
||||
img_width = 180
|
||||
data_dir = pathlib.Path("dataset")
|
||||
|
||||
data_augmentation = keras.Sequential(
|
||||
[
|
||||
layers.RandomFlip("horizontal_and_vertical",
|
||||
input_shape=(img_height,
|
||||
img_width,
|
||||
3)),
|
||||
layers.RandomRotation(0.1),
|
||||
layers.RandomZoom(-0.1),
|
||||
layers.Rescaling(0.1),
|
||||
]
|
||||
)
|
||||
def TrainNetwork(model, train_ds, val_ds, epochs):
|
||||
return model.fit(
|
||||
train_ds,
|
||||
validation_data=val_ds,
|
||||
epochs=epochs
|
||||
)
|
||||
|
||||
def CreateTrainAndValidDataSet(batch_size):
|
||||
train_ds = tf.keras.utils.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="training",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
|
||||
val_ds = tf.keras.utils.image_dataset_from_directory(
|
||||
data_dir,
|
||||
validation_split=0.2,
|
||||
subset="validation",
|
||||
seed=123,
|
||||
image_size=(img_height, img_width),
|
||||
batch_size=batch_size)
|
||||
global class_names
|
||||
class_names = train_ds.class_names
|
||||
return [train_ds, val_ds]
|
||||
|
||||
def CompileMoment(model, optimaizer):
|
||||
model.compile(optimizer=optimaizer,
|
||||
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
|
||||
metrics=['accuracy'])
|
||||
|
||||
def GetModelArchitecture(type):
|
||||
global num_classes
|
||||
num_classes = len(class_names)
|
||||
return architectureType[type]()
|
||||
|
||||
def DefaultArchitecture():
|
||||
|
||||
return Sequential([
|
||||
data_augmentation,
|
||||
layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
|
||||
layers.Conv2D(32, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(64, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(128, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Flatten(),
|
||||
layers.Dropout(0.2),
|
||||
layers.Dense(256, activation='relu'),
|
||||
layers.Dense(num_classes)
|
||||
])
|
||||
|
||||
def FiveArchitecture():
|
||||
return Sequential([
|
||||
data_augmentation,
|
||||
layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
|
||||
layers.Conv2D(64, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(128, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(256, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(128, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(64, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Flatten(),
|
||||
layers.Dropout(0.2),
|
||||
layers.Dense(256, activation='relu'),
|
||||
layers.Dense(num_classes)
|
||||
])
|
||||
|
||||
def SixArchitecture():
|
||||
return Sequential([
|
||||
data_augmentation,
|
||||
layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
|
||||
layers.Conv2D(128, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(256, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Conv2D(512, 3, padding='same', activation='relu'),
|
||||
layers.MaxPooling2D(),
|
||||
layers.Flatten(),
|
||||
layers.Dropout(0.2),
|
||||
layers.Dense(512, activation='relu'),
|
||||
layers.Dense(num_classes)
|
||||
])
|
||||
|
||||
architectureType = {
|
||||
1 : DefaultArchitecture,
|
||||
2 : DefaultArchitecture,
|
||||
3 : DefaultArchitecture,
|
||||
4 : DefaultArchitecture,
|
||||
5 : FiveArchitecture,
|
||||
6 : SixArchitecture
|
||||
}
|
||||
|
||||
def create_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-e', '--epoch')
|
||||
parser.add_argument('-b', '--batch')
|
||||
parser.add_argument('-a', '--arch')
|
||||
parser.add_argument('-m', '--method')
|
||||
return parser
|
||||
|
||||
namespace = create_parser().parse_args(sys.argv[1:])
|
||||
|
||||
def mainFunction(epoch, batch_size, modelType, optimaizeMethod):
|
||||
image_count = len(list(data_dir.glob('*/*.jpg')))
|
||||
print("Всего изображений = " + str(image_count))
|
||||
|
||||
#Передаем размер пакета
|
||||
train_ds, val_ds = CreateTrainAndValidDataSet(batch_size)
|
||||
|
||||
AUTOTUNE = tf.data.AUTOTUNE
|
||||
|
||||
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
|
||||
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
|
||||
|
||||
#Модель из предкомпелированных
|
||||
model = GetModelArchitecture(modelType)
|
||||
|
||||
CompileMoment(model, optimaizeMethod)
|
||||
|
||||
history = TrainNetwork(model, train_ds, val_ds, epoch)
|
||||
|
||||
acc = history.history['accuracy']
|
||||
val_acc = history.history['val_accuracy']
|
||||
|
||||
loss = history.history['loss']
|
||||
val_loss = history.history['val_loss']
|
||||
|
||||
epochs_range = range(epoch)
|
||||
|
||||
plt.figure(figsize=(8, 8))
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.plot(epochs_range, acc, label='Точность на тренировочной выборке')
|
||||
plt.plot(epochs_range, val_acc, label='Точность на контрольной выборке')
|
||||
plt.legend(loc='lower right')
|
||||
plt.title('Точности на тренировочной и контрольной выборке')
|
||||
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.plot(epochs_range, loss, label='Ошибка на тренировочной выборке')
|
||||
plt.plot(epochs_range, val_loss, label='Ошибка на контрольной выборке')
|
||||
plt.legend(loc='upper right')
|
||||
plt.title('Ошибки на обучающей и контрольной выборках')
|
||||
plt.show()
|
||||
|
||||
valid_image = PIL.Image.open('plantain_vs_duckling.jpg')
|
||||
|
||||
matrix_valid_image = np.array(valid_image)
|
||||
plt.figure(figsize=(10, 10))
|
||||
dx = int(matrix_valid_image.shape[0] / 4)
|
||||
dy = int(matrix_valid_image.shape[1] / 4)
|
||||
count = 1
|
||||
for j in range(0, matrix_valid_image.shape[1] - dy, dy):
|
||||
for i in range(0, matrix_valid_image.shape[0] - dx, dx):
|
||||
ax = plt.subplot(4, 4, count)
|
||||
plt.imshow(matrix_valid_image[j:j + dy, i:i + dx].astype("uint8"))
|
||||
img = (PIL.Image.fromarray(np.uint8(matrix_valid_image[j:j + dy, i:i + dx]))).resize((img_height, img_width))
|
||||
img_array = tf.keras.utils.img_to_array(img)
|
||||
img_array = tf.expand_dims(img_array, 0)
|
||||
predictions = model.predict(img_array)
|
||||
score = tf.nn.softmax(predictions[0])
|
||||
plt.title(class_names[np.argmax(score)] + "\nТочность = " + str(int(100 * np.max(score))) + " %")
|
||||
plt.axis("off")
|
||||
count += 1
|
||||
plt.subplots_adjust(wspace=0.1, hspace=1)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#Создание и обучение сети
|
||||
mainFunction(int(namespace.epoch), int(namespace.batch), int(namespace.arch), namespace.method)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Архитектуры применённых нейросетей}
|
||||
\label{appendix:architectures}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-04-lab-1network-arch.png}
|
||||
\caption{Нейросеть для 1, 2, 3 и 4 случая}
|
||||
\label{pic:arch-1}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-04-lab-5network-arch.png}
|
||||
\caption{Нейросеть 5}
|
||||
\label{pic:arch-5}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.3\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-dip-04-lab-6network-arch.png}
|
||||
\caption{Нейросеть 6}
|
||||
\label{pic:arch-6}
|
||||
\end{subfigure}
|
||||
\caption{Стандартная визуализация архитектур пакета TensorFlow}
|
||||
\label{pic:architectures}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Графики обучения нейросетей}
|
||||
\label{appendix:graphics}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-1network.png}
|
||||
\caption{Графики обучения сети №1}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-2network.png}
|
||||
\caption{Графики обучения сети №2}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-3network.png}
|
||||
\caption{Графики обучения сети №3}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-4network.png}
|
||||
\caption{Графики обучения сети №4}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-5network.png}
|
||||
\caption{Графики обучения сети №5}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-6network.png}
|
||||
\caption{Графики обучения сети №6}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Результаты классификации изображений}
|
||||
\label{appendix:result-pics}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-1network-valid.png}
|
||||
\caption{Классификация сетью №1}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-2network-valid.png}
|
||||
\caption{Классификация сетью №2}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-3network-valid.png}
|
||||
\caption{Классификация сетью №3}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-4network-valid.png}
|
||||
\caption{Классификация сетью №4}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-5network-valid.png}
|
||||
\caption{Классификация сетью №5}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\includegraphics[width=17cm]{02-dip-04-lab-6network-valid.png}
|
||||
\caption{Классификация сетью №6}
|
||||
\end{figure}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,263 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationTop
|
||||
|
||||
\titlespacing*{\section}{\parindent}{1ex}{1em}
|
||||
|
||||
\setlength{\parindent}{4pc} % exaggerated for the example
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
\captionsetup[tabular]{labelsep=space,
|
||||
justification=raggedright, singlelinecheck=off}
|
||||
|
||||
\makeReportTitle{домашней}{1}{Команды микропроцессора}{Микропроцессорные устройства обработки сигналов}{}{проф. каф. ИУЗ, д.т.н. \\В.С. Выхованец}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\addtocontents{toc}{\vspace{2ex}} % 6.2.3 В элементе «Содержание» номера подразделов приводят после абзацного отступа, равного двум знакам, относительно номеров разделов.
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Задача}
|
||||
Целью выполнения домашнего задания является изучение архитектуры и организации микропроцессора и выбор методов и средств реализации низкоуровневой функции, заданной в теме домашнего задания.
|
||||
|
||||
\textbf{Темой домашнего задания} является умножение и сложение с насыщением и округлением: \code{long \_smacr(long src1, int src2, int src3)}.
|
||||
|
||||
Выполнение задания разделено на следующие этапы:
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item ознакомление с методическим материалом, учебным пособием \cite[с. 6-68]{dsp:lectures} и технической документацией \cite{ti:dsp-mnemonics}, поиск и изучение команд микропроцессора, позволяющих эффективно реализовать заданную функцию;
|
||||
\item описание найденных команд и их настройка для реализации разрабатываемой низкоуровневой функции;
|
||||
\item описание методики разработки низкоуровневой функции.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Выполнение}
|
||||
Для выполнения домашнего задания необходимо:
|
||||
\begin{itemize}
|
||||
\item ознакомиться с рекомендованной литературой;
|
||||
\item разработать и описать алгоритм решения задачи;
|
||||
\item найти и изучить команды микропроцессора, необходимые для решения задачи;
|
||||
\item подготовить тестовые данные для проверки реализации алгоритма;
|
||||
\item оформить\cite{gost:texts} отчет\cite{gost:links} по домашнему заданию\cite{bmstu:dsp-methodics1}.
|
||||
\end{itemize}
|
||||
Основным результатом домашнего задания является методика разработки низкоуровневой функции для умножения и сложения с насыщением и округлением.
|
||||
|
||||
\subsection{Описание алгоритма низкоуровневой функции}
|
||||
В микропроцессоре используется арифметика с фиксированной запятой, поэтому умножение дробных и целых чисел производится по одному и тому же принципу, представленному в общем виде формулами
|
||||
\begin{equation}
|
||||
\begin{gathered}
|
||||
X_{Q1.15} = -s_x + 2^{-15} \sum_{i=0}^{14} x_i \cdot 2^i, Y_{Q1.15} = -s_y + 2^{-15} \sum_{i=0}^{14} y_i \cdot 2^i, \\
|
||||
Z = 2^{-30} \big( -s_x + 2^{15} \sum_{i=0}^{14} x_i \cdot 2^i\big) \big( -s_y + 2^{15} \sum_{i=0}^{14} y_i \cdot 2^i \big), \\
|
||||
Z = 2^{-30}(X_{Z16} \cdot Y_{Z16}) = 2^{-30} Z_{Z32}, Z_{Q1.31} = 2 \cdot Z, \\
|
||||
Z_{Q1.31} = -s_Z + 2^{-31} \sum_{i=0}^{30} z_i \cdot 2^i, \\
|
||||
Z_{Q1.31} = Z_{Z32} < < 1, \\
|
||||
Z_{Q1.15} = Z_{Z32} > > 15,
|
||||
\end{gathered}
|
||||
\label{math:multiply}
|
||||
\end{equation}
|
||||
где $ X_{Q1.15} $ - первый операнд в формате Q1.15, $ Y_{Q1.15} $ - второй операнд в формате Q1.15, $ Z_{Q1.15} $ - результат вычислений в формате Q1.15, $-s_x$ - старший разряд первого операнда, обозначающий знак числа, $ x_i$ - каждый следующий разряд первого операнда, $-s_y$ - старший разряд второго операнда, обозначающий знак числа, $ y_i$ - каждый следующий разряд второго операнда. Таким образом для получения корректного результат умножения двух чисел в формате Q1.15 необходимо отсечь от полученного 32-разрядного результата младшие 15 разрядов, предварительно удалив самый старший разряд.
|
||||
|
||||
Насыщение - это процесс для операций с фиксированной запятой, при котором происходит преобразование результата умножения на максимально возможное представимое число. При отрицательном результате происходит замена на самое маленькое представимое число (например, \code{0xFF80000000} – минимальное число в Q1.31), а при положительном - на самое большое доступное (например, \code{0x007FFFFFFF} – максимальное число в Q1.31). Пример насыщения в таблице \hrf{table:saturation} демонстрирует также разницу двоичных представлений чисел разной разрядности.
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\caption{Пример насыщения}
|
||||
\label{table:saturation}
|
||||
\begin{tabular}{|lclcl|}
|
||||
\hline
|
||||
Q9.31 & & & & Q1.31 \\ [0.5ex]
|
||||
0xFE80\_0000\_09 & & & $\neq$ & 0x80\_0000\_09 \\
|
||||
0x0180\_0000\_09 & & & $\neq$ & 0x80\_0000\_09 \\
|
||||
0xFE80\_0000\_09 & $\approx$ & 0xFF80\_0000\_09 & = & 0x80\_0000\_00 \\
|
||||
0x0180\_0000\_09 & $\approx$ & 0x007F\_FFFF\_FF & = & 0x7F\_FFFF\_FF \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
|
||||
\subsection{Прототип низкоуровневой функции}
|
||||
Согласно документации \cite[с. 77 (3-33)]{ti:dsp-prog-guide}, прототип низкоуровневой функции и описание аргументов функции на языке Си имеют вид, представленный в таблице \hrf{table:prototype}.
|
||||
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\caption{Прототип и описание действия функции}
|
||||
\label{table:prototype}
|
||||
\begin{tabular}{|p{55mm}|p{110mm}|}
|
||||
\hline
|
||||
Прототип функции & Верхнеуровневое описание \\ [3ex]
|
||||
\hline
|
||||
\multirow{2}{54mm}{\code{long \_smacr(long src, int op1, int op2)}} & Функция осуществляет умножение операторов \code{op1} и \code{op2}, сдвиг полученного результата влево на один разряд, складывает результат со значением параметра \code{src}, округляет результат, добавляя число 215 и присваивает значение 0 в младшие 16 разрядов, (устанавливаются биты SATD, SMUL и FRCT).\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Параметры функции в таблице \hrf{table:prototype} имеют типы \code{long} и \code{int}, то есть представлены в формате Q1.15 и Q1.31, соответственно. Двоичные представления чисел в данных форматах \cite{dsp:lectures} представлены в таблицах \hrf{table:qbin-15} и \hrf{table:qbin-31} соответственно.
|
||||
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\setlength\tabcolsep{1.5pt}
|
||||
\centering
|
||||
\caption{Формат представления чисел с фиксированной запятой (Q1.15)}
|
||||
\label{table:qbin-15}
|
||||
\begin{tabular}{|c|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|}
|
||||
\multirow{3}{*}{Q1.15} & $2^{0}$ & $2^{-1}$ & $2^{-2}$ & $2^{-3}$ & $2^{-4}$ & $2^{-5}$ & $2^{-6}$ & $2^{-7}$ & $2^{-8}$ & $2^{-9}$ & $2^{-10}$ & $2^{-11}$ & $2^{-12}$ & $2^{-13}$ & $2^{-14}$ & $2^{-15}$ \\
|
||||
&$15$ & $14$ & $13$ & $12$ & $11$ & $10$ & $9$ & $8$ & $7$ & $6$ & $5$ & $4$ & $3$ & $2$ & $1$ & $0$ \\
|
||||
\cline{2-17}
|
||||
&S & X & X & X & X & X & X & X & X & X & X & X & X & X & X & X \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\setlength\tabcolsep{1.5pt}
|
||||
\centering
|
||||
\caption{Формат представления чисел с фиксированной запятой (Q1.31)}
|
||||
\label{table:qbin-31}
|
||||
\begin{tabular}{|c|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|}
|
||||
\multirow{3}{*}{Q1.31} & $2^{0}$ & $2^{-1}$ & $2^{-2}$ & $2^{-3}$ & $2^{-4}$ & $2^{-5}$ & $2^{-6}$ & $2^{-7}$ & $2^{-8}$ & $2^{-9}$ & $2^{-10}$ & $2^{-11}$ & . . . & $2^{-25}$ & $2^{-26}$ & $2^{-27}$ & $2^{-28}$ & $2^{-29}$ & $2^{-30}$ & $2^{-31}$\\
|
||||
& $31$ & $30$ & $29$ & $28$ & $27$ & $26$ & $25$ & $24$ & $23$ & $22$ & $21$ & $20$ & . . . & $6$ & $5$ & $4$ & $3$ & $2$ & $1$ & $0$ \\
|
||||
\cline{2-21}
|
||||
& S & X & X & X & X & X & X & X & X & X & X & X & . . . & X & X & X & X & X & X & X\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Для очищения младших 16ти разрядов может быть использована макрокоманда\cite[стр. 138]{ti:dsp-c-compiler}, представленная в листинге \hrf{lst:macros}.
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Макрокоманда, очищающая младшие разряды},label={lst:macros}]
|
||||
#define mac_r(a,b,c) (short)(_smacr((a),(b),(c)) >> 16)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Передача аргументов и возврат результата}
|
||||
При вызове функции на языке Си, передача значений аргументов осуществляется в регистры и на стек по следующим правилам \cite[с. 125]{ti:dsp-c-compiler}:
|
||||
\begin{itemize}
|
||||
\item для функций, объявленных с переменным числом не типизированных аргументов, последний явно объявленный аргумент помещается на стек, за ним следуют оставшиеся аргументы, адрес этого аргумента может быть использован как ссылка для доступа к неявно переданным аргументам;
|
||||
\item структура из двух слов или менее рассматриваются как 32-разрядный аргумент;
|
||||
\item структура из более, чем двух слов передаётся по ссылке, компилятор передаст адрес структуры как указатель;
|
||||
\item в основном, когда аргумент передаётся в функцию, компилятор присваивает его определённому классу и помещает в регистр (если доступен), согласно класса. Компилятор использует три класса:
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item 24-разрядный указатель на данные (\code{int*}, \code{long*}, и так далее);
|
||||
\item 16-разрядные данные (\code{char}, \code{short}, \code{int});
|
||||
\item 32-разрядные данные (\code{long}, \code{float}, \code{double}, указатель на функцию).
|
||||
\end{enumerate}
|
||||
Если аргумент является указателем на любой тип данных, он считается указателем на данные. Если аргумент может быть помещён в 16-разрядный регистр, он считается 16-разрядными данными. Во всех остальных случаях данные считаются 32-разрядными. 40-разрядные данные передаются с использованием всего регистра, а не только его младших 32 разрядов.
|
||||
\end{itemize}
|
||||
|
||||
Аргументы передаются в регистры в порядке, в котором они указаны в прототипе функции и помещаются, согласно класса, в следующие регистры:
|
||||
\begin{itemize}
|
||||
\item 24-разрядный указатель в регистрах \code{(X)AR0}, \code{(X)AR1}, \code{(X)AR2}, \code{(X)AR3} и \code{(X)AR4};
|
||||
\item 16-разрядные данные в регистрах \code{T0}, \code{T1}, \code{AR0}, \code{AR1}, \code{AR2}, \code{AR3}, \code{AR4};
|
||||
\item 32- или 40-разрядные данные в регистрах \code{AC0}, \code{AC1}, \code{AC2}.
|
||||
\end{itemize}
|
||||
|
||||
Если доступные регистры для размещения аргументов отсутствуют, то не поместившиеся аргументы помещаются на стек. Стек по умолчанию выровнен по чётной границе. Затем каждый аргумент выравнивается на стеке согласно его класса. В случае необходимости вставляются пустоты для дополнительного выравнивания аргументов.
|
||||
|
||||
В ячейке \code{*SP(0)} размещается адрес возврата из функции, в \code{*SP(1)} – 1-й аргумент функции, не поместившийся в регистрах, и т.д., где \code{SP} – это указатель стека операндов, а в круглых скобках указано смещение относительно этого указателя в двойных словах.
|
||||
|
||||
Возврат результата выполнения функции осуществляется через регистры:
|
||||
\begin{itemize}
|
||||
\item данные разрядностью 16 бит размещаются в регистре \code{T0};
|
||||
\item данные разрядностью 32 или 40 бита размещаются в регистре \code{AC0};
|
||||
\item указатели разрядностью 24 бит размещаются в регистре \code{(X)AR0};
|
||||
\item структура длиной более 32 бит возвращается через первый аргумент
|
||||
\item функции – указатель на структуру, если он \code{0x0}, то структура не возвращается.
|
||||
\end{itemize}
|
||||
|
||||
Вызываемая функция при использовании должна сохранять и восстанавливать регистры \code{T2}, \code{T3}, \code{(X)AR5}, \code{(X)AR6} и \code{(X)AR7}, а регистры \code{T0}, \code{T1}, \code{(X)AR0}, \code{(X)AR1}, \code{(X)AR2}, \code{(X)AR3}, \code{(X)AR4}, \code{AC0}, \code{AC1}, \code{AC2}, \code{AC3} может использовать без сохранения. Все другие специальные регистры микропроцессора при использовании подлежат обязательному сохранению и восстановлению, а именно: \code{RETA}, \code{BKx}, \code{BRCx}, \code{BRS1}, \code{BSAx}, \code{RSAx}, \code{REAx}, \code{RPTC}, \code{CSR}, \code{TRNx}, \code{(X)DP}, \code{(X)CDP}, \code{STx\_55}, где вместо \code{x} подставляется номер соответствующего регистра.
|
||||
|
||||
Сохранение регистров производится в автоматической (локальной) памяти функции, выделяемой на стеке перед адресом возврата путем уменьшения указателя стека SP на число двойных слов выделяемой памяти. Локальная память освобождается перед возвратом из функции путем увеличения указателя стека SP на число выделенных двойных слов. После выделения локальной памяти доступ к аргументам осуществляется с учетом длины выделенной памяти. Например, после выделения двух двойных слов адрес возврата из функции может быть адресован как \code{*SP(2)}, первый аргумент в стеке – как \code{*SP(3)}, и т.д.
|
||||
|
||||
Очистку стека с аргументами производит вызывающая функция после вызова вызываемой. В соответствии с вышеописанным для функции с прототипом, указанным в таблице \hrf{table:prototype} аргументы размещаются в порядке следования в регистрах \code{AC0}, \code{T0} и \code{T1}, а результат будет помещён в регистр \code{AC0}. Стек для размещения аргументов не используется.
|
||||
|
||||
\subsection{Описание и форматы команд микропроцессора}
|
||||
Из документации на компилятор\cite[с. 134]{ti:dsp-c-compiler} получены следующие сведения: функция устанавливает биты (флаги) \code{SATD}\footnote{Saturation Mode (D unit)}, \code{SMUL}\footnote{Saturation-on-multiplication mode}, \code{FRCT}\footnote{Fractional mode (fixed-point mathematics in C)}. Возвращает насыщенную сумму \code{src} и fractional-mode произведение параметров \code{op1} и \code{op2}. Сумма округляется так, как если бы была вызвана функция \code{_sround}\cite[с. 136]{ti:dsp-c-compiler}.
|
||||
%\footnote{Returns the value \code{src} rounded by adding $2^{15}$ using saturating arithmetic (biased round to positive infinity) and clearing the lower 16 bits. The upper 16 bits of the Q31 result can be treated as a Q15 value.}.
|
||||
|
||||
\subsubsection{Выбор команд}
|
||||
В наборе команд микропроцессора TMS320C55x \cite{ti:dsp-mnemonics} имеется команда, позволяющая реализовать умножение с насыщением и округлением. \code{MAC} – данная инструкция выполняет умножение и суммирование.
|
||||
\subsubsection{Синтаксис команд}
|
||||
Команда MAC имеет следующий синтаксис \cite[с. 273]{ti:dsp-mnemonics}:
|
||||
\begin{center} \code{MAC[R] ACx, Tx, ACy[, ACy]},\end{center}
|
||||
где MAC – мнемоника команды умножения со сложением, R – признак округления результата операции, Tx - 16-разрядные регистры T0, T1, ACx и ACy – регистр аккумулятор AC0-AC3.
|
||||
|
||||
Необязательный параметр (5) заключён в квадратные скобки.
|
||||
\subsubsection{Операции команд}
|
||||
Эта инструкция выполняет умножение и сложение. Входящие операнды умножителя ACx(32−16) и значение Tx знаково расширяются до 17 битов по формуле (\hrf{eq:expanding})
|
||||
\begin{equation}
|
||||
ACy = ACy + (ACx * Tx).
|
||||
\label{eq:expanding}
|
||||
\end{equation}
|
||||
Команда работает со следующими особенностями:
|
||||
\begin{itemize}
|
||||
\item если выставлен флаг \textbf{FRCT}, вывод умножителя сдвигается влево на один разряд;
|
||||
\item обнаружение переполнения при умножении зависит от флага \textbf{SMUL};
|
||||
\item 32-разрядный результат умножения знаково расширяется до 40 бит и добавляется к аккумулятору-источнику \textbf{ACy};
|
||||
\item округление производится согласно \textbf{RDM}, если к инструкции применяется необязательное ключевое слово \textbf{R};
|
||||
\item обнаружение переполнения при сложении зависит от \textbf{M40}. Если обнаружено переполнение, конечный аккумулятор выставляет статусный бит \textbf{ACOVy};
|
||||
\item когда обнаруживается переполнение при сложении, аккумулятор насыщается согласно \textbf{SATD}.
|
||||
\end{itemize}
|
||||
\subsubsection{Форматы команд}
|
||||
Команда \code{MAC[R] ACx, Tx, ACy[, ACy]} имеет следующий формат (opcode):
|
||||
|
||||
\begin{center} \verb|0101011E DDSSss0%| \end{center}
|
||||
где двоичными цифрами показаны поля кодов команд \cite[с. 779-788]{ti:dsp-mnemonics}, DD – поле регистра-аккумулятора ACy, SS – поле регистра-аккумулятора ACx, ss – поле временного регистра-источника, \% – поле округления.
|
||||
|
||||
Двухразрядное поле регистра-аккумулятора DD кодируется следующим образом:
|
||||
\begin{itemize}
|
||||
\item 00 – регистр-аккумулятор AC0;
|
||||
\item 01 – регистр-аккумулятор AC1;
|
||||
\item 10 – регистр-аккумулятор AC2;
|
||||
\item 11 – регистр-аккумулятор AC3.
|
||||
\end{itemize}
|
||||
|
||||
Двухразрядное поле регистра-аккумулятора SS (ACw, ACx, ACy, ACz) кодируется следующим образом:
|
||||
\begin{itemize}
|
||||
\item 00 – регистр-аккумулятор AC0;
|
||||
\item 01 – регистр-аккумулятор AC1;
|
||||
\item 10 – регистр-аккумулятор AC2;
|
||||
\item 11 – регистр-аккумулятор AC3.
|
||||
\end{itemize}
|
||||
|
||||
Двухразрядное поле временного регистра-источника ss (Tx, Ty) кодируется следующим образом:
|
||||
\begin{itemize}
|
||||
\item 00 – временный регистр T0;
|
||||
\item 01 – временный регистр T1;
|
||||
\item 10 – временный регистр T2;
|
||||
\item 11 – временный регистр T3.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Методика разработки функции}
|
||||
Входными операндами команд, выполняемых умножителями-аккумуляторами \cite[с. 30]{dsp:lectures}, могут быть (рисунок \hrf{pic:mac}):
|
||||
\begin{itemize}
|
||||
\item 17 разрядов регистров аккумуляторов AC0-AC3 (с 32 до 15);
|
||||
\item числа во временных регистрах T0-T3, расширенные до 17 разрядов;
|
||||
\item константы из кода команд, расширенные до 17 разрядов;
|
||||
\item содержимое 16-разрядной ячеек памяти, расширенное до 17 разрядов.
|
||||
\end{itemize}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[height=5cm]{01lab-rpt-mac.png}
|
||||
\caption{Умножение с накоплением}
|
||||
\label{pic:mac}
|
||||
\end{figure}
|
||||
Умножение с накоплением чисел разной разрядности происходит как показано на рисунке \hrf{pic:mac}. Для повторения этого действия в самостоятельно написанной функции необходимо переместить параметр, переданный в регистре \code{T0} в регистр большей разрядности \code{AC1} (строка \hrf{line:moving-to-hi}). Также необходимо выставить флаги работы с дробными числами и насыщения (строки \hrf{line:frac} и \hrf{line:satd}), предварительно сохранив на стеке старое значение регистра статуса \code{ST1_55}\cite[с. 614]{ti:dsp-mnemonics}. Такое поведение описано в полном листинге ассемблерной команды (\hrf{code:prog-asm}).
|
||||
|
||||
\begin{lstlisting}[style=ASMStyle,caption={Описание функции на языке ассемблера}, label={code:prog-asm}]
|
||||
_my_smacr:
|
||||
PSH mmap(ST1_55)
|
||||
BSET FRCT <@\label{line:frac}@>
|
||||
BSET SATD <@\label{line:satd}@>
|
||||
MOV T1,HI(AC1) <@\label{line:moving-to-hi}@>
|
||||
MACR AC1, T0, AC0
|
||||
POP mmap(ST1_55)
|
||||
RET
|
||||
\end{lstlisting}
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,140 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{1}{Исследование команд обработки сигналов}{Микропроцессорные устройства обработки сигналов}{}{А.И. Германчук}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Целью лабораторной работы является знакомство с интегрированной средой разработки программ Code Composer Studio (CCS) компании Texas Instruments. Лабораторная работа заключается в написании в соответствие с выданным индивидуальным заданием текстов несложных программ на языке C и ассемблера, создании нового проекта в CCS, компиляции и отладке разработанных программ с помощью симулятора микропроцессора TMS320C5515 или оценочной платы TMS320C5515 DSP Evaluation Module (TMDXEVM5515).
|
||||
|
||||
\section{Выполнение}
|
||||
Индивидуальным заданием было написание функции умножения и сложения с насыщением и округлением: \code{long _smacr(long src1, int src2, int src3)}. В учебном пособии \cite[с. 6-68]{dsp:lectures} и технической документацией \cite{ti:dsp-mnemonics} описаны как процессы умножения со сложением, так и используемые тестовые данные для проверки работоспособности.
|
||||
|
||||
Согласно документации \cite[с. 77 (3-33)]{ti:dsp-prog-guide} прототип низкоуровневой функции и описание аргументов функции на языке Си имеют вид, представленный в таблице \hrf{table:prototype}. Функция осуществляет умножение операторов \code{op1} и \code{op2}, сдвиг полученного результата влево на один разряд, складывает результат со значением параметра \code{src}, округляет результат, добавляя число 215 и обнуляет младшие 16 разрядов.
|
||||
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\caption{Прототип и описание действия функции}
|
||||
\label{table:prototype}
|
||||
\begin{tabular}{|p{55mm}|p{110mm}|}
|
||||
\hline
|
||||
Прототип функции & Верхнеуровневое описание \\ [3ex]
|
||||
\hline
|
||||
\multirow{2}{54mm}{\code{long _smacr(long src, int op1, int op2)}} & Multiplies \code{op1} and \code{op2}, shifts the result left by 1, adds the result to \code{src}, and then rounds the result by adding 215 and zeroing out the lower 16 bits. (SATD, SMUL, and FRCT bits set).\\
|
||||
\cline{2-2}
|
||||
& Returns the saturated sum of src1 and the fractional-mode product of src2 and src3. The sum is rounded as if the intrinsic \code{_sround} were used. \\ [5ex]
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
В наборе команд микропроцессора TMS320C55x \cite{ti:dsp-mnemonics} имеется команда, позволяющая реализовать умножение с насыщением и округлением. \code{MAC} – данная инструкция выполняет умножение и суммирование.
|
||||
|
||||
Команда MAC имеет следующий синтаксис \cite[с. 273]{ti:dsp-mnemonics}:
|
||||
\begin{center} \code{MAC[R] ACx, Tx, ACy[, ACy]},\end{center}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item [] MAC – мнемоника команды умножения со сложением;
|
||||
\item [] R – признак округления результата операции;
|
||||
\item [] Tx - 16-разрядные регистры T0, T1;
|
||||
\item [] ACx и ACy – регистр аккумулятор AC0-AC3.
|
||||
\end{itemize}
|
||||
Необязательный параметр (5) заключён в квадратные скобки.
|
||||
|
||||
Эта инструкция выполняет умножение и сложение. Входящие операнды умножителя ACx(32−16) и значение Tx знаково расширяются до 17 битов по формуле (\hrf{eq:expanding})
|
||||
\begin{equation}
|
||||
ACy = ACy + (ACx * Tx).
|
||||
\label{eq:expanding}
|
||||
\end{equation}
|
||||
|
||||
Умножение с накоплением чисел разной разрядности происходит как показано на рис. \hrf{pic:mac}. Для повторения этого действия необходимо переместить параметр, переданный в регистре \code{T0} в регистр большей разрядности \code{AC1} (строка \hrf{line:moving-to-hi}). Полный листинг ассемблерной команды (\hrf{code:prog-asm}) представлен в приложении \hrf{appendix:fulls}.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[height=5cm]{01lab-rpt-mac.png}
|
||||
\caption{Умножение с накоплением}
|
||||
\label{pic:mac}
|
||||
\end{figure}
|
||||
|
||||
\section{Результаты работы}
|
||||
После запуска проверочной программы (\hrf{code:prog-c}) представленной в приложении \hrf{appendix:fulls} было доказано совпадение результатов библиотечной функции и описанной в листинге \hrf{code:prog-asm}. Снимки экрана, демонстрирующие идентичность полученных результатов представлены на рис. \hrf{pic:result}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{01lab-rpt-1.png}
|
||||
\end{subfigure}
|
||||
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{01lab-rpt-2.png}
|
||||
\end{subfigure}
|
||||
\caption{Результаты вызова функций \code{_smacr} и \code{lab1}}
|
||||
\label{pic:result}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Полные листинги программ}
|
||||
\label{appendix:fulls}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Программа на языке С}, label=code:prog-c]
|
||||
#include "stdio.h"
|
||||
|
||||
#define SIZE 2
|
||||
|
||||
//long _smacr(long src1, int src2, int src3);
|
||||
extern long lab1(long, int, int);
|
||||
|
||||
void main(void) {
|
||||
//Локальные переменные
|
||||
int i;
|
||||
int intValues[] = {0x00008001, 0xFFFE0001};
|
||||
long longValues[] = {0x00008001, 0xFFFE0001};
|
||||
|
||||
long result_lib;
|
||||
long result_lab;
|
||||
for (i = 0; i < SIZE; ++i) {
|
||||
result_lib = 10;
|
||||
result_lab = 10;
|
||||
result_lib = _smacr(result_lib, longValues[i], intValues[i]);
|
||||
result_lab = lab1(result_lab, longValues[i], intValues[i]);
|
||||
int neq = result_lib - result_lab;
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[style=ASMStyle,caption={Описание функции на языке ассемблера}, label=code:prog-asm]
|
||||
.def _lab1
|
||||
.text
|
||||
|
||||
_lab1:
|
||||
BSET FRCT
|
||||
BSET SATD
|
||||
MOV T1,HI(AC1) <@\label{line:moving-to-hi}@>
|
||||
MACR AC1, T0, AC0
|
||||
RET
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationTop
|
||||
\newcolumntype{s}{>{\tiny{}}c}
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{домашней}{2}{Библиотечная подпрограмма}{Микропроцессорные устройства обработки сигналов}{}{проф. каф. ИУЗ, д.т.н. \\В.С. Выхованец}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\addtocontents{toc}{\vspace{2ex}}
|
||||
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Задача}
|
||||
Темой домашнего задания является изучение алгоритмов и исследование способов их реализации, выполняющих Вычисление арктангенсов \code{atan16} \cite[с. 32 (4-11)]{ti:dsp-lib-prog-ref}. Для выполнения домашнего задания необходимо:
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item ознакомиться с рекомендованной литературой \cite[с. 102-165]{dsp:lectures};
|
||||
\item привести в отчете теоретические сведения по методам обработки сигналов;
|
||||
\item описать алгоритм обработки сигналов и данных;
|
||||
\item прокомментировать текст библиотечной функции;
|
||||
\item оформить\cite{gost:texts} отчет\cite{gost:links} по домашнему заданию\cite{bmstu:dsp-methodics2}.
|
||||
\end{enumerate}
|
||||
|
||||
Основным результатом домашнего задания является комментированный текст библиотечной функции на языке ассемблера, а также описание выполняемого ею алгоритма цифровой обработки сигналов и данных.
|
||||
|
||||
\section{Выполнение}
|
||||
\subsection{Теоретические сведения}
|
||||
Арктангенс (arctg или arctan) – это обратная тригонометрическая функция. Арктангенс x определяется как функция, обратная к тангенсу x, где x – любое число ($x\in\mathbb{R}$). Если тангенс угла у равен х ($\tan(y) = x$), значит арктангенс x равняется y:
|
||||
|
||||
\[ \arctan(x) = \tan^{-1} x = y, \text{причем} -\pi / 2 < y < \pi / 2.\]
|
||||
|
||||
При этом $\tan^{-1}x$ означает обратный тангенс, а не тангенс в степени -1. Функция арктангенс непрерывна на своей области определения, то есть для всех x. Функция арктангенс является нечетной:
|
||||
|
||||
\[ \arctan(–x) = \arctan(–\tan \arctan x) = \arctan(\tan(–\arctan x)) = –\arctan x.\]
|
||||
|
||||
График арктангенса получается из графика тангенса, если поменять местами оси абсцисс и ординат. Чтобы устранить многозначность, множество значений ограничивают интервалом, на котором функция монотонна. Такое определение называют главным значением арктангенса.
|
||||
|
||||
\subsection{Интерфейс библиотечной функции}
|
||||
Согласно документации \cite[c. 32 (4-11)]{ti:dsp-lib-prog-ref} функция вычисления арктангенса вектора значений имеет прототип, представленный в листинге \hrf{lst:atan-proto}:
|
||||
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Прототип функции вычисления арктангенса},label={lst:atan-proto}]
|
||||
\code{ushort oflag = atan16 (DATA *x, DATA *r, ushort nx)}
|
||||
\end{lstlisting}
|
||||
где \code{ushort} – тип данных, определенный как \code{unsigned short}; \code{DATA} – тип данных, являющийся синонимом \code{int}; \code{x} – указатель на вектор исходных данных; \code{r} – указатель на вектор выходных данных арктангенса \code{x} в диапазоне $[-\pi/4, \pi/4]$, при этом, \code{atan(1.0) = 0.7854 или 6478h}; \code{nx} – число элементов в векторах \code{x} и \code{r}. Векторы входных и выходных данных функции представляют собой одномерные массивы, элементами которых являются 16-разрядные числа (целые или дробные),
|
||||
пронумерованные в порядке увеличения их адресов в памяти данных (таблица \hrf{table:vectors}).
|
||||
\begin{table}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\caption{Общий вид вектора функции atan16}
|
||||
\label{table:vectors}
|
||||
\begin{tabular}{|c|c|c|c|c|c|c|}
|
||||
\hline
|
||||
Адрес & x(+0) & x+1 & x+2 & x... & x+(nx-2) & x+(nx-1) \\ [0.5ex]
|
||||
\hline
|
||||
Индекс & x[0] & x[1] & x[2] & x... & x[nx-2] & x[nx-1] \\ [1ex]
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Длина векторов \code{nx} задается в формате N16 – беззнаковом 16-разрядном целочисленном формате. Сами массивы, а также их элементы выравнены по границе слова. Разрешается использование одного и того же указателя для задания двух векторов\footnote{In-place processing allowed (r can be equal to x)}. Функция управляет флагом переполнения \code{oflag}, который выставляется в 1 или 0 если произошло или не произошло 32-разрядное переполнение, соответственно.
|
||||
|
||||
\subsection{Описание алгоритма}
|
||||
Функция \code{atan16} подсчитывает значение арктангенса каждого элемента вектора \code{x}, Результат записывается в выходной вектор \code{r} в диапазоне $[-\pi/4, \pi/4]$ радиан. Например, если x = [0x7fff, 0x3505, 0x1976, 0x0], что
|
||||
эквивалентно $\tan(\frac{\pi}{4})$, $\tan(\frac{\pi}{8})$, $\tan(\frac{\pi}{16})$, $\tan(0)$ в формате float, то вызов функции \code{atan16(x, r, 4);} должен выдать r = [0x6478, 0x3243, 0x1921, 0x0], что эквивалентно $\frac{\pi}{4}$, $\frac{\pi}{8}$, $\frac{\pi}{16}$, $0$.
|
||||
|
||||
Реализуемый функцией \code{atan16} алгоритм описан на языке программирования Cи и приведен на листинге \hrf{lst:atan-alg}.
|
||||
|
||||
\begin{lstlisting}[language=C, style=CCodeStyle, caption = {Алгоритм вычисления арктангенса}, label={lst:atan-alg}]
|
||||
#define DATA int
|
||||
#define ushort unsigned short
|
||||
void atan(DATA* x, DATA* r, ushort nx) {
|
||||
ushort i;
|
||||
for (i = 0; i < nx; i++) {
|
||||
r[i] = atan(x[i]);
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
В теле основного цикла функции выполняется извлечение очередных элементов вектороа \code{x} и передача их в функцию \code{atan()}, с последующим присваиванием результата в соответствующий индекс выходного вектора \code{r}. Для организации цикла используется целочисленная переменная \code{i}, которая задает индекс элементов векторов.
|
||||
Комментированный текст библиотечной функции \code{atan()} на основе сведений о мнемониках \cite{ti:dsp-mnemonics} приведен в приложении \hrf{appendix:asm}.
|
||||
|
||||
\section{Выводы}
|
||||
В домашнем задании 2 приведено описание библиотечной функции вычисления арктангенса вектора. Для функции вычисления значений арктангенса разработан алгоритм на языке Си и приведен комментированный текст его реализации библиотечной функцией на языке ассемблера для микропроцессора цифровой обработки сигналов TMS320C5515.
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\begin{appendices}
|
||||
\renewcommand{\thesubsection}{\Asbuk{subsection}}
|
||||
\subsection{Библиотечная функция atan()}
|
||||
\label{appendix:asm}
|
||||
\begin{lstlisting}[style=ASMStyle]
|
||||
;<@\lh{dkgreen}{************************************************************}@>
|
||||
;<@\lh{dkgreen}{* Version 3.00.00 }@>
|
||||
;<@\lh{dkgreen}{************************************************************}@>
|
||||
;<@\lh{dkgreen}{* Функция: atan16}@>
|
||||
;<@\lh{dkgreen}{* Процессор: C55xx}@>
|
||||
;<@\lh{dkgreen}{* Описание: реализация арктангенса}@>
|
||||
;<@\lh{dkgreen}{* Использование: short atan16( DATA *x, DATA *r, int nx)} @>
|
||||
;<@\lh{dkgreen}{* nx : число элементов x и r}@>
|
||||
;<@\lh{dkgreen}{* r[i] = atan(x[i]) где x и r в формате Q15}@>
|
||||
;<@\lh{dkgreen}{* return 0}@>
|
||||
;<@\lh{dkgreen}{*}@>
|
||||
;<@\lh{dkgreen}{* Производительность (бенчмарки):}@>
|
||||
;<@\lh{dkgreen}{* Циклов: (5 * nx) + 14 (Асимптотическая сложность О(n))}@>
|
||||
;<@\lh{dkgreen}{* Объём кода (в байтах): 49}@>
|
||||
;<@\lh{dkgreen}{*}@>
|
||||
;<@\lh{dkgreen}{************************************************************}@>
|
||||
|
||||
.mmregs ;<@\lh{dkgreen}{Разрешение MMR-регистров}@>
|
||||
.cpl_on ;<@\lh{dkgreen}{Режим компилятора}@>
|
||||
.arms_on ;<@\lh{dkgreen}{Сигнальный режим адресации}@>
|
||||
|
||||
;<@\lh{dkgreen}{-----------------------------------------------------------}@>
|
||||
;<@\lh{dkgreen}{| Тело функции}@>
|
||||
;<@\lh{dkgreen}{-----------------------------------------------------------}@>
|
||||
.def _atan16
|
||||
.text
|
||||
_atan16:
|
||||
; <@\lh{dkgreen}{* AR0 присваивается \_x}@>
|
||||
; <@\lh{dkgreen}{* AR1 присваивается \_r}@>
|
||||
; <@\lh{dkgreen}{* T0 присваивается \_nx}@>
|
||||
PSH T3 ; <@\lh{dkgreen}{использовать временный регистр}@>
|
||||
|| BSET FRCT ; <@\lh{dkgreen}{режим рациональных чисел}@>
|
||||
SUB #1, T0 ; nx - 1
|
||||
MOV T0, BRC0 ; <@\lh{dkgreen}{повторить nx раз}@>
|
||||
MOV #2596 << #16, AC3 ; <@\lh{dkgreen}{старшие разряды AC3 = C5}@>
|
||||
MOV #-9464 << #16, AC1 ; <@\lh{dkgreen}{старшие разряды AC1 = C3}@>
|
||||
MOV #32617 << #16, AC2 ; <@\lh{dkgreen}{старшие разряды AC2 = C1}@>
|
||||
|
||||
; <@\lh{dkgreen}{Загрузка T3 на инструкцию раньше, чем умножение его}@>
|
||||
; <@\lh{dkgreen}{использует, приведёт к задержке в один такт}@>
|
||||
|
||||
MPYMR T3=*AR0+, AC3, AC0 ; <@\lh{dkgreen}{непосредственное умножение значения из х}@>
|
||||
|| RPTBLOCAL loop1 - 1 ; <@\lh{dkgreen}{и запустить цикл}@>
|
||||
MACR AC0,T3,AC1,AC0; <@\lh{dkgreen}{вычислить смещение для следующего значения}@>
|
||||
MPYR T3, AC0 ; <@\lh{dkgreen}{сохранить временный результат умножения}@>
|
||||
|| MOV *AR0+, T1 ; <@\lh{dkgreen}{сместить указатель на следующее значение х}@>
|
||||
MACR AC0,T3,AC2,AC0; <@\lh{dkgreen}{вычислить смещение для следующего значения}@>
|
||||
MPYR T3, AC0 ; <@\lh{dkgreen}{сохранить временный результат умножения}@>
|
||||
|| MOV T1, T3 ; <@\lh{dkgreen}{сохранить значение итератора}@>
|
||||
MOV HI(AC0), *AR1+ ; <@\lh{dkgreen}{сохранить старшую часть результата вычислений}@>
|
||||
|| MPYR T1, AC3, AC0 ; <@\lh{dkgreen}{следующая итерация}@>
|
||||
|
||||
loop1: ; <@\lh{dkgreen}{цикл}@>
|
||||
POP T3 ;
|
||||
|| BCLR FRCT ; <@\lh{dkgreen}{вернуться в режим обычного C}@>
|
||||
MOV #0, T0 ; <@\lh{dkgreen}{вернуть значение ОК}@>
|
||||
|| RET ; <@\lh{dkgreen}{(нет возможных ошибок)}@>
|
||||
\end{lstlisting}
|
||||
\end{appendices}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
Официальное описание из комментария к функции хорошо объясняет, что именно она делает:
|
||||
\begin{verbatim}
|
||||
Description: minimum Value and Index of the minimum
|
||||
element of a vector
|
||||
\end{verbatim}
|
||||
|
||||
Снаружи функция будет вызываться вот так
|
||||
\begin{verbatim}
|
||||
void minvec (DATA *x, ushort nx, DATA *val, DATA *idx)
|
||||
\end{verbatim}
|
||||
То есть передадим
|
||||
\begin{itemize}
|
||||
\item вектор (массив чисел) \code{DATA *x}, важно, что вектор у нас из типа \code{DATA}, который, на самом деле \code{ushort (unsigned short)}, 16-разрядный, то есть при подсчёте сдвига по вектору для получения следующего значения - нужно смещаться на 2 байта.
|
||||
\item длину вектора \code{ushort nx},
|
||||
\item указатель на полученное значение \code{DATA *val},
|
||||
\item указатель на полученный индекс \code{DATA *idx}.
|
||||
\end{itemize}
|
||||
|
||||
Для языка ассемблера, умеющего манипулировать только регистрами, важно понимать, в какие именно регистры будут положены эти параметры
|
||||
\begin{itemize}
|
||||
\item \code{DATA *x} - указатель AR0
|
||||
\item \code{ushort nx} - регистр T0
|
||||
\item \code{DATA *val} - указатель AR1
|
||||
\item \code{DATA *idx} - указатель AR2
|
||||
\end{itemize}
|
||||
|
||||
дальше последовательно опишем что именно делает функция и как:
|
||||
|
||||
\begin{verbatim}
|
||||
.text
|
||||
.global _minvec
|
||||
_minvec:
|
||||
\end{verbatim}
|
||||
|
||||
до вызова функции система находилась в каком-то статусе, соответственно, нам нужно этот статус сохранить, чтобы наша функция ничего не сломала
|
||||
\begin{verbatim}
|
||||
PSH mmap(ST0_55) ; Сохранение регистров статуса на стеке
|
||||
PSH mmap(ST1_55)
|
||||
PSH mmap(ST2_55)
|
||||
PSH mmap(ST3_55)
|
||||
\end{verbatim}
|
||||
|
||||
далее происходит одновременное действие, знак \code{II} показывает, что два этих действия будут выполняться параллельно. Запись очередного значения из вектора во временный регистр \code{AC1} и вычитание 2 из регистра \code{T0}. Запись \code{*AR0+} означает, что мы не только разыменовали указатель (получили значение по указателю, знак *), но и сдвинули указатель вектора на следующий адрес (знак +)
|
||||
\begin{verbatim}
|
||||
MOV *AR0+,AC1
|
||||
|| SUB #2,T0
|
||||
\end{verbatim}
|
||||
|
||||
Сохраним значение из \code{T0} в \code{BRC0} и одновременно запишем 0 в \code{AR3}. Это вспомогательное действие, чтобы высвободить регистры, при помощи которых мы будем делать дальнейшие вычисления.
|
||||
\begin{verbatim}
|
||||
MOV T0,BRC0
|
||||
|| MOV #0,AR3
|
||||
\end{verbatim}
|
||||
|
||||
Далее происходит обнуление регистра \code{T0} и цикл между значением \code{RPTBLOCAL} и \code{end_block:}
|
||||
\begin{verbatim}
|
||||
MOV #0,T0
|
||||
|| RPTBLOCAL end_block-1
|
||||
\end{verbatim}
|
||||
|
||||
В цикле мы кладём следующее значение из вектора в \code{AC0}, помнишь, мы уже клали значение из вектора в \code{AC1}, вот теперь в \code{AC0}. Мнемоника \code{MAR} в явном виде не описана в документации, но есть предположение, что MAR это аббревиатура от Modify Auxiliary Register, то есть по факту это просто увеличение временного указателя на будущий вычисленный индекс на единицу. Напомню, в этот регистр два шага назад, до цикла, мы положили 0, то есть, скорее всего, это будет конечный индекс в векторе, который мы должны вернуть.
|
||||
\begin{verbatim}
|
||||
MOV *AR0+,AC0
|
||||
|| MAR *AR3+
|
||||
\end{verbatim}
|
||||
|
||||
Тут, понятно, мы ищем минимальное из двух значений (мы же положили последовательно два значения из вектора в \code{AC0} и \code{AC1}). Значение, полученное в результате сравнения, будет положено в \code{AC1}\footnote{TMS320C55x-Mnemonic Instruction Set. Reference Guide-2009, p.428}. То, что мы положим минимальное в \code{AC1} даст нам возможность на следующей итерации цикла снова сравнивать с ним прочитанное в \code{AC0} следующее значение из вектора, как мы это делаем на предыдущем шаге.
|
||||
\begin{verbatim}
|
||||
MIN AC0,AC1
|
||||
\end{verbatim}
|
||||
|
||||
Это проверка условия завершения цикла \footnote{TMS320C55x-Mnemonic Instruction Set. Reference Guide-2009, p.749 (XCCPART), p.20(CARRY)} по биту переноса и одновременно вывод информации из \code{AR3} (в котором, напомню, у нас хранился индекс минимального значения в векторе) по указателю \code{AR2}, который, напомню, нам передали с параметрами функции
|
||||
\begin{verbatim}
|
||||
XCCPART end_block, !CARRY
|
||||
|| MOV AR3,*AR2
|
||||
\end{verbatim}
|
||||
|
||||
По завершении цикла, сохраним полученное значение минимума по указателю \code{AR1}, который мы передали снаружи в параметре \code{val}.
|
||||
\begin{verbatim}
|
||||
end_block:
|
||||
MOV AC1,*AR1
|
||||
\end{verbatim}
|
||||
|
||||
Вернём на место статус системы из сохранённого ранее и выйдем из функции
|
||||
\begin{verbatim}
|
||||
POP mmap(ST3_55)
|
||||
POP mmap(ST2_55)
|
||||
POP mmap(ST1_55)
|
||||
POP mmap(ST0_55)
|
||||
RET
|
||||
\end{verbatim}
|
||||
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
void minvec (DATA *x, ushort nx, DATA *val, DATA *idx) {
|
||||
while (nx-- >= 0) {
|
||||
if (*val > *(x + nx)) {
|
||||
*val = *(x + nx);
|
||||
*idx = nx;
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{2}{Исследование процессов обработки сигналов}{Микропроцессорные устройства обработки сигналов}{}{А.И. Германчук}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Целью работы является изучение стандартных процедур обработки сигналов и данных, а также их реализация в интегрированной среде проектирования Code Composer Studio версии 5 и на микропроцессоре TMS320C5515 компании Texas Instruments Incorporated. При выполнении лабораторной работы используется симулятор микропроцессора TMS320C5515 или оценочноя плата TMS320C5515 DSP Evaluation Module (TMDXEVM5515).
|
||||
|
||||
\section{Выполнение}
|
||||
Индивидуальным заданием было написание функции вычисления арктангенса числа: \code{ushort atan16(DATA *x, DATA *r, ushort nx)}.
|
||||
|
||||
\section{Результаты работы}
|
||||
После запуска проверочной программы (\hrf{code:prog-c}) представленной в приложении \hrf{appendix:fulls} было доказано совпадение результатов библиотечной функции (листинг \hrf{code:std-asm}) и описанной в дизассемблированном листинге \hrf{code:asm}. Результаты работы профилировщика отражены в таблице \hrf{table:profiler}. Снимки экрана, демонстрирующие идентичность полученных результатов представлены на рис. \hrf{pic:result}.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}
|
||||
\hline
|
||||
Name & Calls & EC Av & EC Ttl & IC Av & IC Ttl & File \\
|
||||
\hline
|
||||
atan(short *, short *, int) & 1 & 969.0 & 969.0 & 3384.0 & 3384.0 & main.c \\
|
||||
\hline
|
||||
null() & 1 & 49.0 & 49.0 & 49.0 & 49.0 & atan16.asm \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Результат работы профилировщика}
|
||||
\label{table:profiler}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{02lab-rpt-1.png}
|
||||
\caption{Результат вычислений}
|
||||
\label{pic:result}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Полные листинги программ}
|
||||
\label{appendix:fulls}
|
||||
\begin{lstlisting}[style=ASMStyle,caption={Стандартный ассемблерный листинг}, label=code:std-asm]
|
||||
_atan16:
|
||||
;* AR0 assigned to _x
|
||||
;* AR1 assigned to _r
|
||||
;* T0 assigned to _nx
|
||||
PSH T3
|
||||
|| BSET FRCT ;fractional mode
|
||||
SUB #1, T0 ;nx-1
|
||||
MOV T0, BRC0 ;repeat nx times
|
||||
MOV #2596 << #16, AC3 ; AC3.Hi = C5
|
||||
MOV #-9464 << #16, AC1 ; AC1.Hi = C3
|
||||
MOV #32617 << #16, AC2 ; AC2.Hi = C1
|
||||
|
||||
MPYMR T3=*AR0+, AC3, AC0 ; (Prime the Pump)
|
||||
|| RPTBLOCAL loop1-1
|
||||
MACR AC0, T3, AC1, AC0
|
||||
MPYR T3, AC0
|
||||
||MOV *AR0+, T1 ; (for next iteration)
|
||||
MACR AC0, T3, AC2, AC0
|
||||
MPYR T3, AC0
|
||||
||MOV T1, T3
|
||||
MOV HI(AC0), *AR1+ ;save result
|
||||
||MPYR T1, AC3, AC0 ; (for next iteration)
|
||||
|
||||
loop1:
|
||||
POP T3
|
||||
|| BCLR FRCT ;return to standard C
|
||||
MOV #0, T0 ;return OK value (no possible error)
|
||||
|| RET
|
||||
\end{lstlisting}
|
||||
|
||||
\newpage
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Программа на языке С}, label=code:prog-c]
|
||||
#include "TMS320.h"
|
||||
|
||||
#define NX 7
|
||||
#define FNAME "t1"
|
||||
#define MAXERROR 40
|
||||
|
||||
ushort atan16(DATA *x, DATA *r, ushort nx);
|
||||
|
||||
short atan(DATA *x, DATA *r, int nx) {
|
||||
long long ac3 = ((long long) 2596) << 16; // AC3.Hi = C5 0.0396118164062500
|
||||
long long ac1 = ((long long) -9464) << 16; // AC1.Hi = C3 -0.1444091796875000
|
||||
long long ac2 = ((long long) 32617) << 16; // AC2.Hi = C1 0.4976959228515625
|
||||
while (--nx >= 0) {
|
||||
long long ac0;
|
||||
DATA t3 = *(x + nx);
|
||||
ac0 = (t3 * (ac3 >> 15)) << 1; // MPYMR T3=*AR0+, AC3, AC0
|
||||
ac0 = ((ac0 >> 15) * t3) + ac1; // MACR AC0, T3, AC1, AC0
|
||||
ac0 = ((ac0 >> 15) * t3); // MPYR T3, AC0
|
||||
|
||||
ac0 = ((ac0 >> 15) * t3) + ac2; // MACR AC0, T3, AC2, AC0
|
||||
ac0 = ((ac0 >> 15) * t3); // MPYR T3, AC0
|
||||
*(r + nx) = ac0 >> 16; // MOV HI(AC0), *AR1+
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
DATA x[NX] = {8192,16384,24576,32767,-8192,-16384,-24576};
|
||||
DATA rtest[NX] ={8027,15192,21086,25735,-8028,-15193,-21087};
|
||||
DATA r[NX];
|
||||
DATA r0[NX];
|
||||
|
||||
(void)atan16(x, r0, NX);
|
||||
atan(x, r, NX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\newpage
|
||||
\begin{lstlisting}[style=ASMStyle,caption={Дизассемблированная программа}, label=code:asm]
|
||||
atan:
|
||||
4ee9 AADD #-23,SP
|
||||
c408 MOV T0,*SP(#04h)
|
||||
eb0495 MOV XAR1,dbl(*SP(#02h))
|
||||
eb0085 MOV XAR0,dbl(*SP(#00h))
|
||||
long long ac3 = ((long long) 2596) << 16;
|
||||
7a0a240a MOV #2596 << #16,AC0
|
||||
46a3_110700 BSET ST1_M40 || SFTL AC0,#0,AC0
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb0c18 MOV AC1,dbl(*SP(#06h))
|
||||
eb1008 MOV AC0,dbl(*SP(#08h))
|
||||
long long ac1 = ((long long) -9464) << 16;
|
||||
7adb080a MOV #-9464 << #16,AC0
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb1418 MOV AC1,dbl(*SP(#0ah))
|
||||
eb1808 MOV AC0,dbl(*SP(#0ch))
|
||||
long long ac2 = ((long long) 32617) << 16;
|
||||
7a7f690a_47a2 MOV #32617 << #16,AC0 || BCLR ST1_M40
|
||||
46a3_110700 BSET ST1_M40 || SFTL AC0,#0,AC0
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb1c18 MOV AC1,dbl(*SP(#0eh))
|
||||
eb2008 MOV AC0,dbl(*SP(#10h))
|
||||
while (--nx >= 0)
|
||||
a908 MOV *SP(#04h),AR1
|
||||
4219 SUB #1,AR1
|
||||
c908 MOV AR1,*SP(#04h)
|
||||
6d2900d6 BCC C$DW$L$_atan$2$E,AR1 < #0
|
||||
DATA t3 = *(x + nx);
|
||||
2294 MOV AR1,T0
|
||||
ed00bf MOV dbl(*SP(#00h)),XAR3
|
||||
a96b MOV *AR3(T0),AR1
|
||||
c92c MOV AR1,*SP(#16h)
|
||||
ac0 = (t3 * (ac3 >> 15)) << 1;
|
||||
ed1018 MOV dbl(*SP(#08h)),AC1
|
||||
ed0c28 MOV dbl(*SP(#06h)),AC2
|
||||
c21a_98 MOV AC2,mmap(@AC1G)
|
||||
a02c MOV *SP(#16h),AC0
|
||||
46a2_115531 BCLR ST1_M40 || SFTS AC1,#-15,AC1
|
||||
6c00207d CALL _mpylli
|
||||
46a3 BSET ST1_M40
|
||||
4450 SFTS AC0,#1
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb2418 MOV AC1,dbl(*SP(#12h))
|
||||
eb2808 MOV AC0,dbl(*SP(#14h))
|
||||
ac0 = ((ac0 >> 15) * t3) + ac1;
|
||||
ed2808 MOV dbl(*SP(#14h)),AC0
|
||||
ed2418 MOV dbl(*SP(#12h)),AC1
|
||||
c114_98 MOV AC1,mmap(@AC0G)
|
||||
a12c MOV *SP(#16h),AC1
|
||||
46a2_110531 BCLR ST1_M40 || SFTS AC0,#-15,AC0
|
||||
6c00207d CALL _mpylli
|
||||
ed1428 MOV dbl(*SP(#0ah)),AC2
|
||||
ed1818 MOV dbl(*SP(#0ch)),AC1
|
||||
c21a_98 MOV AC2,mmap(@AC1G)
|
||||
46a3 BSET ST1_M40
|
||||
2401 ADD AC0,AC1
|
||||
101720 SFTL AC1,#-32,AC0
|
||||
eb2408 MOV AC0,dbl(*SP(#12h))
|
||||
eb2818 MOV AC1,dbl(*SP(#14h))
|
||||
ac0 = ((ac0 >> 15) * t3);
|
||||
ed2418 MOV dbl(*SP(#12h)),AC1
|
||||
ed2808 MOV dbl(*SP(#14h)),AC0
|
||||
c114_98 MOV AC1,mmap(@AC0G)
|
||||
a12c MOV *SP(#16h),AC1
|
||||
46a2_110531 BCLR ST1_M40 || SFTS AC0,#-15,AC0
|
||||
6c00207d CALL _mpylli
|
||||
46a3 BSET ST1_M40
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb2418 MOV AC1,dbl(*SP(#12h))
|
||||
eb2808 MOV AC0,dbl(*SP(#14h))
|
||||
ac0 = ((ac0 >> 15) * t3) + ac2;
|
||||
ed2808 MOV dbl(*SP(#14h)),AC0
|
||||
ed2418 MOV dbl(*SP(#12h)),AC1
|
||||
c114_98 MOV AC1,mmap(@AC0G)
|
||||
a12c MOV *SP(#16h),AC1
|
||||
46a2_110531 BCLR ST1_M40 || SFTS AC0,#-15,AC0
|
||||
6c00207d CALL _mpylli
|
||||
ed1c28 MOV dbl(*SP(#0eh)),AC2
|
||||
ed2018 MOV dbl(*SP(#10h)),AC1
|
||||
c21a_98 MOV AC2,mmap(@AC1G)
|
||||
46a3 BSET ST1_M40
|
||||
2401 ADD AC0,AC1
|
||||
101720 SFTL AC1,#-32,AC0
|
||||
eb2408 MOV AC0,dbl(*SP(#12h))
|
||||
eb2818 MOV AC1,dbl(*SP(#14h))
|
||||
ac0 = ((ac0 >> 15) * t3);
|
||||
ed2418 MOV dbl(*SP(#12h)),AC1
|
||||
ed2808 MOV dbl(*SP(#14h)),AC0
|
||||
c114_98 MOV AC1,mmap(@AC0G)
|
||||
a12c MOV *SP(#16h),AC1
|
||||
46a2_110531 BCLR ST1_M40 || SFTS AC0,#-15,AC0
|
||||
6c00207d CALL _mpylli
|
||||
46a3 BSET ST1_M40
|
||||
104720 SFTL AC0,#-32,AC1
|
||||
eb2418 MOV AC1,dbl(*SP(#12h))
|
||||
eb2808 MOV AC0,dbl(*SP(#14h))
|
||||
*(r + nx) = ac0 >> 16;
|
||||
a408 MOV *SP(#04h),T0
|
||||
ed04bf MOV dbl(*SP(#02h)),XAR3
|
||||
ed2418 MOV dbl(*SP(#12h)),AC1
|
||||
ed2808 MOV dbl(*SP(#14h)),AC0
|
||||
c114_98 MOV AC1,mmap(@AC0G)
|
||||
bc6b MOV HI(AC0),*AR3(T0)
|
||||
a908 MOV *SP(#04h),AR1
|
||||
4219 SUB #1,AR1
|
||||
c908 MOV AR1,*SP(#04h)
|
||||
6d59ff2a BCC C$L1,AR1 >= #0
|
||||
return 0;
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationBottom
|
||||
\newcolumntype{s}{>{\tiny{}}c}
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{домашней}{3}{Звуковой эффект}{Микропроцессорные устройства обработки сигналов}{}{проф. каф. ИУЗ, д.т.н. \\В.С. Выхованец}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\addtocontents{toc}{\vspace{2ex}}
|
||||
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Постановка задачи}
|
||||
Целью домашнего задания является разработка алгоритма звукового эффекта «Контроллер динамического диапазона». Для выполнения домашнего задания необходимо:
|
||||
\begin{itemize}
|
||||
\item ознакомиться с рекомендованной литературой \cite{dsp:lectures};
|
||||
\item привести в отчете описание звукового эффекта;
|
||||
\item описать алгоритм обработки сигналов и данных.
|
||||
\end{itemize}
|
||||
При разработке алгоритма необходимо учесть, что исходный звуковой сигнал поступает на обработку от звукового кодека по одному отсчету, получаемому при вызове функции \code{sam = GetSample()}, где \code{sam} – текущий входной отсчет звукового сигнала в формате с фиксированной запятой. Обработанные отсчеты передаются звуковому кодеку обратно путем вызова функции \code{PutSample(res)}, где \code{res} – текущий выходной отсчет звукового сигнала в формате с фиксированной запятой.
|
||||
|
||||
\section{Выполнение}
|
||||
\subsection{Описание звукового эффекта}
|
||||
Контроллер динамического диапазона - это адаптивная регулировка динамического диапазона сигнала. Динамический диапазон - это соотношение между наибольшими и наименьшими значениями, которые может принять определенная величина. Существует несколько типов контроллеров. В данной лабораторной работе будет рассматриваться ограничитель. Назначение ограничителя состоит в том, чтобы обеспечить контроль над самыми высокими пиками сигнала, но при этом, как можно меньше изменять динамику сигнала. Это достигается за счёт использования характеристической кривой с бесконечным отношением \cite[с. 109]{dsp:dafx}. Ограничитель динамического диапазона подавляет громкость звуков, пересекающих заданный порог (рисунок \hrf{pic:limiter}).
|
||||
|
||||
\begin{figure}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\def\svgwidth{100mm}
|
||||
\input{pics/02-dsp-03lab-limiter.pdf_tex}
|
||||
\caption{Иллюстрация работы ограничителя сигнала}
|
||||
\label{pic:limiter}
|
||||
\end{figure}
|
||||
|
||||
Для достижения плавности кривой применяемого ослабления громкости используются такие параметры, как время атаки и высвобождения. Время атаки и время высвобождения соответствуют времени, за которое сигнал увеличивается или уменьшается до конечного значения (рисунок \hrf{pic:limiter-explain}). На рисунке видно, что при отсутствии времени атаки и освобождения усиление применяется сразу, создавая неплавные «обрезанные» кривые (жёсткое урезание).
|
||||
|
||||
\begin{figure}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\def\svgwidth{170mm}
|
||||
\input{pics/02-dsp-03lab-limiter-explain.pdf_tex}
|
||||
\caption{Иллюстрация влияния времени атаки и освобождения}
|
||||
\label{pic:limiter-explain}
|
||||
\end{figure}
|
||||
|
||||
Ограничитель обычно используется для того, чтобы «поймать» самые громкие моменты источника, уменьшив их таким образом, чтобы защитить от нежелательных искажений и сохранить целостность общего баланса звука.
|
||||
|
||||
\subsection{Математическое описание ограничителя}
|
||||
\label{sect:description}
|
||||
Динамическая обработка выполняется усилительными устройствами, где коэффициент усиления автоматически регулируется уровнем входного сигнала. Динамическая обработка проходит в несколько этапов:
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item Сначала используется схема определения амплитуды/уровня по алгоритму PEAK \cite[с. 107]{dsp:dafx}.
|
||||
|
||||
В начале алгоритма значение переменной $X_{peak}$ равно нулю. Далее сравнивается модуль поступающего сигнала $|x(n)|$ с предыдущим значением $X_{peak}$. В случае если значение модуля поступающего сигнала больше, то значение $X_{peak}$ для текущего элемента вычисляется с использованием коэффициента $AT$, которое используется, как сокращение для времени атаки (attack time). В ином случае вычисление значения $X_{peak}$ для текущего элемента производится с помощью коэффициента $RT$, то есть времени освобождения (release time). Математическая формула описанного выше алгоритма
|
||||
|
||||
\begin{equation}
|
||||
X_{p}(n) = \begin{cases}
|
||||
(1 - AT) \times X_{p}(n - 1) + AT \times |X(n)|, |X(n)| > X_{p}(n - 1)\\
|
||||
(1 - RT) \times X_{p}(n - 1), |X(n)| \leq X_{p}(n - 1),
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
где $X_{p}$ - пиковое значение $X_{peak}$, $AT$ – время атаки, $RT$ – время освобождения, $n$ – номер текущего элемента.
|
||||
|
||||
\item После определения значения $X_{peak}$ выполняется функция для получения коэффициента усиления $f$ по формуле
|
||||
\begin{equation}
|
||||
f(n) = min \bigg( 1; \frac{lt}{X_{peak}n} \bigg),
|
||||
\end{equation}
|
||||
где $n$ – номер текущего элемента, $lt$ – пороговое значение.
|
||||
|
||||
\item После вычисления коэффициента усиления используется сглаживающий фильтр для предотвращения слишком резких изменений усиления. Для его реализации используется формула
|
||||
\begin{equation}
|
||||
cfc = \begin{cases}
|
||||
AT, f(n) < f(n-1)\\
|
||||
RT, f(n) \geq f(n-1),
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
где $n$ – номер текущего элемента.
|
||||
|
||||
\item Далее вычисляется множитель для регулирования входного сигнала по формуле
|
||||
\begin{equation}
|
||||
g(n) = (1 - cfc) \times g(n - 1) + cfc \times f(n)
|
||||
\end{equation}
|
||||
\item После получения искомого множителя входного сигнала, его значение умножается на задержанный в буфере задержки входной сигнал. Сигнал задерживается для того, чтобы компенсировалась любая задержка при вычислении множителя \cite[с. 106]{dsp:dafx}.
|
||||
\end{enumerate}
|
||||
|
||||
Результирующая комбинированная система, схематично демонстрирующая все шаги преобразования, изображена на рисунке \hrf{pic:limiter-scheme} \cite[с. 109]{dsp:dafx}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\captionsetup{labelsep=endash}
|
||||
\centering
|
||||
\def\svgwidth{165mm}
|
||||
\input{pics/02-dsp-03lab-limiter-scheme.pdf_tex}
|
||||
\caption{Принципиальная схема алгоритма работы ограничителя}
|
||||
\label{pic:limiter-scheme}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Алгоритм обработки сигналов}
|
||||
Алгоритм реализован на основе раздела \hrf{sect:description}. Основная реализующая алгоритм функция приведена в приложении \hrf{appendix:dyn-control-func}.
|
||||
|
||||
На вход алгоритма принимается массив с отсчетами. Пороговое значение задаётся константой \code{LT} в теле функции.
|
||||
|
||||
\subsubsection{Основная программа \code{main}}
|
||||
Функция \code{main} вызывается при запуске программы и реализует следующие шаги:
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item Инициализация кодека;
|
||||
\item Чтение из кодека текущего отсчета сигнала;
|
||||
\item Получение выходного отсчета сигнала;
|
||||
\item Переход на шаг 2.
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Функция ограничителя \code{dynDiaCtrl}}
|
||||
Функция ограничителя получает в качестве аргумента текуший отсчет \code{х} и возвращает его модифицированное значение \code{у}. Функция реализует следующие шаги алгоритма.
|
||||
\begin{enumerate}[label=\arabic*),ref=\arabic*]
|
||||
\item Получение модуля входного значения;
|
||||
\item Определение коэффициента для вычисления уровня;
|
||||
\item Вычисление уровня;
|
||||
\item Определение коэффициента усиления;
|
||||
\item Определение коэффициента для вычисления управляющего коэффициента;
|
||||
\item Запись выходного отсчета;
|
||||
\item Возврат из функции.
|
||||
\end{enumerate}
|
||||
Функция использует математические функции из стандартной библиотеки для корректной работы с числами в формате с фиксированной запятой.
|
||||
|
||||
\section{Выводы}
|
||||
В результате выполнения домашнего задания изучен звуковой эффект «Контроллер динамического диапазона», на примере ограничителя, для которого разработан и описан реализующий его алгоритм.
|
||||
\nocite{gost:texts}
|
||||
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\begin{appendices}
|
||||
\renewcommand{\thesubsection}{\Asbuk{subsection}}
|
||||
\subsection{Функция контроллера динамического диапазона}
|
||||
\label{appendix:dyn-control-func}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
volatile Int16 xpeak = 0;
|
||||
volatile Int16 g = 1;
|
||||
void dynDiaCtrl(Int16 *x, Int16 *y, Int16 nx) {
|
||||
const Int16 at_cfc = 9830;
|
||||
const Int16 rt_cfc = 328;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < nx; i++) {
|
||||
// step 1
|
||||
Int16 a = abs(x[i]);
|
||||
xpeak = (a > xpeak)
|
||||
? (_smpy((32767 - at_cfc), xpeak) + _smpy(at_cfc, a))
|
||||
: _smpy((32767 - rt_cfc), xpeak);
|
||||
|
||||
// step 2
|
||||
Int16 cmp = LT / xpeak;
|
||||
Int16 f = (cmp < 1) ? cmp : 1;
|
||||
// step 3
|
||||
Int16 cfc = (f < g) ? at_cfc : rt_cfc;
|
||||
// step 4
|
||||
g = _smpy((1 - cfc), g) + _smpy(cfc, f);
|
||||
y[i] = _smpy(g, x[i]);
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{appendices}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{3}{Звуковой эффект}{Микропроцессорные устройства обработки сигналов}{}{А.И. Германчук}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Целью работы является разработка и исследование программы обработки сигналов на языке программирования Си, реализующей звуковой эффект, определенный в индивидуальном задании (контроллер динамического диапазона, ограничитель).
|
||||
|
||||
\section{Описание звукового эффекта}
|
||||
Контроллер динамического диапазона - это адаптивная регулировка динамического диапазона сигнала. Динамический диапазон - это соотношение между наибольшими и наименьшими значениями, которые может принять определенная величина. Существует несколько типов контроллеров. В данной лабораторной работе будет рассматриваться ограничитель. Назначение ограничителя состоит в том, чтобы обеспечить контроль над самыми высокими пиками сигнала, но при этом, как можно меньше изменять динамику сигнала. Это достигается за счёт использования характеристической кривой с бесконечным отношением \cite[с. 109]{dsp:dafx}. Ограничитель динамического диапазона подавляет громкость звуков, пересекающих заданный порог (рисунок \hrf{pic:limiter}).
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{100mm}
|
||||
\input{pics/02-dsp-03lab-limiter.pdf_tex}
|
||||
\caption{Иллюстрация работы ограничителя сигнала}
|
||||
\label{pic:limiter}
|
||||
\end{figure}
|
||||
|
||||
Для достижения плавности кривой применяемого ослабления громкости используются такие параметры, как время атаки и высвобождения. Время атаки и время высвобождения соответствуют времени, за которое сигнал увеличивается или уменьшается до конечного значения (рисунок \hrf{pic:limiter-explain}). На рисунке видно, что при отсутствии времени атаки и освобождения усиление применяется сразу, создавая неплавные «обрезанные» кривые (жёсткое урезание).
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{170mm}
|
||||
\input{pics/02-dsp-03lab-limiter-explain.pdf_tex}
|
||||
\caption{Иллюстрация влияния времени атаки и освобождения}
|
||||
\label{pic:limiter-explain}
|
||||
\end{figure}
|
||||
|
||||
Ограничитель обычно используется для того, чтобы «поймать» самые громкие моменты источника, уменьшив их таким образом, чтобы защитить от нежелательных искажений и сохранить целостность общего баланса звука.
|
||||
|
||||
\section{Математическое описание ограничителя}
|
||||
\label{sect:description}
|
||||
Динамическая обработка выполняется усилительными устройствами, где коэффициент усиления автоматически регулируется уровнем входного сигнала. Динамическая обработка проходит в несколько этапов.
|
||||
\begin{enumerate}
|
||||
\item Сначала используется схема определения амплитуды/уровня по алгоритму PEAK \cite[с. 107]{dsp:dafx}.
|
||||
|
||||
В начале алгоритма значение переменной $X_{peak}$ равно нулю. Далее сравнивается модуль поступающего сигнала $|x(n)|$ с предыдущим значением $X_{peak}$. В случае если значение модуля поступающего сигнала больше, то значение $X_{peak}$ для текущего элемента вычисляется с использованием коэффициента $AT$, которое используется, как сокращение для времени атаки (attack time). В ином случае вычисление значения $X_{peak}$ для текущего элемента производится с помощью коэффициента $RT$, то есть времени освобождения (release time). Математическая формула описанного выше алгоритма
|
||||
|
||||
\begin{equation}
|
||||
X_{p}(n) = \begin{cases}
|
||||
(1 - AT) \times X_{p}(n - 1) + AT \times |X(n)|, |X(n)| > X_{p}(n - 1)\\
|
||||
(1 - RT) \times X_{p}(n - 1), |X(n)| \leq X_{p}(n - 1),
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
где
|
||||
\begin{itemize}
|
||||
\item [] $X_{p}$ - пиковое значение $X_{peak}$;
|
||||
\item [] $AT$ – время атаки;
|
||||
\item [] $RT$ – время освобождения;
|
||||
\item [] $n$ – номер текущего элемента.
|
||||
\end{itemize}
|
||||
|
||||
\item После определения значения $X_{peak}$ выполняется функция для получения коэффициента усиления $f$ по формуле
|
||||
\begin{equation}
|
||||
f(n) = min \bigg( 1; \frac{lt}{X_{peak}n} \bigg),
|
||||
\end{equation}
|
||||
где
|
||||
\begin{itemize}
|
||||
\item [] $n$ – номер текущего элемента;
|
||||
\item [] $lt$ – пороговое значение.
|
||||
\end{itemize}
|
||||
|
||||
\item После вычисления коэффициента усиления используется сглаживающий фильтр для предотвращения слишком резких изменений усиления. Для его реализации используется формула
|
||||
\begin{equation}
|
||||
cfc = \begin{cases}
|
||||
AT, f(n) < f(n-1)\\
|
||||
RT, f(n) \geq f(n-1),
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
где $n$ – номер текущего элемента.
|
||||
|
||||
\item Далее вычисляется множитель для регулирования входного сигнала по формуле
|
||||
\begin{equation}
|
||||
g(n) = (1 - cfc) \times g(n - 1) + cfc \times f(n)
|
||||
\end{equation}
|
||||
\item После получения искомого множителя входного сигнала, его значение умножается на задержанный в буфере задержки входной сигнал. Сигнал задерживается для того, чтобы компенсировалась любая задержка при вычислении множителя \cite[с. 106]{dsp:dafx}.
|
||||
\end{enumerate}
|
||||
|
||||
Результирующая комбинированная система изображена на рисунке \hrf{pic:limiter-scheme} \cite[с. 109]{dsp:dafx}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\def\svgwidth{165mm}
|
||||
\input{pics/02-dsp-03lab-limiter-scheme.pdf_tex}
|
||||
\caption{Принципиальная схема алгоритма работы ограничителя}
|
||||
\label{pic:limiter-scheme}
|
||||
\end{figure}
|
||||
|
||||
\section{Алгоритм обработки сигналов}
|
||||
Алгоритм реализован на основе раздела \hrf{sect:description}. В реализации алгоритма учитывается средняя частота дискретизации современных аудиофайлов 44,1 КГц. Алгоритм буферизует отсчёты на 6 миллисекунд, то есть если 44 отсчета - это одна милисекунда, то величина буфера должна быть $44 * 6 = 264$ отсчётов.
|
||||
|
||||
На вход алгоритма, вычисляющего значение коэффициента, принимается единичный отсчёт. Пороговое значение задаётся константой \code{LT} в теле функции.
|
||||
|
||||
\subsection{Основная программа \code{main}}
|
||||
Функция \code{main} вызывается при запуске программы и реализует следующие шаги:
|
||||
\begin{enumerate}
|
||||
\item инициализация кодека;
|
||||
\item чтение из кодека текущего отсчета сигнала по прерыванию от интерфейса I2S \code{x}, \code{x = I2S2_W0_MSW_R};
|
||||
\item вычисление и корректировка коэффициента g и сохранение текущего отсчёта в буфер;
|
||||
\item получение выходного отсчета сигнала \code{y}, путём умножения буферизованного отсчёта на вычисленный на текущем шаге коэффициент \code{_smpy(g, leftBuffer[qRead++]};
|
||||
\item смещение флагов чтения и записи данных в буфер, ожидание готовности контроллера прерываний;
|
||||
\item запись значений обоих каналов обратно в контроллер I2S;
|
||||
\item переход на шаг 2.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Функция ограничителя}
|
||||
Фактически, функция ограничителя разделена на две части:
|
||||
\begin{enumerate}
|
||||
\item приём отсчёта, буферизация и вычисление коэффициента ограничителя;
|
||||
\item чтение из очереди и умножение буферизованного отсчёта на коэффициент.
|
||||
\end{enumerate}
|
||||
|
||||
Функция расчёта коэффициента реализует следующие шаги алгоритма:
|
||||
\begin{enumerate}
|
||||
\item получение входного значения \code{x};
|
||||
\item получение модуля отсчёта;
|
||||
\item определение коэффициента \code{cfc} для вычисления уровня;
|
||||
\item вычисление уровня \code{xpeak}, \code{xpeak = (1 - cfc) * xpeak + coeff * x};
|
||||
\item определение коэффициента усиления \code{f}, \code{f = min(1, LT / xpeak)};
|
||||
\item определение коэффициента \code{cfc} для вычисления управляющего коэффициента \code{g = (1 - cfc) * g + cfc * f};
|
||||
\item возврат коэффициента \code{g} из функции.
|
||||
\end{enumerate}
|
||||
|
||||
Код, вызывающий функцию, кроме буферизации прочитанного значения (\code{leftBuffer[qWrite++] = left;}) осуществляет умножение ранее буферизованного отсчёта на текущее скорректированное значение коэффициента фильтра \code{out_left = _smpy(g, leftBuffer[qRead++])} и запись выходного отсчета на шину контроллера I2S \code{I2S2_W0_MSW_W = out_left;}
|
||||
|
||||
\section{Выводы}
|
||||
В результате выполнения работы была разработана программа обработки сигнала на языке программирования Си, реализующая звуковой эффект - контроллер динамического диапазона, а именно, ограничитель. В ходе работы были получены графики входных и выходных отсчетов и по ним исследован результат применения звукового эффекта на входной сигнал.
|
||||
\nocite{gost:texts}
|
||||
\newpage
|
||||
\printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1]
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Полные листинги программ}
|
||||
\label{appendix:fulls}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Функция вычисления коэффициента ограничителя}, label=code:prog-coeff]
|
||||
Int16 oneCountCoefficient(Int16 x) {
|
||||
const Int16 LT = 28576;
|
||||
Int16 at_cfc = 9830;
|
||||
Int16 rt_cfc = 328;
|
||||
|
||||
Int16 a = abs(x); // <@\lh{dkgreen}{модуль значения текущего отсчёта}@>
|
||||
Int16 cmp;
|
||||
xpeak = (a > xpeak) // <@\lh{dkgreen}{коэффициент x пиковое}@>
|
||||
? (_smpy((32767 - at_cfc), xpeak) + _smpy(at_cfc, a))
|
||||
: _smpy((32767 - rt_cfc), xpeak);
|
||||
|
||||
if (abs(LT) > abs(xpeak)) // <@\lh{dkgreen}{коэффициент cmp}@>
|
||||
cmp = (Int16)(((Int32) LT << 15) / ((Int32) xpeak));
|
||||
|
||||
Int16 f = (cmp < 32767) ? cmp : 32767;
|
||||
Int16 cfc = (f < g) ? at_cfc : rt_cfc; // <@\lh{dkgreen}{коэффициент cfc}@>
|
||||
|
||||
// <@\lh{dkgreen}{возврат вычисленного коэффициента g}@>
|
||||
return _smpy((32767 - cfc), g) + _smpy(cfc, f);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle,caption={Полный листинг программы на языке С}, label=code:prog-c]
|
||||
// DSP, board libraries
|
||||
#include "C5515.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
#include "i2s.h"
|
||||
#include "stdio.h"
|
||||
// <@\lh{dkgreen}{заголовок с функцией oneCountCoefficient}@>
|
||||
#include "mylimiter.h"
|
||||
|
||||
#define AIC3204_I2C_ADDR 0x18
|
||||
#define Rcv 0x08
|
||||
#define Xmit 0x20
|
||||
extern Int16 aic3204_stereo_in1();
|
||||
|
||||
volatile Int16 xpeak = 1;
|
||||
volatile Int16 g = 1;
|
||||
|
||||
Int16 oneCountCoefficient(Int16 x);
|
||||
|
||||
void main(void) {
|
||||
// <@\lh{dkgreen}{инициализация}@>
|
||||
c5515_init();
|
||||
|
||||
// <@\lh{dkgreen}{конфигурирование параллельного порта}@>
|
||||
SYS_EXBUSSEL &= ~0x7000;
|
||||
SYS_EXBUSSEL |= 0x1000;
|
||||
|
||||
// <@\lh{dkgreen}{конфигурирование последовательного порта}@>
|
||||
SYS_EXBUSSEL &= ~0x0C00;
|
||||
SYS_EXBUSSEL |= 0x0400;
|
||||
|
||||
c5515_GPIO_init();
|
||||
c5515_GPIO_setDirection(GPIO10, GPIO_OUT);
|
||||
c5515_GPIO_setOutput(GPIO10, 1); // <@\lh{dkgreen}{вывод AIC3201 из reset}@>
|
||||
I2C_init(); // <@\lh{dkgreen}{инициализация I2C}@>
|
||||
|
||||
// <@\lh{dkgreen}{I2S настройки}@>
|
||||
I2S2_SRGR = 0x0015;
|
||||
I2S2_ICMR = 0x0028;
|
||||
I2S2_CR = 0x8012;
|
||||
|
||||
// Режим стерео входа
|
||||
aic3204_stereo_in1();
|
||||
|
||||
#define BUF_LENGTH 264
|
||||
Int16 left, right; // <@\lh{dkgreen}{отсчеты до примененого эффекта}@>
|
||||
Int16 out_left = 0; // <@\lh{dkgreen}{отсчеты после примененого эффекта}@>
|
||||
Int16 leftBuffer[BUF_LENGTH]; // <@\lh{dkgreen}{буфер}@>
|
||||
Int16 qWrite = 0;
|
||||
Int16 qRead = -255;
|
||||
|
||||
while(1){
|
||||
// <@\lh{dkgreen}{Ожидание прерывания по получению отсчёта}@>
|
||||
while ((Rcv & I2S2_IR) == 0);
|
||||
left = I2S2_W0_MSW_R; // <@\lh{dkgreen}{16-битное значение левого канала}@>
|
||||
right = I2S2_W1_MSW_R; // <@\lh{dkgreen}{16-битное значение правого канала}@>
|
||||
|
||||
g = oneCountCoefficient(left); // <@\lh{dkgreen}{текущий коэффициент}@>
|
||||
leftBuffer[qWrite++] = left; // <@\lh{dkgreen}{буферизация отсчёта}@>
|
||||
if (qWrite == BUF_LENGTH)
|
||||
qWrite = 0; // <@\lh{dkgreen}{не дать флагу записи переполниться}@>
|
||||
|
||||
if (qRead >= 0) {
|
||||
// <@\lh{dkgreen}{прочитать из буфера и умножить на коэффициент}@>
|
||||
out_left = _smpy(g, leftBuffer[qRead++]);
|
||||
if (qRead == BUF_LENGTH)
|
||||
qRead = 0; // <@\lh{dkgreen}{не дать флагу чтения переполниться}@>
|
||||
} else {
|
||||
++qRead;
|
||||
}
|
||||
|
||||
while ((Xmit & I2S2_IR) == 0); // <@\lh{dkgreen}{Ждём контроллер прерывания}@>
|
||||
|
||||
// <@\lh{dkgreen}{записать изменённое}@>
|
||||
I2S2_W0_MSW_W = out_left;
|
||||
|
||||
// <@\lh{dkgreen}{записать не изменённое}@>
|
||||
I2S2_W1_MSW_W = right;
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,469 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\author{Кадырбаева Анастасия Рустемовна}
|
||||
\title{Методы исследования и моделирования информационных процессов и технологий}
|
||||
\date{2022-02-08}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
\usepackage{subfiles}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\newpage
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\section{Введение}
|
||||
Можно послушать курс на курсере. Или курс Systems Engineering Focus Area.
|
||||
|
||||
Литература: Системноинженерное мышление Левенчук 2020. 3 РКх10, 4 ЛРх10.
|
||||
|
||||
ИСО 15288-2015, 42010-2011
|
||||
|
||||
Курс о процессах, проектируемых системах, нотациях, техтребования, тз, системноинженерное мышление.
|
||||
|
||||
Системная инженерия отличается от инженерий по специальности тем, что в ней используются специальные средства мышления о целостности целевой системы: средства системного мышления, когда слово “система” обозначает не просто любой объект, а именно систему — и в явном виде используются практики системной инженерии. В инженериях по специальности есть свои способы удержания целостности целевой системы в сборке различных требуемых для её создания деятельностей — но эти способы основаны не столько на общих принципах, сколько на глубоком опыте разработки тысяч и тысяч более-менее однотипных систем. Этот опыт достигается специализацией инженерной работы, обучением и воспитанием.
|
||||
|
||||
\subsection{Термины}
|
||||
\textbf{Процесс} - это набор взаимосвязанны или взаимодействующих действий, преобразующих входы и выходы. Процессы состоят из действий, а действия из задач, которые могут выполнять некоторые акторы(деятели) над/с системой.
|
||||
|
||||
\textbf{Нотация} - множество символов и правил их применения, используемые для представления леусических единиц и их взаимоотношений.
|
||||
|
||||
\textbf{Архитектурный метод описания} - спецификация соглашений для конструирования и применения группы описаний.
|
||||
|
||||
\textbf{Системная инженерия} - междисциплинарный подход и средства для обеспечения реализации успешных систем, определяющий полный набор технических и управленческих усилий, которые требуются для преобразования совокупности потребностей и ожиданий заказчика, имеющихся ограничений. Помогает создателям систем в выделении точек зрения, которые следует использовать для описания мира или разрабатываемой системы. Включает в себя:
|
||||
\begin{itemize}
|
||||
\item Эргономика
|
||||
\item Программная инженерия
|
||||
\item Управление проектами
|
||||
\item Управление качеством
|
||||
\item Менеджмент
|
||||
\item Математика
|
||||
\item Компьютерные науки
|
||||
\item Компьютерная инженерия
|
||||
\end{itemize}
|
||||
|
||||
Помогает создателям систем в выделении точек зрения, которые следует использовать для описания мира или разрабатываемой системы. Определяет сферу ответственности системного инженера. Предлагает инструментарий для осуществления этой деятельности.
|
||||
|
||||
Суть курса:
|
||||
\begin{itemize}
|
||||
\item заложить основы системноинженерного мышления
|
||||
\item научится работать с нотациями, разрабатывать их по ТЗ и читать
|
||||
\item освоить методы моделирования информационных процессов.
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Методологический статус системной инженерии}
|
||||
\begin{itemize}
|
||||
\item Методы и процедуры, почерпнутые из современной науки и созданные специально для неё
|
||||
\item Развитие системной инженерии не имеет законченной теории и строгой формализации, это связано с тем, что чрезвычайно высокая сложность и разнообразие крупномасштабных систем существенно затрудняет использование точных формализованных методов при их создании.
|
||||
\item В настоящее время системная инженерия представляет собой междисциплинарный комплекс исследований, подходов и методологий к построению и эксплуатации сложных систем любого масштаба и назначения в различных областях человеческой деятельности
|
||||
\end{itemize}
|
||||
|
||||
Работа с \textbf{терминологией} - в первую очередь работа с естественным человеческим языком. В каждом языке сформировались наборы терминов для разных областей человеческой деятельности. В этих областях термины приобретают значения, то есть обозначают какие-то объекты и их отношения
|
||||
|
||||
Работа с \textbf{онтологией} - попытка понять, как и почему мы выделяем в мире те объекты и отношения, которые обозначаются терминами. Т.о. терминология – про язык и слова, онтология – про мир и его объекты.
|
||||
|
||||
|
||||
\textbf{Сообщество} знаний - совокупность людей, которые одинаково понимают суть окружающих предметов и явлений.
|
||||
|
||||
\textbf{Семантика} - наука о связи разных обозначений, символов и общими для разных людей и ситуаций значениями и реального мира.
|
||||
|
||||
\textit{На слайде изображение карты с размеченными разным цветом областями}. Пример: карта, это один уровень описания, на неё можно дополнительно нанести описание дорог, создание меток о наличии препятствий, карта высот. Получается, что класс А описан языком В который содержит грамматики С. Карта будет являться описанием некоторого уровня. Такие многоуровневые описания называются метамоделями.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
x=0.75pt, y=0.75pt, yscale=-1, xscale=1,
|
||||
outline/.style={draw=#1, thick},
|
||||
outline/.default=black,
|
||||
antenna/.pic={
|
||||
\draw(0,0) -- (0,2);
|
||||
\draw(0,1) -- (1,2);
|
||||
\draw(0,1) -- (-1,2);
|
||||
},
|
||||
]
|
||||
\tkzblk{outline}{-100,0}{Concept}
|
||||
\tkzblk{outline}{100,0}{Occurence}
|
||||
\tkzblk{outline}{0,-75}{Descriptor}
|
||||
\tkzblk{outline}{0,-200}{Symbol}
|
||||
\draw[thin] (-100, -15) -- (-10, -185);
|
||||
\draw[thin] (100, -13) -- (10, -185);
|
||||
\draw[thin] (-80, -15) -- (-45, -60);
|
||||
\draw[thin] (80, -13) -- (45, -60);
|
||||
\draw[thin] (0, -90) -- (0, -185);
|
||||
\draw[thin] (-62, 0) -- (53, 0);
|
||||
\node [] at (0,10) {classifies};
|
||||
\node [rotate=90] at (-10,-130) {describes};
|
||||
\node [rotate=62] at (-70,-100) {symbolises};
|
||||
\node [rotate=-62] at (70,-100) {symbolises};
|
||||
\end{tikzpicture}
|
||||
\caption{Метауровни}
|
||||
\label{pic:metalevels}
|
||||
\end{figure}
|
||||
|
||||
Метамодели и метауровни позволяют описывать модели мира на разных уровнях. Кто будет составлять? И учёные и инженеры, но у них будут разные уровни описания.
|
||||
|
||||
\subsection{Инженерия и исследования}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
x=0.75pt, y=0.75pt, yscale=-1, xscale=1,
|
||||
outline/.style={draw=#1, thick},
|
||||
outline/.default=black,
|
||||
antenna/.pic={
|
||||
\draw(0,0) -- (0,2);
|
||||
\draw(0,1) -- (1,2);
|
||||
\draw(0,1) -- (-1,2);
|
||||
},
|
||||
]
|
||||
\tkzblk{outline}{0,-200}{Компактное описание}
|
||||
\tkzblk{outline}{0,0}{Создание систем}
|
||||
\tkzdarr{-30,-185}{-30,-15}
|
||||
\tkzdarr{30,-185}{30,-15}
|
||||
|
||||
\node [rotate=90] at (-50,-100) {Инженерия};
|
||||
\node [rotate=-90] at (50,-100) {Исследования};
|
||||
\end{tikzpicture}
|
||||
\caption{Цикл разработки системы}
|
||||
\label{pic:metadevel}
|
||||
\end{figure}
|
||||
|
||||
Инженерия описывает то, как работают инженеры. Другие предметы и науки, которые изучаются инженерией, вроде механики, электроники, математики - описывают поведение инженерных объектов.
|
||||
|
||||
Инженерия, кроме научных теорий активно использует эвристики - догадки о закономерностях, которые вовсе необязательно научны
|
||||
|
||||
Формальные описания инженерных систем позволяют проводить формальный анализ, находить ошибки без создания системы, вычислить необходимые или оптимальные характеристики системы
|
||||
|
||||
Инженерная работа не делается в одиночку. Компактные описания нужны для того, чтобы люди могли иметь одинаковое описание того, что они делают
|
||||
|
||||
Системных инженеров учат на работах предшественников, показывают положительные и отрицательные моменты, учат приёмам работы, которые должны давать хорошие результаты.
|
||||
|
||||
\paragraph{Развитие и совершенствование инженерии}
|
||||
S-образные графики по диагонали внахлёст как по х так и по у. От нуля перечисляются поколения:
|
||||
\begin{enumerate}
|
||||
\item Алхинженерия - неформальные тексты и эскизы
|
||||
\item Современная (классическая) инженерия - диаграммы, чертежи, псевдокод
|
||||
\item Моделе-ориентированная (model-based) инженерия - формальные языки (вычисляемый код)
|
||||
\item ИИ, гибридные вычисления
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Система}
|
||||
\begin{itemize}
|
||||
\item Иерархия холонов
|
||||
\item Классы и классификаторы
|
||||
\item наборы правил, обычаев, процедур, имеющих какую-то структуру
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Успешная система} - результирующая система проекта, учитывающая ролевые потребности затрагивающих систему и её людей, равно как и потребности, затрагиваемых системой и её проектом людей.
|
||||
|
||||
\textbf{Система} - индивидуальный, уникальный объект, имеющий некоторую протяжённость в пространстве и времени. Имеет изменяющиеся состояния. Системы меняются по мере взаимодействия с окружающими системами, которые тоже находятся в физическом мире, а внутри них меняются взаимодействующие подсистемы.
|
||||
|
||||
\textbf{Документация} - абстрактное описание, записанное на каком-то физическом носителе информации.
|
||||
|
||||
\paragraph{Системность и систематичность.}
|
||||
|
||||
Систематичность - формальное обращение внимания на определённые моменты. Системность - про документацию и предметы окружающего мира. Системность - специальный трансдисциплинарный набор концептов, обращающий внимание на главное и важное. Системность - содержание мышления. Системность - структурирование, представление формального описания, формальное обращение внимание на необходимые вещи, про документацию и предметы окружающего мира. Сразу подразумевает огромное количество умственной и документарной работы.
|
||||
|
||||
\paragraph{Многоуровневость системного разбиения.}
|
||||
|
||||
На самом верхнем уровне - вселенная, на самом нижнем - суперструны.
|
||||
|
||||
Явное указание системного уровня важно для управления вниманием
|
||||
|
||||
Системные уровни принципиальны, они отражают саму суть системного подхода
|
||||
|
||||
Никакого «истинного» или «объективного» разбиения системы на части нет.
|
||||
|
||||
\section{Стандартный язык нотаций UML}
|
||||
Для разработки ПО нужно понимать, что нужно пользователю. Обсуждать конкретные требования к разрабатываемой системе. Для быстрой и эффективной разработки ПО с имнимальным браком требуется: привлечи рабочую силу, выбрать технологию...
|
||||
|
||||
Зачем нужно моделирование?
|
||||
\begin{itemize}
|
||||
\item наглядная демонстрация структуры и поведения
|
||||
\item визуализация и управление архитектуры системы
|
||||
\item помогает добить ся лучшего понимания создаваемой системы
|
||||
\item упрощение системы
|
||||
\item обеспечивает возможность повторного использования
|
||||
\item минимизация рисков
|
||||
\end{itemize}
|
||||
|
||||
Если вы хотите соорудить собачью будку, то можете приступить к работе, имея в наличии лишь кучу досок, горсть гвоздей, молоток, плоскогубцы и рулетку. Несколько часов работы после небольшого предварительного планирования – и вы сколотите вполне приемлемую будку, причем, скорее всего, без посторонней помощи. Если будка получится достаточно большой и не будет сильно протекать, собака останется довольна. В крайнем случае никогда не поздно начать все сначала.
|
||||
|
||||
Если вам надо построить дом для своей семьи, вы, конечно, можете воспользоваться тем же набором инструментов, но времени на это уйдет значительно больше, и ваши домочадцы, надо полагать, окажутся более требовательными, чем собака. Стоит, по меньшей мере, сделать хотя бы несколько эскизов будущей постройки.
|
||||
|
||||
\textbf{Моделирование} – это устоявшаяся и повсеместно принятая инженерная методика. Мы строим архитектурные модели зданий, чтобы помочь их будущим обитателям во всех деталях представить готовый объект. Иногда применяют даже математическое моделирование зданий, чтобы учесть влияние сильного ветра или землетрясения. Очевидно, моделирование применяется не только в строительстве.
|
||||
|
||||
\textbf{Модель} – абстракция физической системы, рассматриваемая с определенной точки зрения и представленная на некотором языке или в графической форме. С точки зрения общих принципов системного анализа одна и та же физическая система может быть представлена несколькими моделями. При этом назначение отдельной модели системы определяется характером решаемой проблемы. Основные требования к модели программной системы состоит в том, что она должна быть понятна заказчику и всем специалистам проектной группы, включая бизнес-аналитиков и программистов. Разработка и использование моделей языка UML осуществляется в рамках общей концепции объектно-ориентированного анализа и проектирования, которая, в свою очередь, является обобщением методологии объектно-ориентированного программирования.
|
||||
|
||||
Модель позволяет:
|
||||
\begin{itemize}
|
||||
\item визуализировать систему в её текущем или желательном сосотоянии,
|
||||
\item описать структуру или поведение системы,
|
||||
\item получить шаблон, позволяющий сконструировать систему,
|
||||
\item докуентировать принимаемые решения, используя полученные модели.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Принципы моделирования}
|
||||
\begin{enumerate}
|
||||
\item Выбор модели оказывает определяющее влияние на подход к решению проблемы и на то, как будет выглядеть это решение. Правильно выбранная модель высветит самые опасные проблемы разработки и позволит описать суть задачи. Даёт дополнительную информацию, позволяет проработать больше различных сценариев. Каждая модель может быть представлена с различной степенью точности.
|
||||
|
||||
Мы будем использовать диаграммы Феймана, которая позволит описать задачу с разных точек зрения. Если вы смотрите на систему глазами разработчика баз данных, то внимание будете уделять моделям «сущность-связь», где поведение инкапсулировано в триггерах и хранимых процедурах. Аналитик, использующий структурный подход создал бы модель, в центре которой находятся алгоритмы и передача данных от одного процесса к другому. Результатом труда разработчика, пользующегося объектно-ориентированным методом, будет система, архитектура которой основана на множестве классов и образах взаимодействия, определяющих как классы действуют совместно. Любой из этих вариантов может оказаться подходящим для разработки методики или приложения. Хотя более эффектинвой будет объектно-ориентированная точка зрения при создании гибких архитектур.
|
||||
\item Каждая модель может быть представлена с различной степенью точности.
|
||||
|
||||
Лучшей моделью окажется та, которая позволит выбрать уровень детализации в зависимости от того, кто и с какой целью на нее смотрит. Для аналитика или конечного пользователя наибольший интерес представляет вопрос «что», а для разработчика – «как». В обоих случаях необходима возможность рассматривать систему на разных уровнях детализации в разное время.
|
||||
\item лучшие модели те, что ближе к реальности. Модель всегда упрощает реальность, задача - чтобы упрощение не повлекло за собой существенные потери. Проблема при проектировании ПО - несоответствие принятой в нём модели и модели системного проекта. При объектно ориентированного подхода можео объединить все почти независимые представления системы в единое семантическое целое.
|
||||
|
||||
При объектно-ориентированном подходе можно объединить все почти независимые представления системы в единое семантическое целое.
|
||||
\item нельзя ограничиваться созданием только одной модели.
|
||||
|
||||
Наилучший подход при разработку любой нетривиальной системы – использовать совокупность нескольких моделей, почти независимых друг от друга. Если вы конструируете здание, никакой отдельный комплект чертежей не поможет вам прояснить все детали до конца. Понадобятся как минимум поэтажные планы, виды в разрезе, схемы электропроводки, центрального отопления и водопровода.
|
||||
\end{enumerate}
|
||||
Для понимания архитектуры подобной системы требуется несколько взаимодополняющих представлений:
|
||||
\begin{itemize}
|
||||
\item представление с точки зрения вариантов использования (чтобы выявить требования к системе);
|
||||
\item с точки зрения проектирования (чтобы построить словарь предметной области и области решения);
|
||||
\item с точки зрения взаимодействий (чтобы смоделировать взаимодействия между частями системы, системой в целом и средой ее функционирования);
|
||||
\item с точки зрения реализации (позволяющее рассмотреть физическую реализацию системы);
|
||||
\item с точки зрения размещения (помогающее сосредоточиться на вопросах системного проектирования).
|
||||
\end{itemize}
|
||||
Каждое из перечисленных представлений имеет множество структурных и поведенческих аспектов, которые в своей совокупности составляют детальный чертеж программной системы.
|
||||
|
||||
\subsection{Методы моделирования, UML}
|
||||
Алгоритмический
|
||||
\begin{itemize}
|
||||
\item традиционный подход к созданию ПО;
|
||||
\item основан на процедурах и функциях;
|
||||
\item вопросы передачи управления и декомпозиции б\'{о}льших алгоритмов на меньшие.
|
||||
\end{itemize}
|
||||
|
||||
Объектно-ориентированный
|
||||
\begin{itemize}
|
||||
\item современный подход;
|
||||
\item основные блоки - объекты и классы;
|
||||
\item каждый блок обладает идентичностью, состоянием и поведением.
|
||||
\end{itemize}
|
||||
|
||||
ОО подход помогает отвечать на вопросы:
|
||||
\begin{itemize}
|
||||
\item какая структура должна быть у хорошей ОО архитектуры
|
||||
\item какие артефакты должны быть созданы в процессе работы над проектом
|
||||
\item кто создаёт артефакты
|
||||
\item как оценить результат работы
|
||||
\end{itemize}
|
||||
|
||||
Унифицированный язык моделирования (Unified Modeling Language – UML) – это стандартный инструмент для разработки «чертежей» программного обеспечения. Его можно использовать для визуализации, спецификации, конструирования и документирования артефактов программных систем. UML – всего лишь язык, и как таковой представляет только одну из составляющих процесса разработки программного обеспечения. Хотя UML не зависит от моделируемых процессов, лучше всего применять его в тех случаях, когда процесс моделирования основан на применении вариантов использования, сконцентрирован на архитектуре системы, является итеративным и пошаговым.
|
||||
|
||||
UML – это язык для визуализации, специфицирования, конструирования и документирования артефактов программных систем. Язык представляет словарь и правила комбинирования входящих в него слов в целях коммуникации. Язык моделирования – это язык, словарь и правила которого сосредоточены на концептуальном и физическом представлении системы. UML – стандартное средство представления «чертежей» программного обеспечения. Нотация представляет собой совокупность графичеких элементов, которые используются в моделях.
|
||||
|
||||
Моделирование необходимо для понимания системы. При этом ни одна модель не является абсолютно достаточной. Напротив, чтобы понять большинство систем, кроме самых тривиальных, часто требуется множество взаимосвязанных моделей. В отношении программных систем это означает, что необходим язык, средствами которого можно описать архитектуру системы с различных точек зрения, причем на протяжении всего жизненного цикла ее разработки.
|
||||
Словарь и правила такого языка, как UML, говорят о том, как создавать и читать хорошо согласованные модели, но не говорит о том, какие именно модели в каких случаях требуется создавать. Это задача всего процесса разработки программного обеспечения. Хорошо организованный процесс должен сам подсказать, какие потребуются рабочие продукты, какие ресурсы понадобятся для их создания и управления ими, как их использовать для оценки выполненной работы и управления проектом в целом.
|
||||
|
||||
UML имеет три вида блоков:
|
||||
\begin{itemize}
|
||||
\item Сущности – абстракции, которые являются основными элементами модели
|
||||
\begin{itemize}
|
||||
\item Структурные – в основном это статические части модели, представляющие либо концептуальные, либо физические элементы. В совокупности структурные сущности называются классификаторами. Структурные сущности это: класс, интерфейс, кооперация (collaboration), компонент, артефакт, сервер.
|
||||
\item Поведенческие – динамические части моделей. Так сказать «глаголы», представляющие поведение во времени и пространстве. Это: взаимодействие (interaction, обмен сообщениями между наборами объектов или ролей в определенном контексте достижения целей), автомат (state machine, поведение, характеризуемое последовательностью состояний объекта), деятельность (activity – последовательность шагов вычислений).
|
||||
\item Группирующие сущности – организованная часть моделей. Самый распространенный элемент – пакет, т.е. механизм общего назначения для организации проектных решений, который упорядочивает конструкцию реализации.
|
||||
\item Аннотирующие сущности – т.е. поясняющие части, комментарии для описания выделения и пояснения любого элемента модели. Примечания.
|
||||
\end{itemize}
|
||||
\item Связи – соединяют между собой сущности
|
||||
\begin{itemize}
|
||||
\item Зависимость – связь между двумя элементами модели, в которой изменение одного элемента может привести к изменению семантики другого элемента.
|
||||
\item Ассоциация – структурная связь между классами, которая описывает набор связей, существующих между объектами – экземплярами классов. Агрегация – особая разновидность ассоциации, представляющая структурную связь целого с его частями.
|
||||
\item Обобщение – связь, в которой специализированный элемент (потомок) строится по спецификациям обобщенного элемента (родителя).
|
||||
\item Реализация – семантическая связь между классификаторами, когда один из них специфицирует соглашение, которого второй обязан придерживаться.
|
||||
\end{itemize}
|
||||
\item Диаграммы – группируют представляющие интерес наборы сущностей.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Правила UML}
|
||||
Хорошо согласованная модель - та, которая семантически самосогласована и находится в гармонии со всеми другими моделями, связанными с ней.
|
||||
|
||||
\subsection{Механизмы UML}
|
||||
\textbf{Спецификация.} За каждой частью его графической нотации стоит спецификация (specification) содержащая текстовое представление синтаксиса и семантики определенного строительного блока. С помощью графической нотации UML вы визуализируете систему, с помощью спецификаций UML описываете ее детали. Таким образом, допускается последовательное построение модели – шаг за шагом, когда сначала рисуются диаграммы, а затем добавляется семантика к спецификациям модели, – или же напрямую, когда в первую очередь создаются спецификации (возможно, при выполнении обратного проектирования существующей системы), а затем рисуются диаграммы, представляющие их проекции.
|
||||
Спецификации UML создают семантический задний план, который включает в себя все составные части всех моделей системы, согласованные между собой. Таким образом, диаграммы UML – это простые визуальные проекции на этот задний план, при этом каждая из них раскрывает некоторый существенный аспект системы.
|
||||
|
||||
\subsection{Архитектура}
|
||||
Архитектура программного обеспечения касается не только его структуры и поведения, но также пользовательских свойств, функциональности, производительности, гибкости, возможности повторного использования, понятности, экономических и технологических ограничений и компромиссов, а также эстетических вопросов.
|
||||
|
||||
\textbf{Архитектура} набор существенных решений относительно организации программной системы, выбора структурных элементов, составляющих систему и их интерфейсов; поведения этих элементов, определенного в их кооперациях; объединения структурных и поведенческих элементов в более крупные подсистемы; архитектурного стиля, определяющего организацию системы? Статические и динамические элементы и их интерфейсы, кооперацию и композицию.
|
||||
|
||||
\subsection{Представления}
|
||||
\section{MDA, MDD, генерация кода}
|
||||
MDA - model-driven architecture - суть в построении метамодели управления и обмена метаданными с заданием разных способов и технологий программирования. Модель - это основной артефакт разработки, из которой будет генерироваться не только код, но и другие артефакты. Главный стандарт - UML. Достоинство - множество методов описания, множество уровней. Есть недостаток в выразительности, ограниченности архитектуры языком UML.
|
||||
|
||||
MOF - meta object facility. Стандарт, целью которого является предоставление системы типов для сущностей и набор интерфейсов с помощью которых можно создавать эти типы. Реализовано как четырёхслойная архитектура. Помимо этих уровней есть средства описания моделей, например стандарт XMI который может и поддерживать МОФ и описывать модели сам по себе, аналогично уровням 1-3 МОФа.
|
||||
|
||||
EMF - Eclipse Modeling Framework. Предназначен для понятного метамоделирования и визуализации моделей. Модели просты, но предназначены для смешивания с написанным «от руки» кодом. обеспечивает унифицированное представление структур данных, описанных в приложении. Модели представлены в виде внутренней структуры.
|
||||
|
||||
(слайд 13) Применение моделе-управляемого подхода. Получаем второй этап: платформо-независимые модели. Важным аспектом будет визуальное моделирование. Третий этап - это платформо-зависимые модели. Четвёртый этап - это генерация кода. Ecore поддерживает джавские аннотации и поэтому может создавать экземпляры модели. ЕКор поддерживает ряд других концепций, которые не поддерживаются джавой, например, двунаправленные отношения.
|
||||
|
||||
Представление вариантов использования системы охватывает варианты использования, описывающие поведение системы с точки зрения конечных пользователей, аналитиков и тестировщиков.
|
||||
Их взгляд в дейст вительности специфицирует не истинную организацию программной системы, а лишь некие движущие силы, формирующие системную архи тектуру. В языке UML статические аспекты этого представления передаются диаграммами вариантов использования, а динамические его аспекты – диаграммами взаимодействий, состояний и деятельности.
|
||||
Представление системы с точки зрения дизайна охватывает классы, интерфейсы и кооперации, формирующие словарь проблемы и ее решение. Это представление в основном поддерживает функциональные требования к системе, то есть сервис, который она должна предоставлять конечным пользователям. Статические аспекты этого представления в UML сосредоточены в диаграммах классов и объектов, а динамические передаются диаграммами взаимодействий, состояний и деятельности. Диаграмма внутренней структуры класса, в частности, также полезна.
|
||||
Представление взаимодействия системы показывает поток управления, проходящий через разные ее части, включая возможные механизмы параллелизма и синхронизации. Это представление касается производительности, масштабируемости и пропускной способности системы. Статические и динамические аспекты этого представления в UML представлены в некоторых видах диаграмм, используемых в представлении дизайна, но сфокусированы на активных классах, управляющих системой, и передаваемых между ними сообщениях.
|
||||
Представление реализации системы охватывает артефакты, используемые для сборки и физической реализации системы. Это представление в первую очередь относится к управлению конфигурацией версий системы, состоящей из независимых (в определенной степени) файлов и компонентов, которые могут быть собраны различными способами для формирования работающей системы.
|
||||
Оно также связано с отображением из логических классов и компонентов в физические артефакты. В UML статические аспекты этого представления отражены в диаграммах артефактов, динамические аспекты – в диаграммах взаимодействия, состояний и деятельности.
|
||||
Представление развертывания системы охватывает узлы, образующие топологию оборудования, на котором работает система. Это представление в основном связано с поставкой, распределением и установкой частей, составляющих физическую систему. Его
|
||||
статические аспекты в UML описываются диаграммами размещения, а динамические – диаграммами взаимодействий, состояний и деятельности. Каждое из этих пяти представлений может быть достаточным для различных заинтересованных лиц, имеющих отношение к разработке и эксплуатации системы, позволяя им сосредоточиться только на тех аспектах архитектуры, которые непосредственно их касаются. Однако все эти представления также взаимодействуют друг с другом. Узлы из представления размещения содержат компоненты из представления реализации, которые, в свою очередь, представляют собой физическую реализацию классов, интерфейсов, коопераций и активных классов из представлений дизайна, и взаимодействия.
|
||||
|
||||
\section{X-Text}
|
||||
Язык DSL - структура отражает решаемые языком задачи. DSL - это предметно-специфический язык (domain-specific language). Объединяет кроме текста и графики ещё и концептуальную часть. Деление довольно условно, потому что любой описанный протокол на общих языках - это вариация DSL. Это ЯП более высокого уровня абстракции и оперируют правилами.
|
||||
|
||||
Преимущества языка и движка трансформации позволяет значительно повышать эффективность определённых этапов разработки. Позволяет отдельить важное от неважного. размывает границы между аналитиками и техническими специалистами.
|
||||
|
||||
Использует грамматику основного языка, может формировать внутренние DSL.
|
||||
|
||||
Правила Х-текста
|
||||
\begin{itemize}
|
||||
\item правила лексем
|
||||
\item правила данных
|
||||
\item правила разбора
|
||||
\end{itemize}
|
||||
Х-текст значительно упрощает формальный язык.
|
||||
|
||||
Семантические правила закладываются в два этапа - на этапе написания грамматика и на этапе внедрения. Можно описывать валидацию программ (статический анализ на предмет корректности). Формируем абстрактное синтаксическое дерево.
|
||||
|
||||
эклипс предоставляет интерфейс для встраивания новых отладчиков. платформа многопоточна.
|
||||
|
||||
\section{Archmate Framework}
|
||||
архитектор предприятия - это технический специалист, который получил специальное образование, способный заниматься проектированием, анализом и внедрением информационных систем. Архитектура организации это область знаний об организованности отдельных элементов предприятия. Архитектура - это совокупность некоторых принципов и правил.
|
||||
|
||||
Корректная архитектура несёт преимущества для бизнеса. Потребность в архитектуре есть в организациях со сложной организацией. Сложные структуры легче разбивать на модели. Для адекватного моделирования следует различать функциональные, организационные и поведенческие модели.
|
||||
|
||||
Модель закмана - это таблица из 6 столбцов и 6 строк, описывающая 6 точек зрения и 6 аспектов деятельности (вопросов). В общем виде самая распространённая и простая, но есть ряд недостатков - не накладывает ограничений на изменение, нет динамики. С другой стороны можно расширять, не накладывает ограничений на использование единой программной системы моделирования.
|
||||
|
||||
Модель TOGAF. включает 4 области описаний: бизнес, приложения, архитектура данных, технологическая (инфраструктура).
|
||||
|
||||
Модель Garner фактически не определяет ничего. в методике сформулированы ряд шагов, не детализированных до конкретных процессов. этапов 4 - бизнес, техническая архитектура, инфраструктура, безопасность. в 2007 добавили таймлайн, то есть наложили изменения системы на временную ось. Архитектура предприятия может иметь больше трёх осей (измерений). Элементы очень похожи на UML. Есть механизм типов. Для каждого типа вопросов есть своя диаграмма.
|
||||
|
||||
Archmate.
|
||||
делит модели на внутреннюю и внешнюю структуру. Сервис и интерфейс - это единицы функциональности, которые предоставляют приложения внутри или снаружи
|
||||
|
||||
При описании часто описываются только внутренние работы, только один уровень работы или ориентированно на сервис.
|
||||
|
||||
\newpage
|
||||
\section{BPMN}
|
||||
модель должна давать полное точное и адекватное описание системы.
|
||||
нотация - это графические элементы для построения модели
|
||||
аналитическое моделирование заключается в построении модели, основанной на описании поведения объекта или системы объектов в виде аналитических выражений. разработка исполняемых моделей использует более точные методы моделирования.
|
||||
|
||||
бпмн чаще используется для более верхнеуровневого описания. если модель перестала быть актуальной то надо выявлять целесообразность документирования часто меняющейся модели. Задача бпмн - описание продуктов и процессов для бизнес-аналитиков и руководителей. Связующее звено между пользователями и разработчиками. то есть понятно широкому кругу людей. нотация позволяет начать с высокоуровневой аналитики. по мере понимания работы модель уточняется и преобразуется в исполняемую модель.
|
||||
|
||||
бизнес-процесс, в отличие от бизнес-проекта (достигающего уникального результата) есть технология достижения результата, предполагается повторяемость действий и воспроизводимость результата. технология - совокупность методов и инструментов. Операция - единица работы, выполняемая непрерывно. Действие - акта взаимодействия оператора с обрабатываемым изделием.
|
||||
|
||||
Есть три уровня управления:
|
||||
\begin{enumerate}
|
||||
\item оперативное - исполнение каждого экземпляра с целью выявить те, которые выполняются с отклонениями. уменьшает число брака
|
||||
\item тактическое - контроль показателей на краткосрочном интервале. не предполагает изменения процессов
|
||||
\item стратегическое - контроль параметров на долгосрочном интервале. маркетинговые исследования, корпоративный дизайн.
|
||||
\end{enumerate}
|
||||
|
||||
применяется для описания и документации процессов. на втором уровне - аналитические процессы, позволяет описать и для айти сферы. на третьем уровне - описание для исполнителей.
|
||||
|
||||
\section{GSN, i*}
|
||||
Зачем выявлять требования? чтобы сделать точные и достаточные сценарии. Цели помогают понять кто чего хочет, объяснить угрозы, понять корректирующие меры и альтернативы.
|
||||
|
||||
все сценарии пишутся в определённой последовательности. обычно описывается луковичной диаграммой. на таких диаграммах показывают как позитивных так и негативных стейкхолдеров.
|
||||
|
||||
ставим цель, выбираем стратегию, строим предположения. в целях описываются все цели и требования заинтересованных сторон, кандидаты в требования, альтернативные варианты, могут противоречить одни другим, могут быть не всегда реалистичны, могут оказаться возможными только для некоторых вариантов.
|
||||
|
||||
Варианты - альтернативные подходы к решениям на любом уровне - функции ПО, конкурирующие за время/бюджет разработки, свойства ПО, конкурирующие за энергосбережение, массу итд, альтернативные алгоритмы достижения данной цели.
|
||||
|
||||
Критерии прохождения развилок на основе целей - размерности в котором оцениваются цели.
|
||||
|
||||
Предполагается следующий алгоритм:
|
||||
\begin{itemize}
|
||||
\item моделируем цели
|
||||
\item определяем контекст
|
||||
\item определить интерфейс
|
||||
\item исследовать варианты
|
||||
\item ...
|
||||
\end{itemize}
|
||||
|
||||
в модели требований обозначается область применения, область проекта и область конструирования системы.
|
||||
|
||||
SD - Strategic dependency - обеспечивает намеренное описание процесса в терминах отношений зависимости между участниками. состоит из набора узлов и ссылок. Для такого описания нам нужны сущности, действия и утверждения. зависимости потребуются от ресурсов, задач, целей и программных целей - основан на понятии нефункциональных требований в разработке ПО. Модель зависимостей использует роли и агентов.
|
||||
|
||||
GSN - Goal Structuring Notation
|
||||
Результат должен быть достижим. Цели структурируют чтобы предварительно подготовить аргументы, используется для выделения того, чего не хватает на схеме или в начинании.
|
||||
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{0}
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Семинар 1 2022-02-11}
|
||||
Систему можно рассматривать с разных точек зрения (программист, аналитик, заказчик). Система имеет назначение в своём физическом окружении. Назначение системы - это её функция или поведение, игра по роли. Система прежде всего называется по её роли/назначению/поведению, функции.
|
||||
|
||||
Ролевой объект может иметь имя, отличающееся от имени конструктивных объектов, которые рассматриваются вне окружения. Роли и стейтхолдеры в танцах: танцор, партнёр, зритель, хореограф, тренер/педагог, музредактор, организатор мероприятия, худкостюм, гримёр, фотограф/видеограф, судьи.
|
||||
|
||||
В роль неправильно указывать
|
||||
\begin{itemize}
|
||||
\item человека
|
||||
\item начальника
|
||||
\item звание
|
||||
\item организацию
|
||||
\end{itemize}
|
||||
|
||||
В проекте достаточно указать 5 внешних ролей. Обычно забывают про множественность интересов и собственные интересы. Системные уровни:
|
||||
люди 5 мин в локации с 16.05 и до 16.10 танцуют:
|
||||
\begin{itemize}
|
||||
\item врач смотрит с точки зрения здоровья
|
||||
\item тренер смотрит на системные органы
|
||||
\item учитель смотрит на то как выполняются движения
|
||||
\item хореограф смотрит на общую композицию
|
||||
\item зрители и родственники смотрят на сочетание картинки и ритма
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Задание: диаграмма активности}
|
||||
Испольуется для описания процессов в зависимости от текущего состояния системы (см диаграмму состояний). Стандартизирует внешний вид описания действий, непосредственной логики.
|
||||
\begin{itemize}
|
||||
\item прямоугольник с закруглениями - обычная операция
|
||||
\item ромб - обычно if, но формально - switch
|
||||
\item широкие полосы - многопоточность, параллелизм
|
||||
\item начало
|
||||
\item конец
|
||||
\end{itemize}
|
||||
|
||||
% -танец
|
||||
% --начало (партнёры вместе)
|
||||
% --свимлейны
|
||||
% --танцор-девушка
|
||||
% ---упасть назад
|
||||
% --танцор-мужчина
|
||||
% ---попытаться поймать партнёршу
|
||||
% ---условие: если поймал
|
||||
% ----да (ничего не делать) - следующее действие - параллельность
|
||||
% ----нет (упасть рядом)
|
||||
% -----конец
|
||||
% --параллельность
|
||||
% ---свои собственные движения каждого партнёра происходящие одновременно
|
||||
% --конец параллельности
|
||||
% --танец (движения партнёров, элементы парного танца)
|
||||
% --условие: в процессе танца на сцену бросили букет
|
||||
% ---да (сделать его элементом танца)
|
||||
% ---нет (ничего не делать)
|
||||
% --вернуться к условию
|
||||
% --конец
|
||||
|
||||
% -а ещё есть расширение SDL которое формализует прямоугольники для описания
|
||||
% СОСТОЯНИЕ
|
||||
% ВЫЗОВ ПРОЦЕДУРЫ
|
||||
% ВВОД
|
||||
% ВЫВОД
|
||||
% СОХРАНЕНИЕ
|
||||
% ЗАДАЧА
|
||||
% РЕШЕНИЕ
|
||||
|
||||
\subsection{Семинар 2 2022-02-25}
|
||||
Диаграмма классов.
|
||||
\begin{enumerate}
|
||||
\item в е ж \item а б \item б е ж \item б в г д е
|
||||
\item в \item г \item б г \item е \item в г
|
||||
\item а б в г е з \item б \item а б в г \item в
|
||||
\end{enumerate}
|
||||
\end{document}
|
|
@ -0,0 +1,166 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
%\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{1}{Имитационное моделирование архитектурных решений}{Моделирование информационных процессов и систем}{а}{Кадырбаева А.Р.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель работы}
|
||||
Целью работы является ознакомление с современными средствами имитационного моделирования архитектурных решений.
|
||||
|
||||
\textit{В связи с возникшими проблемами с установкой среды, указанной в методических материалах было выдано другое задание, с применением альтернативного инструментария.}
|
||||
|
||||
\subsection{Задача}
|
||||
Промоделировать работу билетных касс. В кассы есть единая очередь, которую обслуживают две основные кассы. Если основные кассы не справляются с потоком покупателей, то открывается третья касса. Поток покупателей меняется в зависимости от времени суток и становится больше в выходные дни. Расписание потока покупателей приведено ниже.
|
||||
\textbf{Рабочие дни:}
|
||||
\begin{itemize}
|
||||
\item [] 8:00–13:00 — десять человек в час;
|
||||
\item [] 13:00–16:00 — пятнадцать человек в час;
|
||||
\item [] 16:00–22:00 — двадцать человек в час.
|
||||
\end{itemize}
|
||||
\textbf{Выходные дни:}
|
||||
\begin{itemize}
|
||||
\item [] 9:00–12:00 — двадцать человек в час;
|
||||
\item [] 12:00–21:00 — сорок человек в час.
|
||||
\end{itemize}
|
||||
Покупатели, время ожидания покупки у которых превысило час, уходят из касс, не купив билета. Время обслуживания одного покупателя в кассах меняется случайным образом от 2 до 15 минут и в среднем составляет 5 минут. Предусмотреть в модели учет купивших и некупивших билеты.
|
||||
\subsection{Задача для самостоятельного решения}
|
||||
\begin{enumerate}
|
||||
\item Выявите узкие места в модели и предложите решение.
|
||||
\item Творческий проект. Создайте модель массового обслуживания. Принимаются собственные инициативы. Если таковых нет, то обратитесь к преподавателю.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Этапы решения}
|
||||
\begin{enumerate}
|
||||
\item Задание логики работы модели:
|
||||
\begin{enumerate}[label=\asbuk*),ref=\asbuk*]
|
||||
\item создание модели;
|
||||
\item моделирование прихода покупателей;
|
||||
\item моделирование очереди покупателей;
|
||||
\item моделирование процесса покупки;
|
||||
\item моделирование ухода покупателей из касс.
|
||||
\end{enumerate}
|
||||
\item Уточнение расписаний:
|
||||
\begin{enumerate}[label=\asbuk*),ref=\asbuk*]
|
||||
\item задание расписания прихода покупателей;
|
||||
\item задание расписания работы кассиров;
|
||||
\item задание расписания перерывов в работе кассиров;
|
||||
\item привязка расписания покупателей;
|
||||
\item привязка расписания работы кассиров;
|
||||
\item привязка расписания перерывов в работе кассиров.
|
||||
\end{enumerate}
|
||||
\item Создание резервной кассы и ухода клиентов, чье ожидание покупки превысило час:
|
||||
\begin{enumerate}[label=\asbuk*),ref=\asbuk*]
|
||||
\item моделирование резервной кассы и ресурсов;
|
||||
\item организация ограничения времени ожидания в кассах;
|
||||
\item проверка работоспособности модели, добавление часов;
|
||||
\item организация ухода покупателей, не купивших билет.
|
||||
\end{enumerate}
|
||||
\item Добавление динамических графиков в модель:
|
||||
\begin{enumerate}[label=\asbuk*),ref=\asbuk*]
|
||||
\item создание наборов данных по проданным и непроданным билетам;
|
||||
\item создание круговой диаграммы по покупателям;
|
||||
\item создание временн\'{о}го графика;
|
||||
\item проверка работоспособности модели.
|
||||
\end{enumerate}
|
||||
\end{enumerate}
|
||||
\section{Результаты проведенных опытов и проеланной работы}
|
||||
\subsection{Создание модели}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=16cm]{01-model-draft.png}
|
||||
\caption{Черновик созданной модели}
|
||||
\label{pic:model-draft}
|
||||
\end{figure}
|
||||
|
||||
В среде моделирования была создана модель билетных касс (рис. \hrf{pic:model-draft}) с указанием единиц модельного времени - минутами. Из библиотеки моделирования процессов в рабочей области были созданы:
|
||||
\begin{itemize}
|
||||
\item Источник заявок (Source-\code{customer}) - блок моделирует появление заявок в модели. В нашем случае покупатели — это заявки. Начальное значение интенсивности заявок было установлено в 10 заявок в час (первый параметр из задания).
|
||||
\item Очередь покупателей (Queue-\code{queue}) - блок имитирует накопление заявок в модели, фактически моделирует очередь. Был отмечен пункт «Максимальная вместимость», поскольку в задании ничего не сказано об ограничениях длины очереди.
|
||||
\item Выбор кассы (SelectOutput) - блок осуществляет выбор очереди, поскольку покупатель может пройти на любую из (например, двух) касс. Пусть покупатель идет во вторую кассу, увидев, что в первой кассе собралось более трех человек. Если величина, возвращенная функцией \code{size()} объекта \code{booking1}, будет больше 3, то значит, что в эту кассу покупатель не пойдет \code{booking1.size() < 4}.
|
||||
\item Ресурсы для обработки заявок (ResourcePool-\code{booking\_clerk}) - блок не связывается ни с каким блоком в модели, так как через него не должны проходить заявки. Поскольку кассиры могут передвигаться от кассы к кассе, тип ресурса был задан как «Движущийся», с указанием скорости в 2 км/ч. Также было указано количество кассиров: 2.
|
||||
\item Модель обслуживания (Service-\code{booking1,2}) - блок Service, который включает в себя логику работы: захват ресурсов, удержание заявки и ресурсов, освобождение ресурсов. Блокам была задана вместимость собственных очередей 2 и время задержки (задается функцией треугольного распределения со средним значением 5 минут, минимальным значением 2 минуты и максимальным значением 15 минут \code{triangular(2, 5, 15)}). В «Набор ресурсов» модели обслуживания добавлен созданный ресурс \code{booking\_clerk}. Так в первой и во второй кассах будут работать указанные в ресурсах 2 кассира.
|
||||
\item Уход покупателя (Sink-\code{exit}) - блок, завершающий исполнение заявки, соединён с выходами обеих касс.
|
||||
\end{itemize}
|
||||
В результате запуска моделирования поведения чернового варианта модели были получены значения, показанные на рис. \hrf{pic:model-launch}. Модель с ненастроенным расписанием показывает, что в результате обслуживания 303 покупателей кассиры в среднем были заняты 57\% времени, причём вторая касса использовалась только для 14 покупателей ($4,6(2046)\%$).
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=16cm]{01-model-launch.png}
|
||||
\caption{Черновик созданной модели}
|
||||
\label{pic:model-launch}
|
||||
\end{figure}
|
||||
\subsection{Уточнение расписаний}
|
||||
К созданной модели были добавлены следующие компоненты:
|
||||
\begin{itemize}
|
||||
\item Расписание прихода покупателей (\code{schedule\_customer}) - тип расписания «Интенсивность», дискретизация задана в часах, расписание составлено на неделю, поскольку в задании было сказано, что интенсивность меняется по будням и выходным дням, полное расписание представлено на рис. \hrf{pic:schedule-customer};
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.45\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{01-schedule-customer.png}
|
||||
\caption{Расписание интенсивности покупателей}
|
||||
\label{pic:schedule-customer}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.45\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{01-schedule-clerks-timeout.png}
|
||||
\caption{Расписание перерывов работы кассиров}
|
||||
\label{pic:sched-clerk-to}
|
||||
\end{subfigure}
|
||||
\caption{Расписания в модели}
|
||||
\label{pic:schedules}
|
||||
\end{figure}
|
||||
\item Расписание работы кассиров - установлено в значения 8:00 - 22:00, расписание перерывов в работе кассиров представлено на рис. \hrf{pic:sched-clerk-to}.
|
||||
\item Объект \code{customer} был изменён так, чтобы прибытие осуществлялось не согласно интенсивности, а по расписанию интенсивности;
|
||||
\item Объект \code{booking\_clerk} был изменён так, чтобы количество задавалось не константно, а по расписанию, также в раздел «Смены» было добавлено расписание перерывов;
|
||||
\end{itemize}
|
||||
\subsection{Создание резервной кассы и ухода клиентов, чье ожидание покупки превысило час}
|
||||
Для моделирования резервной кассы был использован аналогичный основным кассам блок service. Время обработки было задано чуть меньше, чем в основных кассах (\code{triangular(1, 3, 15)}). К резервной кассе был привязан дополнительный ресурс \code{reserved\_clerk}. Выход резервной кассы ведёт к объекту \code{exit}.
|
||||
|
||||
Согласно условиям задачи тайм-ауты в первой и второй кассе равны 30 минутам, а в третьей кассе — 20 минут. Выходы OutTimeout объектов \code{booking1} и \code{booking2} ведут на вход объекта \code{booking3}. Таким образом, покупатели, чье время ожидания в первой и второй кассах превысило 30 минут, идут в резервную кассу. Уход покупателей, не купивших билет, моделируется так же, как и уход покупателей, купивших билет, но в вхыод \code{without\_ticket}.
|
||||
|
||||
\section{Анализ полученных результатов и выводы}
|
||||
Для сбора данных по количеству проданных билетов во время работы модели используется объект Набор данных. Поскольку нас интересует динамика продаж билетов, то по оси Х зададим модельное время. По оси Y будем сохранять количество покупателей, прошедших через выход (\code{exit.count()}). Данные в наборе обновляются каждые три минуты. Для сбора данных по количеству потерянных билетов \code{without\_ticket.count()} (считаем минимальные потери, то есть каждый ушедший покупатель мог купить один билет). Для удобства визуализации были созданы диаграммы (графики) и круговая диаграмма продаж и упущенных покупателей. На круговой диаграмме, видно конечный результат моделирования - финальное количество купленных билетов и упущенных покупателей.
|
||||
|
||||
В результате запуска модели были получены значения, представленные на рис. \hrf{pic:model-final}.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=15cm]{01-model-final.png}
|
||||
\caption{Результат запуска модели}
|
||||
\label{pic:model-final}
|
||||
\end{figure}
|
||||
|
||||
Симуляция идеальных условий для проектирования системы или изменений системы, выявление «узких мест» и возможность рассмотреть разные стороны работы системы. AnyLogic позволяет сымитировать действия системы с достаточной степенью детализации и гибкости, поэтому полученные сведения могут считаться достоверными и подвергаться дальнейшему анализу.
|
||||
|
||||
\section{Контрольные вопросы}
|
||||
\begin{itemize}
|
||||
\item \textbf{Выявите узкие места в модели и предложите решение.}
|
||||
\begin{enumerate}
|
||||
\item Очевидно, что система не удовлетворяет никаким реалистичным требованиям продаж, поскольку количество упущенных покупателей превышает количество проданных в $\approx 3$ раза. Одним из самых простых решений может быть открытие третьей кассы на постоянной основе.
|
||||
\item Модель не учитывает, что пользователи, стоящие в общей очереди, скорее всего, не будут в ней стоять после завершения работы касс, поэтому общую очередь следует обнулять в 22:01 каждого дня.
|
||||
\item Расписания, представленные на рис. \hrf{pic:schedules} в модели менять не целесообразно, поскольку рабочий день и статистика посещений касс вряд ли изменятся по желанию системного аналитика. В связи с чем необходимо изменить логику работы модели. А именно - условие перехода от одной кассы к другой. Так, если каждый покупатель будет отправляться на кассу, которая содержит меньше людей, это позволит более равномерно распределить общий поток.
|
||||
\end{enumerate}
|
||||
\item \textbf{Творческий проект. Создайте модель массового обслуживания.}
|
||||
В индивидуальном задании реализована модель обслуживания интернет-магазина. В интернет-магазин с некоторой интенсивностью приходят заказы, несколько человек с разной скоростью могут обрабатывать заказы и отправлять их на доставку. Доставка осуществляется командой курьеров, по понятной причине, работающей медленнее, но у них больший по длительности рабочий день и скорость перемещения. В результате моделирования (рис. \hrf{pic:model-indi}) стало очевидно, что было потеряно $\approx8\%$ заказов. Также поверхностный анализ показывает, что более загруженное работой подразделение - это курьеры ($68\%$ против $21\%$ у сотрудников, обрабатывающих заказы). Более детально рассмотрев полученную статистику, можно увидеть, что отказы из-за задержек происходят в системе \textbf{только} на этапе доставки, то есть сотрудников склада целесообразно переквалифицировать в сотрудников доставки для снижения показателя потерь.
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\includegraphics[height=15cm, angle=90]{01-modify-final.png}
|
||||
\caption{Моделирование работы интернет-магазина}
|
||||
\label{pic:model-indi}
|
||||
\end{figure}
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,150 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
%\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лаботаторной}{2}{Создание и использование метамоделей}{Моделирование информационных процессов и систем}{а}{Кадырбаева А.Р.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель работы}
|
||||
Ознакомление с методами и средствами model-driven development, создания и использования метамоделей, автоматической генерации кода.
|
||||
Задание: необходимо ознакомиться с основами работы с метамоделями с использованием Ecore, а также освоить применение инструментов Eclipse EMF.
|
||||
|
||||
\section{Выполнение}
|
||||
Для выполнения работы было установлено программное обеспечение Eclipse Modeling Tools\footnote{прямая ссылка на страницу загрузок: https://www.eclipse.org/downloads/packages/}.
|
||||
\begin{enumerate}
|
||||
\item Создан новый проект с именем webpage и классами, указанными на рис. \hrf{pic:first-model}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[height=8cm]{02-frist-model.png}
|
||||
\caption{Диаграмма классов с отношениями}
|
||||
\label{pic:first-model}
|
||||
\end{figure}
|
||||
\item Для верхнего уровня модели был задан адрес артефакта \code{com.vogella.emf.webpage.model}.
|
||||
\item Был сгенерирован код на языке Java для описанной модели.
|
||||
\item Созданы ещё два проекта: \code{webpage.edit} и \code{webpage.editor}. На основе модели в рамках запущенного \code{Webpage.editor} были созданы демонстрационные экземпляры сущностей \code{Web} и \code{Webpage} (рис. \hrf{pic:instance-first-model}).
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[height=8cm]{02-instance-first-model}
|
||||
\caption{Экземпляр приложения по модели}
|
||||
\label{pic:instance-first-model}
|
||||
\end{figure}
|
||||
\item В методических указаниях не очевидно, какой именно проект нужно создать и в какую часть манифеста добавить зависимость, пункт пропущен.
|
||||
\item Была создана переопределённая функция \code{toString();} При переопределении была отмечена особеность, что сохранить многострочное тело функции в модели недостаточно (в файле \code{genmodel} сохраняется только первая строка), необходимо добавить тело функции полностью непосредственно в свойства функции в файле \code{genmodel}.
|
||||
\item Был создан тестовый метод ввода некоторого целого числа.
|
||||
\item Были проработаны механизмы наследования классов.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Индивидуальное задание}
|
||||
Индивидуальным заданием к лабораторной работе было описание небольшого проекта в приложении для моделирования и создание классов на языке Java по заданному описанию. Было выбрано приложение-расширение для обмена сообщениями в информационных системах.
|
||||
|
||||
Для обмена сообщениями в системе необходимо хранить:
|
||||
\begin{itemize}
|
||||
\item Объект сообщения;
|
||||
\item Данные сообщения;
|
||||
\item Тип данных сообщения;
|
||||
\item Метаданные сообщения;
|
||||
\item Пользователя;
|
||||
\item Роль пользователя;
|
||||
\end{itemize}
|
||||
|
||||
В Eclipse Modeling Framework была создана модель данных, показанная на рис. \hrf{pic:indi-model}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{02-mailing.png}
|
||||
\caption{Упрощённая модель данных приложения для обмена сообщениями}
|
||||
\label{pic:indi-model}
|
||||
\end{figure}
|
||||
|
||||
Поскольку все сообщения сохраняются в БД и сразу доступны всем пользователям, то необходимо определить разделение прав доступа к сообщениям (видимость только отправителю и получателю), что сделано привязкой сообщения к пользователю. Также пользователь может начать писать сообщение, но не отправить его, удалить сообщение или отправить в корзину/избранное/папку. Для всех манипуляций с сообщением создан класс метаинформации о сообщении, содержащий флажки (булевы значения), говорящие о разных состояниях объекта сообщения. Содержание сообщения может быть разнообразным, поэтому принято решение хранить все данные в максимально простом типе: обычный массив байтов, который может быть представлен как текст, изображение, ссылка на сущность в приложении, другое сообщение, пользователя, и так далее. Пользователи в данном варианте приложения могут иметь несколько ролей: самая простая - это просто отправка и получение сообщений, модератор - пользователь, имеющий право изменять метаинформацию чужих сообщений, администратор - пользователь, имеющий право удалять чужие сообщения. Никакие пользователи не могут редактировать сообщения для сохранения достоверности. Все сообщения удаляются с применением технологии soft-delete, которая не удаляет объект из БД, а только помечает его, как удалённый. Сгенерированные структуры представлены на рис. \hrf{pic:descriptors}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-mailing-ecore.png}
|
||||
\caption{Ecore}
|
||||
\label{pic:ecore}
|
||||
\end{subfigure}
|
||||
\hfill
|
||||
\begin{subfigure}[b]{0.4\textwidth}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{02-mailing-genmodel.png}
|
||||
\caption{Genmodel}
|
||||
\label{pic:genmodel}
|
||||
\end{subfigure}
|
||||
\caption{Сгенерированные файлы метамоделей}
|
||||
\label{pic:descriptors}
|
||||
\end{figure}
|
||||
|
||||
Полные листинги сгенерированных классов представлены в приложениях \hrf{appendix:interface}, \hrf{appendix:implement}, \hrf{appendix:util}.
|
||||
|
||||
\section{Контрольные вопросы}
|
||||
\subsection{Можно ли установить пустую строку в качестве значения по умолчанию? Как это сделать? Как удалить пустое значение?}
|
||||
Это возможно. Чтобы установить пустую строку в качестве значения по умолчанию, необходимо выполнить следующие действия:
|
||||
\begin{enumerate}
|
||||
\item выбрать атрибут;
|
||||
\item в свойствах выбрать поле значения «Литерал значения по умолчанию»;
|
||||
\item оставить значение пустым.
|
||||
\end{enumerate}
|
||||
|
||||
Чтобы удалить это пустое значение, необходимо нажать «Восстановить значение по умолчанию» на панели инструментов.
|
||||
|
||||
\subsection{Что такое модель данных?}
|
||||
Модель данных - это совокупность модели и метамодели, описывающих структуру и связи классов и объектов в приложении, составляющих абстрактное представление доступа к данным, с которым взаимодействует пользователь.
|
||||
|
||||
\subsection{Какие методы генерации классов существуют? Опишите их.}
|
||||
Классы на языках программирования можно описывать несколькими способами:
|
||||
\begin{itemize}
|
||||
\item вручную по мере описания проекта и возникновения необходимости;
|
||||
\item вручную согласно заранее описанной модели системы;
|
||||
\item автоматизированно приложением codegen на основе описанной модели системы;
|
||||
\item автоматизированно на основе метаданных ORM или реляционной БД;
|
||||
\item автоматизированно одновременно с моделью БД (liquibase);
|
||||
\item автоматизированно на основе описанной модели с помощью приложений для моделирования.
|
||||
\end{itemize}
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
%\setcounter{secnumdepth}{0}
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\subsection{Листинги интерфейсов}
|
||||
\label{appendix:interface}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingFactory.java]{build/src-gen/mailing/MailingFactory.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingPackage.java]{build/src-gen/mailing/MailingPackage.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=Message.java]{build/src-gen/mailing/Message.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageContent.java]{build/src-gen/mailing/MessageContent.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageContentType.java]{build/src-gen/mailing/MessageContentType.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageMeta.java]{build/src-gen/mailing/MessageMeta.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=User.java]{build/src-gen/mailing/User.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=UserRole.java]{build/src-gen/mailing/UserRole.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=UserRolesEnum.java]{build/src-gen/mailing/UserRolesEnum.java}
|
||||
\subsection{Листинги реализаций}
|
||||
\label{appendix:implement}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingFactoryImpl.java]{build/src-gen/mailing/impl/MailingFactoryImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingPackageImpl.java]{build/src-gen/mailing/impl/MailingPackageImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageContentImpl.java]{build/src-gen/mailing/impl/MessageContentImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageImpl.java]{build/src-gen/mailing/impl/MessageImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MessageMetaImpl.java]{build/src-gen/mailing/impl/MessageMetaImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=UserImpl.java]{build/src-gen/mailing/impl/UserImpl.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=UserRoleImpl.java]{build/src-gen/mailing/impl/UserRoleImpl.java}
|
||||
\subsection{Листинги утилитарных классов}
|
||||
\label{appendix:util}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingAdapterFactory.java]{build/src-gen/mailing/util/MailingAdapterFactory.java}
|
||||
% \lstinputlisting[language=Java, style=JCodeStyle, caption=MailingSwitch.java]{build/src-gen/mailing/util/MailingSwitch.java}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,86 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\usepackage{tikz-uml}
|
||||
\usepackage{pgfopts}
|
||||
\usepackage{pgfkeys}
|
||||
|
||||
\usetikzlibrary{positioning, math}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{3}{Анализ поведения систем и их компонентов}{Методы исследования и моделирования информационных процессов и систем}{а}{А.Р. Кадырбаева}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Ознакомление студентов с методами и средствами анализа поведения систем и их компонентов, выраженного при помощи диаграмм UML.
|
||||
\section{Задание}
|
||||
В данной лабораторной работе необходимо ознакомиться с основами стандарта fUML, расширяющего возможности UML, а также освоить применение основанных на использовании этого стандарта программных средств, позволяющих производить анализ диаграмм UML. В таблице \hrf{table:task} представлено индивидуальное задание.
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabular}{|c|p{100mm}|p{30mm}|}
|
||||
\hline
|
||||
Вариант & Задание & Количество вопросов для верификации \\ [0.5ex]
|
||||
\hline
|
||||
11 & Работа копирайтера. Определяем поведение состояний «Выполнение работы», «Оплата работы», «Поиск работы», «Заключение контракта», «Невозможность оплаты заказа», «Невозможность выполнения заказа» & 5 \\ [1ex]
|
||||
\hline
|
||||
\end{tabular}
|
||||
\caption{Задание по варианту}
|
||||
\label{table:task}
|
||||
\end{table}
|
||||
\section{Выполнение работы}
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{tikzpicture}[yscale=-1]
|
||||
\umlstateinitial[x=-4, y=-6, name=initial]
|
||||
\umlbasicstate[x=-3, name=search, entry=мораль-, exit=мораль+]{Поиск работы}
|
||||
\umlbasicstate[x=6, y=-3, name=failExec, entry=мораль-, exit=опыт+]{\shortstack{Невозможно\\выполнение}}
|
||||
\umlbasicstate[x=-3, y=5, name=contract, exit=опыт+, entry=мораль+]{Контракт}
|
||||
\umlbasicstate[x=-3, y=10, name=exec, exit=опыт+, entry=мораль+]{\shortstack{Выполнение\\работ}}
|
||||
\umlbasicstate[x=6, y=10, name=pay, exit=мораль+, entry=мораль+]{Оплата работы}
|
||||
\umlbasicstate[x=-3, y=15, name=failAward, exit=опыт+, entry=мораль-]{\shortstack{Невозможна\\оплата}}
|
||||
|
||||
\umltrans[]{initial}{search}
|
||||
\umlVHtrans[pos=1.5, arg=Недостаток компетенций]{search}{failExec}
|
||||
\umlVHtrans[arg=Возврат к поиску]{failExec}{search}
|
||||
\umltrans[pos=0.5, arg=Найдена работа по силам]{search}{contract}
|
||||
\umltrans[pos=0.5, arg=Приступаем к работе]{contract}{exec}
|
||||
\umltrans[pos=0.5, arg=Нормальный процесс]{exec}{pay}
|
||||
\umlVHtrans[arm1=-30mm, pos=1, arg=Попробовать с тем же работодателем]{pay}{contract}
|
||||
\umlVHtrans[arm1=-20mm, arg=Выйти на рынок]{pay}{search}
|
||||
\umltrans[pos=0.5, arg=Форс-мажор]{exec}{failAward}
|
||||
\umlHVHtrans[arm1=-20mm]{failAward}{search}
|
||||
\umlHVHtrans[arm1=-40mm, pos=0.7, arg=Неудача]{contract}{search}
|
||||
\end{tikzpicture}
|
||||
\caption{Диаграмма конечного автомата по заданию}
|
||||
\label{pic:fsm}
|
||||
\end{figure}
|
||||
|
||||
По заданию необходимо описать диаграмму состояний агента - копирайтера, осуществляющего свою трудовую деятельность. У агента, согласно задания, возможно шесть состояний:
|
||||
\begin{enumerate}
|
||||
\item Поиск работы - состояние, в котором агент осуществляет непосредственный просмотр вакансий;
|
||||
\item Невозможно выполнение - состояние, в котором агент осуществляет повышение квалификации. В него можно попасть только в результате неудачного поиска (недостаточно компетенций), из него можно выйти только в состояние поиска работы;
|
||||
\item Контракт - заключение контракта с работодателем, сюда можно попасть только после поиска работы или после успешной оплаты предыдущей работы. Выход из состояния возможен в состояние выполнения работ или если стороны не смогли договориться;
|
||||
\item Выполнение работы - единственное состояние, которое возможно после заключения контракта. В общем случае, в результате выполнения работы происходит переход в состояние оплаты, а в случае возникновения форс-мажорных ситуаций в состояние невозможности оплаты;
|
||||
\item Оплата работы - состояние в котором возможно оказаться только в результате выполнения работ. Из этого состояния возможно попытаться заключить с работодателем новый контракт или начать новый поиск работы;
|
||||
\item Невозможна оплата - состояние, возникающее только в силу форс-мажорных ситуаций и может вести только к инициированию нового поиска работы.
|
||||
\end{enumerate}
|
||||
|
||||
Диаграмма конечного автомата по заданию представлена на рисунке \hrf{pic:fsm}.
|
||||
|
||||
\section{Выводы}
|
||||
Диаграммы конечных автоматов UML можно использовать для моделирования поведения класса, подсистемы, пакета или системы целиком. Диаграммы состояний предоставляют наглядный способ моделирования взаимодействия или коммуникации, которые происходят внутри внешних объектов и системы. Эти диаграммы используются для моделирования систем, основанных на событиях. Состояние объекта контролируется и изменяется с помощью события. Диаграммы состояний используются для описания изменения состояний объекта в прикладной системе.
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{№ 1}{Анализ данных системы видеонаблюдения в Прологе}{Представление знаний в информационных системах}{}{Лычков И.И.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Цель работы – исследовать возможности языка логического программирования Пролог для анализа ситуаций.
|
||||
\section{Задание}
|
||||
\textbf{Задание к лабораторной работе} - Для заданной физической среды предложить предикаты для описания положения и действий людей.
|
||||
|
||||
% придумать описать предикаты
|
||||
% придумать и описать факты
|
||||
% можно использовать вижл пролог 5.0 или использовать онлайн отладчик SWI Prolog
|
||||
|
||||
\textbf{Индивидуальное задание по варианту:} Предложить предикаты для описания поведения и действий людей на станции метро, описать их в разделе PREDICATES (придумайте не менее 10 предикатов). Создать предложения (в разделе CLAUSES) для определения:
|
||||
\begin{enumerate}
|
||||
\item Списка людей, задержавшихся на станции дольше указанного времени.
|
||||
\item Количества людей, пребывавших на станции в указанный промежуток времени.
|
||||
\item Людей, которые находились в центре зала более трёх раз.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Выполнение работы}
|
||||
Для моделирования поведения были придуманы следующие предикаты:
|
||||
\begin{itemize}
|
||||
\item человек зашёл на станцию
|
||||
\item человек покинул станцию
|
||||
\item человек прошёл центр станции
|
||||
\end{itemize}
|
||||
|
||||
\begin{lstlisting}[language=Prolog, frame=single]
|
||||
enteredStation(ivan, 70).
|
||||
enteredStation(petr, 10).
|
||||
enteredStation(fedor, 15).
|
||||
enteredStation(max, 15).
|
||||
enteredStation(serg, 15).
|
||||
enteredStation(anna, 10).
|
||||
enteredStation(olga, 25).
|
||||
enteredStation(irina, 50).
|
||||
|
||||
leftStation(ivan, 100).
|
||||
leftStation(petr, 150).
|
||||
leftStation(fedor, 25).
|
||||
leftStation(max, 100).
|
||||
leftStation(serg, 30).
|
||||
leftStation(anna, 50).
|
||||
leftStation(olga, 35).
|
||||
leftStation(irina, 70).
|
||||
|
||||
passedCenter(max).
|
||||
passedCenter(ivan).
|
||||
passedCenter(petr).
|
||||
passedCenter(max).
|
||||
passedCenter(max).
|
||||
passedCenter(anna).
|
||||
passedCenter(anna).
|
||||
passedCenter(olga).
|
||||
passedCenter(olga).
|
||||
passedCenter(olga).
|
||||
|
||||
person(max).
|
||||
person(ivan).
|
||||
person(petr).
|
||||
person(anna).
|
||||
person(olga).
|
||||
|
||||
passedCenter2(X,1):- passedCenter(X).
|
||||
|
||||
getDelay(P,D):-
|
||||
enteredStation(P,T1),
|
||||
leftStation(P,T2),
|
||||
D1 is T2-T1,
|
||||
D < D1.
|
||||
|
||||
getPersons(P,From,To):-
|
||||
enteredStation(P,F),
|
||||
leftStation(P,T),
|
||||
F >= From,
|
||||
T =< To.
|
||||
|
||||
getAmount(P, From, To, A):-
|
||||
findall(P, getPersons(P, From, To), Persons),
|
||||
length(Persons,A).
|
||||
|
||||
passedCenterMoreThan(P, X):-
|
||||
person(P),
|
||||
findall(Y, passedCenter2(P,Y), Persons),
|
||||
sum_list(Persons,A),
|
||||
A >= X.
|
||||
\end{lstlisting}
|
||||
|
||||
Результаты выполнения программы представлены на рис. \hrf{pic:results}.
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{01rpt-result.png}
|
||||
\caption{Снимок экрана с результатами выполнения программы}
|
||||
\label{pic:results}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\section{Контрольные вопросы}
|
||||
Что такое предикат?
|
||||
Из каких разделов состоит программа на Прологе?
|
||||
Что такое факты и правила?
|
||||
В чем заключается унификация и конкретизация при доказательстве целевой формулы?
|
||||
Что называется решением для программы на Прологе?
|
||||
Как строится дерево логического вывода при поиске решений?
|
||||
Объясните механизм отката при поиске решений.
|
||||
Как реализовать на Прологе подсчет количества фактов для определенного предиката?
|
||||
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\setcounter{secnumdepth}{0}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{2}{Логическое программирование в ограничениях}{Представление знаний в информационных системах}{}{Лычков И.И.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Цель работы – исследовать возможности языка логического программирования Пролог для анализа ситуаций.
|
||||
\section{Задание}
|
||||
11 предметов с весами [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30] кг соответственно необходимо разложить по корзинам с ограничением по суммарному весу в одной корзине не более 100 кг. В предположении о том, что в наличии имеется достаточно корзин для размещения всех предметов, определите наименьшее количество корзин, которое удовлетворяет указанным требованиям.
|
||||
|
||||
\textbf{Подсказка:} Для перебора значений количества N используемых корзин в диапазоне StartN..StopN используйте предикат \code{between(StartN, StopN, N)}.
|
||||
|
||||
\textbf{Правильное решение:} Минимально нужно 4 корзины. Раскладка предметов по корзинам:
|
||||
\begin{lstlisting}[language=Prolog]
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1].
|
||||
[0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0].
|
||||
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0].
|
||||
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0].
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\section{Выполнение работы}
|
||||
Результат работы программы представлен на снимке экрана рис. \hrf{pic:result}.
|
||||
\begin{lstlisting}[language=Prolog,style=CCodeStyle]
|
||||
:- use_module(library(clpfd)).
|
||||
|
||||
mylength(Length, List):-
|
||||
length(List, Length).
|
||||
|
||||
scalar(List, L):-
|
||||
scalar_product(List, L, #=<, 100).
|
||||
|
||||
uberSum(Column):-
|
||||
sum(Column, #=, 1).
|
||||
|
||||
buckets(AllBuckets) :-
|
||||
Items = [48,30,19,36,36,27,42,42,36,24,30],
|
||||
between(1, 11, Count),
|
||||
length(AllBuckets, Count), maplist(mylength(11), AllBuckets),
|
||||
maplist(scalar(Items), AllBuckets),
|
||||
append(AllBuckets, V), V ins 0..1,
|
||||
transpose(AllBuckets, Column),
|
||||
maplist(uberSum(), Column),
|
||||
label(V).
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\includegraphics[height=4cm]{1.png}
|
||||
\caption{Результат выполнения программы}
|
||||
\label{pic:result}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{№ 3}{Программирование наборов решений}{Представление знаний в информационных системах}{}{Лычков И.И.}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель работы}
|
||||
Получение практических навыков разработки логических программ на языке ASP программирования наборов решений.
|
||||
\section{Условие логической задачи}
|
||||
\subsection{Перевод}
|
||||
У Ван Ли, торговца китайским антиквариатом и артефактами, недавно был отличный месяц, когда он продал четырем покупателям со всего мира — Финляндии, Италии, Японии и Соединенных Штатов, — которые были в состоянии очень хорошо заплатить. Четыре проданных предмета представляли собой редкие нефритовые фигурки (пряжка для ремня, дракон, кузнечик и лошадь), каждая из которых была вырезана из нефрита разных цветов (темно-зеленого, светло-зеленого, красного и белого). Каждая фигурка относится к разным китайским династиям (Цзин, Мин, Сун и Тан). Сможете ли вы подобрать для каждой статуэтки свой цвет и династию, а также указать родную страну каждого покупателя?
|
||||
|
||||
\begin{enumerate}
|
||||
\item Редкий белый дракон (которого американка не купила) не происходил из династии Сун.
|
||||
\item Изысканная пряжка для ремня (не имеющая оттенка зеленого) была создана в 618 году нашей эры для императора династии Тан.
|
||||
\item Из трёх фигурок одна была куплена финном (это не дракон), одна из династии Цин (которая не досталась покупателю из Японии) и светло-зеленый предмет (который не был лошадью).
|
||||
\item Американка отказалась как от кузнечика, так и от произведения династии Сун, поскольку ни один из них, по её мнению, не подходил к её домашнему декору.
|
||||
\end{enumerate}
|
||||
|
||||
Определить: Товар -- Цвет -- Династия -- Страна покупателя
|
||||
|
||||
\subsection{Результат разбора условия задачи}
|
||||
\begin{itemize}
|
||||
\item \textcolor{red}{Страны}: Финляндия, Италия, Япония, Соединенные Штаты;
|
||||
\item \textcolor{blue}{Цвета}: темно-зелёный, светло-зеленый, красный, белый;
|
||||
\item \textcolor{teal}{Предмет}: пряжка для ремня, дракон, кузнечик, лошадь;
|
||||
\item \textcolor{green}{Династии}: Цзин, Мин, Сун, Тан.
|
||||
\end{itemize}
|
||||
\textcolor{violet}{Фиолетовым цветом} в тексте выделены дополнительные отношения между переменными.
|
||||
|
||||
|
||||
\subsection{Исходное}
|
||||
Wan Li, a dealer in Chinese antiques and artifacts, had an excellent month recently when he made sales to four customers from around the world -- \textcolor{red}{Finland}, \textcolor{red}{Italy}, \textcolor{red}{Japan}, and the \textcolor{red}{United States} -- who were willing and able to pay very good prices. The \textcolor{violet}{four items} were rare jade figurines (\textcolor{teal}{a belt buckle}, \textcolor{teal}{dragon}, \textcolor{teal}{grasshopper}, and \textcolor{teal}{horse}), each carved from a \textcolor{violet}{different color} of jade (\textcolor{blue}{dark green}, \textcolor{blue}{light green}, \textcolor{blue}{red}, and \textcolor{blue}{white}). Each piece dates from a \textcolor{violet}{different Chinese dynasty} (\textcolor{green}{Ching}, \textcolor{green}{Ming}, \textcolor{green}{Sung}, and \textcolor{green}{Tang}). Can you match each figurine with its color and dynasty, and give the home country of each buyer?
|
||||
|
||||
\begin{enumerate}
|
||||
\item The rare \textcolor{teal}{white dragon} (which the \textcolor{red}{American} \textcolor{violet}{didn't buy}) \textcolor{violet}{didn't come from} the \textcolor{green}{Sung} dynasty.
|
||||
\item The exquisite \textcolor{teal}{belt buckle} (which \textcolor{violet}{wasn't any} \textcolor{blue}{shade of green}) was created in 618 A.D. for an emperor of the \textcolor{green}{Tang} dynasty.
|
||||
\item \textcolor{violet}{Three of} the figurines were the one bought by the \textcolor{red}{Finn} (which \textcolor{violet}{wasn't} the \textcolor{teal}{dragon}), the one from the \textcolor{green}{Ching} dynasty (which \textcolor{violet}{didn't go to the buyer} from \textcolor{red}{Japan}), and the \textcolor{blue}{light green} object (which \textcolor{violet}{wasn't} the \textcolor{teal}{horse}).
|
||||
\item The \textcolor{red}{American} \textcolor{violet}{decided against both} the \textcolor{teal}{grasshopper} and the piece from the \textcolor{green}{Sung} dynasty, neither of which she felt would match her home decor.
|
||||
\end{enumerate}
|
||||
|
||||
Determine: Item -- Color -- Dynasty -- Country of buyer
|
||||
|
||||
\section{Решение}
|
||||
\begin{enumerate}
|
||||
\item Факты: страны, фигурки, цвета и династии.
|
||||
\small
|
||||
\begin{verbatim}
|
||||
country(finland; italy; japan; states).
|
||||
item(buckle).
|
||||
item(dragon).
|
||||
item(grasshopper).
|
||||
item(horse).
|
||||
color(dkgreen; ltgreen; red; white).
|
||||
dynasty(ching; ming; sung; tang).
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\item Генерирующие (выбирающие) правила: каждая фигурка может быть одного цвета, принадлежать какой-то одной династии и быть купленной представителем какой-то одной страны
|
||||
\small
|
||||
\begin{verbatim}
|
||||
{check_color(I, C) : color(C)} = 1 :- item(I).
|
||||
{check_dynasty(I, D) : dynasty(D)} = 1 :- item(I).
|
||||
{check_country(I, C) : country(C)} = 1 :- item(I).
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\item Глобальные ограничения: обязательно должны выполняться требования (описанные в тексте), а также из текста следует, что нет фигурок одинакового цвета, никто не купил две фигурки, от каждого временн\'{о}го периода была представлена только одна фигурка
|
||||
\small
|
||||
\begin{verbatim}
|
||||
:- check_color(I1, C), check_color(I2, C), I1 != I2.
|
||||
:- check_dynasty(I1, D), check_dynasty(I2, D), I1 != I2.
|
||||
:- check_country(I1, C), check_country(I2, C), I1 != I2.
|
||||
|
||||
:- not rule1.
|
||||
:- not rule2.
|
||||
:- not rule3.
|
||||
:- not rule4.
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\item Вспомогательные предикаты: поскольку правила не могут содержать одновременно и отрицание и переменную, такая логика должна быть выделена в отдельный предикат.
|
||||
\small
|
||||
\begin{verbatim}
|
||||
ofDyn_notJapan(It, Dyn) :-
|
||||
check_dynasty(It, Dyn), not check_country(It, japan).
|
||||
ofDyn_notStates(It, Dyn) :-
|
||||
check_dynasty(It, Dyn), not check_country(It, states).
|
||||
isGrasshopper_notStates(It) :-
|
||||
It == grasshopper, not check_country(It, states).
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
\end{enumerate}
|
||||
|
||||
\section{Листинг разработанной программы}
|
||||
\begin{lstlisting}[language=Prolog, style=CCodeStyle]
|
||||
%%writefile program.lp
|
||||
|
||||
% <@\lh{dkgreen}{1. Факты}@>
|
||||
country(finland; italy; japan; states). % <@\lh{dkgreen}{страны}@>
|
||||
item(buckle).
|
||||
item(dragon).
|
||||
item(grasshopper).
|
||||
item(horse). % <@\lh{dkgreen}{фигурки}@>
|
||||
color(dkgreen; ltgreen; red; white). % <@\lh{dkgreen}{цвета}@>
|
||||
dynasty(ching; ming; sung; tang). % <@\lh{dkgreen}{династии}@>
|
||||
|
||||
% 2. <@\lh{dkgreen}{Генерирующие правила}@>
|
||||
% <@\lh{dkgreen}{1 цвет у фигурки}@>
|
||||
{check_color(Item, Color) : color(Color)} = 1 :- item(Item).
|
||||
% <@\lh{dkgreen}{из 1 династии}@>
|
||||
{check_dynasty(Item, Dynasty) : dynasty(Dynasty)} = 1 :- item(Item).
|
||||
% <@\lh{dkgreen}{продано в 1 страну}@>
|
||||
{check_country(Item, Country) : country(Country)} = 1 :- item(Item).
|
||||
|
||||
ofDyn_notJapan(It, Dyn) :-
|
||||
check_dynasty(It, Dyn), not check_country(It, japan).
|
||||
ofDyn_notStates(It, Dyn) :-
|
||||
check_dynasty(It, Dyn), not check_country(It, states).
|
||||
isGrasshopper_notStates(It) :-
|
||||
It == grasshopper, not check_country(It, states).
|
||||
|
||||
% 3. Глобальные ограничения
|
||||
% <@\lh{dkgreen}{у двух фигурок не может быть один цвет}@>
|
||||
:- check_color(Item1, Color), check_color(Item2, Color), Item1 != Item2.
|
||||
% <@\lh{dkgreen}{у двух фигурок не может быть одна династия}@>
|
||||
:- check_dynasty(Item1, Dynasty), check_dynasty(Item2, Dynasty), Item1 != Item2.
|
||||
% <@\lh{dkgreen}{у двух фигурок не может быть один покупатель}@>
|
||||
:- check_country(Item1, Country), check_country(Item2, Country), Item1 != Item2.
|
||||
|
||||
% <@\lh{dkgreen}{Редкий белый дракон (которого американец не купил)}@>
|
||||
% <@\lh{dkgreen}{не происходил из династии Сун.}@>
|
||||
:- not rule1.
|
||||
% <@\lh{dkgreen}{Изысканная пряжка для ремня (не имеющая оттенка зеленого) была}@>
|
||||
% <@\lh{dkgreen}{создана в 618 году нашей эры для императора династии Тан.}@>
|
||||
:- not rule2.
|
||||
% <@\lh{dkgreen}{Из трёх фигурок одна была куплена финном (это не дракон), одна из}@>
|
||||
% <@\lh{dkgreen}{династии Цин (которая не досталась покупателю из Японии) и}@>
|
||||
% <@\lh{dkgreen}{светло-зеленый предмет (который не был лошадью).}@>
|
||||
:- not rule3.
|
||||
% <@\lh{dkgreen}{Американец отказался как от кузнечика, так и от произведения}@>
|
||||
% <@\lh{dkgreen}{династии Сун, поскольку ни один из них, по его мнению, не}@>
|
||||
% <@\lh{dkgreen}{подходил к его домашнему декору.}@>
|
||||
:- not rule4.
|
||||
|
||||
% 4. <@\lh{dkgreen}{Вспомогательные правила}@>
|
||||
rule1 :- check_color(dragon, white), not check_country(dragon, states), not check_dynasty(dragon, sung).
|
||||
rule2 :- check_dynasty(buckle, tang), not check_color(buckle, dkgreen), not check_color(buckle, ltgreen).
|
||||
rule3 :- check_country(I1, finland), I1 != dragon, ofDyn_notJapan(I2, ching), check_color(I3, ltgreen), I3 != horse, I1 != I2, I1 != I3, I2 != I3.
|
||||
rule4 :- isGrasshopper_notStates(I1), ofDyn_notStates(I2, sung), I1 != I2.
|
||||
|
||||
|
||||
% 5. <@\lh{dkgreen}{Указания по отображению результата}@>
|
||||
info(It,Col,Dyn,Cntr) :- check_color(It,Col), check_dynasty(It,Dyn), check_country(It,Cntr).
|
||||
#show info/4.
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Результаты работы}
|
||||
\begin{verbatim}
|
||||
clingo version 5.2.2
|
||||
Reading from program.lp
|
||||
Solving...
|
||||
Answer: 1
|
||||
info(buckle,red,tang,states)
|
||||
info(dragon,white,ching,italy)
|
||||
info(grasshopper,ltgreen,ming,japan)
|
||||
info(horse,dkgreen,sung,finland)
|
||||
SATISFIABLE
|
||||
|
||||
Models : 1
|
||||
Calls : 1
|
||||
Time : 0.003s (Solving: 0.0s 1st Model: 0.0s Unsat: 0.0s)
|
||||
CPU Time : 0.003s
|
||||
\end{verbatim}
|
||||
|
||||
\section{Интерпретация работы программы}
|
||||
|
||||
Красная нефритовая пряжка для ремня династии Тан была куплена покупательницей из США;
|
||||
|
||||
Дракон из белого нефрита времён династии Цин был куплен покупателем из Италии;
|
||||
|
||||
Кузнечик из светло-зелёного нефрита династии Мин продан покупателю из Японии;
|
||||
|
||||
Лошадь из тёмно-зелёного нефрита династии Сун продан покупателю из Финляндии.
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
% ... работе, номер, тема, предмет, ?а, кто
|
||||
\makeReportTitle{лабораторной}{4}{Исчисление дискретных событий}{Представление знаний в информационных системах}{}{И.И. Лычков}
|
||||
\newpage
|
||||
\thispagestyle{empty}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Получение практических навыков моделирования дискретно-событийных систем на языке логического программирования.
|
||||
|
||||
\section{Задание}
|
||||
В качестве исходных данных выдается словесное описание некоторой физической системы, а именно: общие правила её функционирования, состояние системы в начальный момент, список произошедших событий и вопрос относительно состояния одного из объектов системы в определенный момент времени. Также выдаются аксиомы исчисления дискретных событий. Требуется выделить в исходном описании все объекты, события, флюенты, придумать для них идентификаторы в программе, затем представить логику функционирования заданной системы в виде программы на языке ASP программирования наборов решений с помощью аксиом исчисления дискретных событий, отладить работу программы так, чтобы она выдавала ответ на указанный в задании вопрос относительно состояния одного из объектов системы в определенный момент времени.
|
||||
|
||||
\section{Выполнение}
|
||||
\subsection{Словесное описание системы согласно варианту}
|
||||
Имеется две аксиомы initiates и terminates. Если агент включает нагреватель воздушного шара, то нагреватель более не будет выключен и будет включен. Мы задаем глобальное ограничение о том, что воздушный шар не может находиться одновременно на двух разных высотах в один момент времени.
|
||||
|
||||
Когда нагреватель включен, высота воздушного шара изменяется по закону:
|
||||
\[h(t) = h(0) + V*t\]
|
||||
Когда нагреватель выключен, высота воздушного шара изменяется по закону:
|
||||
\[h(t) = h(0) - V*t,\]
|
||||
где V = 1 - скорость воздушного шара (задана константой)
|
||||
|
||||
Высота воздушного шара освобождается от закона инерции по событиям включения и выключения нагревателя. Имеем следующие факты и хронику событий. Воздушный шар изначально находится на нулевой высоте. В момент времени 1 нагреватель включают, а в момент времени 3 нагреватель выключают. Необходимо проверить, что в момент времени 3 высота воздушного шара равна 2V, а в момент времени 4 она равна V.
|
||||
\subsection{Перечень всех объектов, событий и флюентов с указанием их идентификаторов и смысловой нагрузки}
|
||||
События и флюенты в программе:
|
||||
\begin{itemize}
|
||||
\item \verb|turnOn| - событие включения нагревателя;
|
||||
\item \verb|turnOff| - событие выключения нагревателя;
|
||||
\item \verb|heating| - флюент, говорящий о том, что шар нагревается и летит вверх;
|
||||
\item \verb|falling| - флюент, говорящий о том, что шар охлаждается и падает;
|
||||
\item \verb|height(X)| - флюент, говорящий о текущей высоте шара.
|
||||
\end{itemize}
|
||||
|
||||
Имеется две аксиомы initiates и terminates.
|
||||
\begin{verbatim}
|
||||
initiates(turnOn, heating, Time) :- times(Time).
|
||||
terminates(turnOff, heating, Time) :- times(Time).
|
||||
|
||||
initiates(turnOff, falling, Time) :- times(Time).
|
||||
terminates(turnOn, falling, Time) :- times(Time).
|
||||
\end{verbatim}
|
||||
|
||||
Мы задаем глобальное ограничение о том, что воздушный шар не может находиться одновременно на двух разных высотах в один момент времени.
|
||||
\begin{verbatim}
|
||||
:- holdsAt(height(X1), T), holdsAt(height(X2), T), X1 != X2.
|
||||
\end{verbatim}
|
||||
|
||||
Имеем две аксиомы типа trajectory, описывающие поведение шара при нагревании и охлаждении:
|
||||
\begin{verbatim}
|
||||
trajectory(heating, T1, height(X2), T2) :-
|
||||
times(T1), times(T2), T1 < T2,
|
||||
holdsAt(height(X),T1),
|
||||
X2 = X + 1 * (T2 - T1).
|
||||
|
||||
trajectory(falling, T1, height(X2), T2) :-
|
||||
times(T1), times(T2), T1 < T2,
|
||||
holdsAt(height(X),T1),
|
||||
X2 = X - 1 * (T2 - T1).
|
||||
\end{verbatim}
|
||||
|
||||
Высота воздушного шара освобождается от закона инерции по событиям включения и выключения нагревателя:
|
||||
\begin{verbatim}
|
||||
releases(turnOff, height(X), T) :- holdsAt(height(X), T).
|
||||
releases(turnOn, height(X), T) :- holdsAt(height(X), T).
|
||||
\end{verbatim}
|
||||
|
||||
Имеем следующие факты и хронику событий. Воздушный шар изначально находится на нулевой высоте, в момент времени 1 нагреватель включают, а в момент времени 3 нагреватель выключают:
|
||||
\begin{verbatim}
|
||||
initiallyP(height(0)).
|
||||
initiallyN(heating).
|
||||
|
||||
happens(turnOn, 1).
|
||||
happens(turnOff, 3).
|
||||
\end{verbatim}
|
||||
|
||||
Необходимо проверить, что в момент времени 3 высота воздушного шара равна 2V, а в момент времени 4 она равна V.
|
||||
\begin{verbatim}
|
||||
info(F1, T1, F2, T2) :-
|
||||
holdsAt(height(F1), T1), holdsAt(height(F2), T2),
|
||||
F1==2, T1==3, F2 == 1, T2 == 4.
|
||||
#show info/4.
|
||||
\end{verbatim}
|
||||
\subsection{Результат выполнение программы}
|
||||
Результат выполнения программы представлен на рисунке \hrf{pic:result}.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[height=6cm]{04-lab-result.png}
|
||||
\caption{Результаты работы программы}
|
||||
\label{pic:result}
|
||||
\end{figure}
|
||||
|
||||
На рисунке \hrf{pic:result} видно, что программа нашла одно сочетание флюентов и временных отметок: в момент времени 3 высота воздушного шара равна 2, а в момент времени 4 она равна 1.
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{0}
|
||||
\section*{Приложения}
|
||||
\addcontentsline{toc}{section}{Приложения}
|
||||
\renewcommand{\thesubsection}{\Alph{subsection}}
|
||||
|
||||
\setcounter{secnumdepth}{5}
|
||||
\subsection{Полный листинг приложения по индивидуальному заданию}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
%*
|
||||
********************************************************************
|
||||
Стандартные аксиомы исчисления дискретных событий.
|
||||
********************************************************************
|
||||
*%
|
||||
|
||||
%% BEC1 - StoppedIn(t1,f,t2)
|
||||
stoppedIn(T1,Fluent,T2) :-
|
||||
times(T1), times(T2), T1<T2,
|
||||
terminates(Event,Fluent,T),
|
||||
happens(Event,T), T1<T, T<T2.
|
||||
|
||||
stoppedIn(T1,Fluent,T2) :-
|
||||
times(T1), times(T2), T1<T2,
|
||||
releases(Event,Fluent,T),
|
||||
happens(Event,T), T1<T, T<T2.
|
||||
|
||||
%% BEC2 - StartedIn(t1,f,t2)
|
||||
startedIn(T1,Fluent,T2) :-
|
||||
times(T1), times(T2), T1<T2,
|
||||
initiates(Event,Fluent,T),
|
||||
happens(Event,T), T1<T, T<T2.
|
||||
|
||||
startedIn(T1,Fluent,T2) :-
|
||||
times(T1), times(T2), T1<T2,
|
||||
releases(Event,Fluent,T),
|
||||
happens(Event,T), T1<T, T<T2.
|
||||
|
||||
%% BEC3 - HoldsAt(f,t)
|
||||
holdsAt(Fluent2,T2) :-
|
||||
times(T1),
|
||||
happens(Event,T1),
|
||||
initiates(Event,Fluent1,T1),
|
||||
trajectory(Fluent1,T1,Fluent2,T2),
|
||||
not stoppedIn(T1,Fluent1,T2).
|
||||
|
||||
%% BEC4 - HoldsAt(f,t)
|
||||
holdsAt(Fluent,T) :-
|
||||
times(T),
|
||||
initiallyP(Fluent),
|
||||
not stoppedIn(0,Fluent,T).
|
||||
|
||||
%% BEC5 - not HoldsAt(f,t)
|
||||
-holdsAt(Fluent,T):-
|
||||
times(T),
|
||||
initiallyN(Fluent),
|
||||
not startedIn(0,Fluent,T).
|
||||
|
||||
%% BEC6 - HoldsAt(f,t)
|
||||
holdsAt(Fluent,T) :-
|
||||
times(T),
|
||||
happens(Event,T1),
|
||||
initiates(Event,Fluent,T1), T1<T,
|
||||
not stoppedIn(T1,Fluent,T).
|
||||
|
||||
%% BEC7 - not HoldsAt(f,t)
|
||||
-holdsAt(Fluent,T):-
|
||||
times(T),
|
||||
happens(Event,T1),
|
||||
terminates(Event,Fluent,T1), T1<T,
|
||||
not startedIn(T1,Fluent,T).
|
||||
|
||||
times(0..5).
|
||||
|
||||
initiates(turnOn, heating, Time) :- times(Time).
|
||||
terminates(turnOff, heating, Time) :- times(Time).
|
||||
|
||||
initiates(turnOff, falling, Time) :- times(Time).
|
||||
terminates(turnOn, falling, Time) :- times(Time).
|
||||
|
||||
releases(turnOff, height(X), Time) :- holdsAt(height(X), Time).
|
||||
releases(turnOn, height(X), Time) :- holdsAt(height(X), Time).
|
||||
|
||||
trajectory(heating, T1, height(X2), T2) :-
|
||||
times(T1), times(T2), T1 < T2,
|
||||
holdsAt(height(X),T1),
|
||||
X2 = X + 1 * (T2 - T1).
|
||||
|
||||
trajectory(falling, T1, height(X2), T2) :-
|
||||
times(T1), times(T2), T1 < T2,
|
||||
holdsAt(height(X),T1),
|
||||
X2 = X - 1 * (T2 - T1).
|
||||
|
||||
:- holdsAt(height(X1), T), holdsAt(height(X2), T), X1 != X2.
|
||||
|
||||
releases(turnOn, heating, Time) :- times(Time).
|
||||
releases(turnOff, heating, Time) :- times(Time).
|
||||
|
||||
initiallyP(height(0)).
|
||||
initiallyN(heating).
|
||||
|
||||
happens(turnOn, 1).
|
||||
happens(turnOff, 3).
|
||||
|
||||
info(F1, T1, F2, T2) :- holdsAt(height(F1), T1), holdsAt(height(F2), T2), F1==2, T1==3, F2 == 1, T2 == 4.
|
||||
#show info/4.
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{../common-preamble}
|
||||
\input{../fancy-listings-preamble}
|
||||
\input{../bmstu-preamble}
|
||||
\setcounter{secnumdepth}{4}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{лабораторной}{№ 3}{Разработка и интеграция пользовательских инструкций в состав ядра Nios II}{Проектирование цифровых устройств на \\ программируемых логических интегральных схемах (ПЛИС)}{}{С.В. Фёдоров}
|
||||
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Освоить методику использования в составе системы на кристалле пользовательских периферийных модулей и пользовательских инструкций. Реализовать и отладить программное обеспечение системы на кристалле.
|
||||
|
||||
\section{Задачи}
|
||||
\begin{itemize}
|
||||
\item Изучить методики расширения набора команд процессора пользовательскими инструкциями.
|
||||
\item Реализовать программное обеспечение, использующее пользовательские инструкции на примере инструкции вычисления количества единиц в двоичном числе.
|
||||
\item Сравнить быстродействие с программной реализацией на базовом наборе команд.
|
||||
\item Выполнить индивидуальное задание.
|
||||
\end{itemize}
|
||||
|
||||
\section{Выполнение работы}
|
||||
По шагам из методического материала был создан проект в САПР Quartus Prime (доступен по \href{https://git.iovchinnikov.ru/ivan-igorevich/fpga-lab-2/commits/branch/lab3}{ссылке}).
|
||||
|
||||
Созданная пользовательская инструкция доступна для обращения из программного кода в прикладном проекте.
|
||||
|
||||
\section{Индивидуальное задание}
|
||||
В качестве индивидуального было дано следующее задание: описать пользовательскую инструкцию, принимающую на вход два 32-разрядных значения и возвращающая минимальное, максимальное, верхнее медианное и нижнее медианное значения. Схема получения данных на рис. \hrf{pic:indi-scheme}. Исходные данные представляют собой два 32-разрядных слова, каждое из которых необходимо разделить на четыре 8-разрядных слова, отсортировать все восемь 8-разрядных слов по возрастанию и взять их минимум (1), максимум (4) и медианы (2, 3).
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fontsize{12}{1}\selectfont
|
||||
\includesvg[scale=1.01]{pics/03-fpga-03-lab-indi-scheme.svg}
|
||||
\caption{Схема обработки данных}
|
||||
\label{pic:indi-scheme}
|
||||
\end{figure}
|
||||
|
||||
Поскольку сложность самой быстрой сортировки $O(N*\lg_2(N))$, принято решение опираться на то, что значений в искомом множестве всегда фиксированное число. Сложность задания состоит в том, чтобы получить медианы не отсортированного множества за время меньшее, чем $O(N*\lg_2(N))$. Отсутствие необходимости разработки для множеств не фиксированной длины позволяет воспользоваться несколькими способами получения медианных значений.
|
||||
|
||||
\subsection{Описание схемотехнического решения}
|
||||
Дан исходный числовой ряд (восемь байт, полученных из двух 32-разрядных переменных), например
|
||||
|
||||
\[ [31, 44, 216, 0, 132, 68, 18, 100]. \]
|
||||
|
||||
Алгоритм выполняется в несколько шагов:
|
||||
\begin{enumerate}
|
||||
\item сравнение соседних значений в ряду парами;
|
||||
\item меньшие значения сравнить с меньшими значениями пар, а большие с большими;
|
||||
\item взять меньшую из больших полученных пар и б\'{о}льшую из меньших, также сравнить меньшие с меньшими и б\'{о}льшие с б\'{о}льшими;
|
||||
\item выявить меньшее из меньшей пары, полученной в п. 2 и большее из большей.
|
||||
\end{enumerate}
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
[31, 44, 216, 0, 132, 68, 18, 100]
|
||||
\to
|
||||
\begin{bmatrix}
|
||||
31, 44 \\ 0, 216 \\ 68, 132 \\ 18, 100
|
||||
\end{bmatrix}
|
||||
\to
|
||||
\begin{bmatrix}
|
||||
0, 31 \\ 18, 68 \\ 44, 216 \\ 100, 132
|
||||
\end{bmatrix}
|
||||
\\ \to
|
||||
\begin{bmatrix}
|
||||
44, 100 \\ 31, 68
|
||||
\end{bmatrix}
|
||||
\\ \to [31, 44, 68, 100] \to 44, 68;
|
||||
\\ \to [0, 18], [132, 216] \to 0, 216.
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
Из приведённых вычислений очевидно, что исходное множество содержит:
|
||||
\begin{itemize}
|
||||
\item минимум = 0;
|
||||
\item максимум = 216;
|
||||
\item нижняя медиана = 44
|
||||
\item верхняя медиана = 68.
|
||||
\end{itemize}
|
||||
|
||||
Для реализации данного алгоритма был описан вспомогательный модуль на языке Verilog, возвращающий меньшее и большее из двух входящих чисел.
|
||||
|
||||
\begin{lstlisting}[language=Verilog,style=VerilogStyle]
|
||||
module lessmore (
|
||||
input [7:0] in1,
|
||||
input [7:0] in2,
|
||||
output logic [7:0] less,
|
||||
output logic [7:0] more
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
if (in1 < in2) begin
|
||||
less = in1;
|
||||
more = in2;
|
||||
end else begin
|
||||
less = in2;
|
||||
more = in1;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
\end{lstlisting}
|
||||
|
||||
Сам же алгоритм реализован в несколько «шагов», представляющих собой слои комбинационной логики
|
||||
\begin{lstlisting}[language=Verilog,style=VerilogStyle]
|
||||
module minmelhmax (
|
||||
input clk,
|
||||
input reset,
|
||||
input [31:0] in1,
|
||||
input [31:0] in2,
|
||||
output logic [31:0] result
|
||||
);
|
||||
|
||||
logic [7:0] step1less [0:3];
|
||||
logic [7:0] step1more [0:3];
|
||||
logic [7:0] step2less [0:3];
|
||||
logic [7:0] step2more [0:3];
|
||||
logic [7:0] median [0:3];
|
||||
logic [7:0] temp [0:3];
|
||||
|
||||
// 1: compare pairs
|
||||
lessmore s01 (in1[7:0], in1[15:8], step1less[0], step1more[0]);
|
||||
lessmore s02 (in1[23:16], in1[31:24], step1less[1], step1more[1]);
|
||||
lessmore s03 (in2[7:0], in2[15:8], step1less[2], step1more[2]);
|
||||
lessmore s04 (in2[23:16], in2[31:24], step1less[3], step1more[3]);
|
||||
|
||||
// 2: 1st step mins to mins, maxes to maxes
|
||||
lessmore s11 (step1less[0], step1less[1], step2less[0], step2more[0]);
|
||||
lessmore s12 (step1less[2], step1less[3], step2less[1], step2more[1]);
|
||||
lessmore s13 (step1more[0], step1more[1], step2less[2], step2more[2]);
|
||||
lessmore s14 (step1more[2], step1more[3], step2less[3], step2more[3]);
|
||||
|
||||
// 3: 2nd step less-maxes, more-mins
|
||||
lessmore s21 (step2less[2], step2less[3], median[0], median[1]);
|
||||
lessmore s22 (step2more[0], step2more[1], median[2], median[3]);
|
||||
|
||||
// 4: median of four
|
||||
lessmore s31 (median[0], median[1], temp[1], result[1]);
|
||||
lessmore s32 (median[2], median[3], result[2], temp[2]);
|
||||
|
||||
// 5: max and min of input
|
||||
lessmore s41 (step2less[0], step2less[1], result[0], temp[0]);
|
||||
lessmore s42 (step2more[2], step2more[3], temp[3], result[3]);
|
||||
endmodule
|
||||
\end{lstlisting}
|
||||
|
||||
Работа модуля была проверена на тестовом стенде
|
||||
|
||||
\subsection{Описание программного решения}
|
||||
Два входящих слова записываются во временный указатель и интерпретируются, как указатель на восемь 8-разрядных переменных \code{alt_u8}, далее цикл работает с ними как с массивом данных. На каждом шаге цикла ищется минимальный и максимальный элемент. Найденные элементы меняются местами с теми числами, которые находятся на месте действительно минимального и максимального элемента соответственно. Алгоритм являет собой совмещение \textit{сортировки выбором} и \textit{шейкерной сортировки}. Таким образом за четыре итерации получается сортированное множество, в котором необходимые значения берутся по индексу.
|
||||
|
||||
\begin{equation*}
|
||||
\begin{gathered}
|
||||
[31, 44, 216, 0, 132, 68, 18, 100] \to \\
|
||||
[0, 44, 100, 31, 132, 68, 18, 216] \to \\
|
||||
[0, 18, 100, 31, 44, 68, 132, 216] \to \\
|
||||
[0, 18, 31, 68, 44, 100, 132, 216] \to \\
|
||||
[0, 18, 31, 44, 68, 100, 132, 216]
|
||||
\end{gathered}
|
||||
\end{equation*}
|
||||
|
||||
Программная реализация алгоритма копирует исходные значения функцией \code{memset(dst, src, size)} и обрабатывает ситуацию, в которой найденный максимум равен найденному минимуму.
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
alt_u32 ones_sw (
|
||||
alt_u32* data_block_a,
|
||||
alt_u32* data_block_b,
|
||||
alt_u32 words) {
|
||||
alt_u32 result;
|
||||
int word;
|
||||
for (word = 0; word < words; ++word) {
|
||||
alt_u8 tmp[8];
|
||||
memset(tmp, data_block_a[word], 4);
|
||||
memset((tmp + 4), data_block_b[word], 4);
|
||||
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
int min = tmp[k];
|
||||
int max = min;
|
||||
for (int i = k; i < 8 - k; ++i) {
|
||||
if (min >= tmp[i]) {
|
||||
min = tmp[i];
|
||||
tmp[i] = tmp[k];
|
||||
tmp[k] = min;
|
||||
}
|
||||
|
||||
if ((max <= tmp[i]) && (max != min)) {
|
||||
max = tmp[i];
|
||||
tmp[i] = tmp[8 - k - 1];
|
||||
tmp[8 - k - 1] = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result += tmp[0];
|
||||
result += (tmp[3] << 8);
|
||||
result += (tmp[4] << 16);
|
||||
result += (tmp[7] << 24);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Результат и выводы}
|
||||
После запуска приложения были получены результаты, представленные на рис. \hrf{:}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
% \includegraphics[width=12cm]{.}
|
||||
\caption{}
|
||||
\label{pic:}
|
||||
\end{figure}
|
||||
|
||||
|
||||
Пользовательская инструкция для процессора Nios II -- это эффективный инструмент ускорения работы программы и выноса некоторых алгоритмов поточной обработки данных в аппаратную часть.
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{4}
|
||||
\section{Приложения}
|
||||
\subsection{Исходные коды проекта}
|
||||
\label{appendix:src}
|
||||
|
||||
\lstinputlisting[language=C,style=CCodeStyle,caption={\code{sem.c}},label={lst:sem}]{src/sem.c}
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
|
|
@ -1,69 +1,85 @@
|
|||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{settings/common-preamble}
|
||||
\input{settings/fancy-listings-preamble}
|
||||
\input{settings/bmstu-preamble}
|
||||
\setcounter{secnumdepth}{4}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{лабораторной}{4}{Проектирование цифрового синтезатора}{Проектирование цифровых устройств на \\ программируемых логических интегральных схемах (ПЛИС)}{}{С.В. Фёдоров}
|
||||
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Осуществить полный цикл проектирования цифрового устройства на ПЛИС на языке SystemVerilog. Реализовать генератор периодических функций на основе метода прямого цифрового синтеза на микросхеме семейства Cyclone IV E.
|
||||
|
||||
\section{Задачи}
|
||||
Прямой цифровой синтез -- это метод генерации сигнала заданной формы путём вычисления значений сигнала в последовательных дискретных отсчётах времени и преобразовании их в аналоговый сигнал с помощью ЦАП. Структура системы приведена на рис \hrf{pic:synth-scheme}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fontsize{14}{1}\selectfont
|
||||
\includesvg[scale=1.01]{pics/03-fpga-lab-04-01-synth.svg}
|
||||
\caption{Схема цифрового синтезатора}
|
||||
\label{pic:pic:synth-scheme}
|
||||
\end{figure}
|
||||
|
||||
Инкремент фазы поступает на вход накопителя фазы и определяет скорость изменения фазы формируемого сигнала. Накопитель фазы выдаёт номер текущего отсчёта в периоде на просмотровую таблицу, содержащую образ одного периода синуса. Значение с выхода просмотровой таблицы поступает на дельта-сигма модулятор, который работает как однобитный ЦАП. Модулятор формирует последовательность нулей и единиц на высокой частоте, соответствующую текущему уровню на входе модулятора, после чего двухуровневый выходной сигнал модулятора подается на выход ПЛИС и сглаживается простым RC фильтром НЧ. При изменении приращения фазы изменяется частота формируемого на выходе сигнала.
|
||||
|
||||
\section{Выполнение работы}
|
||||
\subsection{Разработка модулей}
|
||||
\subsubsection{Накопитель фазы}
|
||||
\textbf{Интерфейс модуля}
|
||||
\begin{frm} \begin{itemize}
|
||||
\item [] \textbf{Входы:}
|
||||
\code{phinc[7:0]} -- величина приращения фазы за один период тактового сигнала;
|
||||
\code{clk} -- тактовый сигнал;
|
||||
\code{clr_n} -- вход асинхронного сброса;
|
||||
\item [] \textbf{Выходы:}
|
||||
\code{phase[7:0]} -- 8 старших значащих битов выхода накопителя;
|
||||
\item [] \textbf{Параметры:}
|
||||
\code{WIDTH} -- разрядность накопителя фазы (значение по умолчанию -- 14).
|
||||
\end{itemize} \end{frm}
|
||||
|
||||
\textbf{Принцип действия}
|
||||
Накопитель фазы -- это классический аккумулятор, который сохраняет накопленную сумму в регистре и использует её в качестве одного из операндов сумматора на каждом такте. Второй операнд поступает с входа и определяет величину приращения фазы. Разрядность аккумулятора должна быть параметризирована. Входные значения складываются с младшими битами регистра аккумулятора, а на выход поступают старшие 8 разрядов аккумулятора, поэтому при разрядности аккумулятора M и значении N на входе приращения фазы выход фазы будет увеличиваться на единицу один раз в $2^{(M-8)}/N$ тактов.
|
||||
|
||||
\section{Индивидуальное задание}
|
||||
|
||||
\section{Выводы}
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{4}
|
||||
\section{Приложения}
|
||||
\subsection{Исходные коды проекта}
|
||||
\label{appendix:src}
|
||||
|
||||
% \lstinputlisting[language=Verilog,style=VerilogStyle,caption={Семафор},label={lst:dec}]{src/dec.sv}
|
||||
|
||||
% \lstinputlisting[language=C,style=CCodeStyle,caption={\code{sem.c}},label={lst:sem}]{src/sem.c}
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
|
||||
\documentclass[a4paper,fontsize=14bp]{article}
|
||||
|
||||
\input{settings/common-preamble}
|
||||
\input{settings/fancy-listings-preamble}
|
||||
\input{settings/bmstu-preamble}
|
||||
\setcounter{secnumdepth}{4}
|
||||
\numerationTop
|
||||
|
||||
\begin{document}
|
||||
\thispagestyle{empty}
|
||||
\makeBMSTUHeader
|
||||
|
||||
\makeReportTitle{лабораторной}{4}{Проектирование цифрового синтезатора}{Проектирование цифровых устройств на \\ программируемых логических интегральных схемах (ПЛИС)}{}{С.В. Фёдоров}
|
||||
|
||||
\newpage
|
||||
\pagestyle{fancy}
|
||||
\section{Цель}
|
||||
Осуществить полный цикл проектирования цифрового устройства на ПЛИС на языке SystemVerilog. Реализовать генератор периодических функций на основе метода прямого цифрового синтеза на микросхеме семейства Cyclone IV E.
|
||||
|
||||
\section{Задачи}
|
||||
Прямой цифровой синтез -- это метод генерации сигнала заданной формы путём вычисления значений сигнала в последовательных дискретных отсчётах времени и преобразовании их в аналоговый сигнал с помощью ЦАП. Структура системы приведена на рис \hrf{pic:synth-scheme}.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fontsize{14}{1}\selectfont
|
||||
\includesvg[scale=1.01]{pics/03-fpga-lab-04-01-synth.svg}
|
||||
\caption{Схема цифрового синтезатора}
|
||||
\label{pic:pic:synth-scheme}
|
||||
\end{figure}
|
||||
|
||||
Инкремент фазы поступает на вход накопителя фазы и определяет скорость изменения фазы формируемого сигнала. Накопитель фазы выдаёт номер текущего отсчёта в периоде на просмотровую таблицу, содержащую образ одного периода синуса. Значение с выхода просмотровой таблицы поступает на дельта-сигма модулятор, который работает как однобитный ЦАП. Модулятор формирует последовательность нулей и единиц на высокой частоте, соответствующую текущему уровню на входе модулятора, после чего двухуровневый выходной сигнал модулятора подается на выход ПЛИС и сглаживается простым RC фильтром НЧ. При изменении приращения фазы изменяется частота формируемого на выходе сигнала.
|
||||
|
||||
\section{Выполнение работы}
|
||||
\subsection{Самостоятельная подготовка}
|
||||
Вариант 9 для первой группы $x_n = 9 * 3 - 21 = 6$.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\resizebox{\textwidth}{!}{\input{pics/03-fpga-04-sigdel.pgf}}
|
||||
\caption{1}
|
||||
\label{pic:1}
|
||||
\end{figure}
|
||||
|
||||
\begin{enumerate}
|
||||
\item $x_n = 6, \varepsilon_n = 127$, уровень квантования 127;
|
||||
\item $u_{n + 1} = x_n - \varepsilon_n = 6 – 127 = -121$, при этом $\varepsilon_n = -128-(-121)=-7$, а уровень квантования -128;
|
||||
\item $u_{n + 2} = x_n - \varepsilon_n = 6 – (–7) = 13$, при этом $\varepsilon_n = 127 - 13 = 104$, а уровень квантования 127;
|
||||
\item $u_{n + 3} = x_n - \varepsilon_n = 6 – 104 = -98$, при этом $\varepsilon_n= -128-(-98) = -30$, а уровень квантования -128;
|
||||
\item $u_{n + 4} = x_n - \varepsilon_n = 26 – (–30) = 106$, при этом ξn= 127-106 = 11, а уровень квантования 127 F: Un+1=XN-ξn=26 – 11 = 15, при этом ξn= 127-15 = 112, а уровень квантования 127
|
||||
G: Un+1=XN-ξn=26 – 112 = -86, при этом ξn= -128-(-86) = -42, а уровень квантования -128 H: Un+1=XN-varepsilonn=26 – (–42) = 88, при этом ξn= 127-88 = 39, а уровень квантования 127
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Разработка модулей}
|
||||
\subsubsection{Накопитель фазы}
|
||||
\textbf{Интерфейс модуля}
|
||||
\begin{frm} \begin{itemize}
|
||||
\item [] \textbf{Входы:}
|
||||
\code{phinc[7:0]} -- величина приращения фазы за один период тактового сигнала;
|
||||
\code{clk} -- тактовый сигнал;
|
||||
\code{clr_n} -- вход асинхронного сброса;
|
||||
\item [] \textbf{Выходы:}
|
||||
\code{phase[7:0]} -- 8 старших значащих битов выхода накопителя;
|
||||
\item [] \textbf{Параметры:}
|
||||
\code{WIDTH} -- разрядность накопителя фазы (значение по умолчанию -- 14).
|
||||
\end{itemize} \end{frm}
|
||||
|
||||
\textbf{Принцип действия}
|
||||
Накопитель фазы -- это классический аккумулятор, который сохраняет накопленную сумму в регистре и использует её в качестве одного из операндов сумматора на каждом такте. Второй операнд поступает с входа и определяет величину приращения фазы. Разрядность аккумулятора должна быть параметризирована. Входные значения складываются с младшими битами регистра аккумулятора, а на выход поступают старшие 8 разрядов аккумулятора, поэтому при разрядности аккумулятора M и значении N на входе приращения фазы выход фазы будет увеличиваться на единицу один раз в $2^{(M-8)}/N$ тактов.
|
||||
|
||||
\section{Индивидуальное задание}
|
||||
|
||||
\section{Выводы}
|
||||
|
||||
\newpage
|
||||
\appendix
|
||||
\setcounter{secnumdepth}{4}
|
||||
\section{Приложения}
|
||||
\subsection{Исходные коды проекта}
|
||||
\label{appendix:src}
|
||||
|
||||
% \lstinputlisting[language=Verilog,style=VerilogStyle,caption={Семафор},label={lst:dec}]{src/dec.sv}
|
||||
|
||||
% \lstinputlisting[language=C,style=CCodeStyle,caption={\code{sem.c}},label={lst:sem}]{src/sem.c}
|
||||
|
||||
\end{document}
|
||||
|
|
After Width: | Height: | Size: 180 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 776 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 297 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 127 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 357 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 434 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 267 KiB |
After Width: | Height: | Size: 205 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 203 KiB |
After Width: | Height: | Size: 284 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 687 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 687 KiB |
After Width: | Height: | Size: 130 KiB |
After Width: | Height: | Size: 687 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 686 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 688 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 688 KiB |
After Width: | Height: | Size: 98 KiB |
|
@ -0,0 +1,670 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="02-dip-04-lab-cnn-idea.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.2554688"
|
||||
inkscape:cx="242.20782"
|
||||
inkscape:cy="243.74369"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1387"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g1968" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient8241"
|
||||
inkscape:swatch="solid">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8239" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7589"
|
||||
inkscape:swatch="solid">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7587" />
|
||||
</linearGradient>
|
||||
<pattern
|
||||
inkscape:collect="always"
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="10"
|
||||
height="10"
|
||||
patternTransform="translate(0,0) scale(10,10)"
|
||||
id="Polkadots-small"
|
||||
inkscape:stockid="Polka dots, small">
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="2.567"
|
||||
cy="0.810"
|
||||
r="0.05"
|
||||
id="circle3670" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="3.048"
|
||||
cy="2.33"
|
||||
r="0.05"
|
||||
id="circle3672" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.418"
|
||||
cy="2.415"
|
||||
r="0.05"
|
||||
id="circle3674" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.844"
|
||||
cy="3.029"
|
||||
r="0.05"
|
||||
id="circle3676" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="6.08"
|
||||
cy="1.363"
|
||||
r="0.05"
|
||||
id="circle3678" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="5.819"
|
||||
cy="4.413"
|
||||
r="0.05"
|
||||
id="circle3680" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.305"
|
||||
cy="4.048"
|
||||
r="0.05"
|
||||
id="circle3682" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="5.541"
|
||||
cy="3.045"
|
||||
r="0.05"
|
||||
id="circle3684" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.785"
|
||||
cy="5.527"
|
||||
r="0.05"
|
||||
id="circle3686" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="2.667"
|
||||
cy="5.184"
|
||||
r="0.05"
|
||||
id="circle3688" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.965"
|
||||
cy="1.448"
|
||||
r="0.05"
|
||||
id="circle3690" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.047"
|
||||
cy="5.049"
|
||||
r="0.05"
|
||||
id="circle3692" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.340"
|
||||
cy="0.895"
|
||||
r="0.05"
|
||||
id="circle3694" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.125"
|
||||
cy="0.340"
|
||||
r="0.05"
|
||||
id="circle3696" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="9.550"
|
||||
cy="1.049"
|
||||
r="0.05"
|
||||
id="circle3698" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.006"
|
||||
cy="2.689"
|
||||
r="0.05"
|
||||
id="circle3700" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="8.909"
|
||||
cy="2.689"
|
||||
r="0.05"
|
||||
id="circle3702" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="9.315"
|
||||
cy="4.407"
|
||||
r="0.05"
|
||||
id="circle3704" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.820"
|
||||
cy="3.870"
|
||||
r="0.05"
|
||||
id="circle3706" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="8.270"
|
||||
cy="5.948"
|
||||
r="0.05"
|
||||
id="circle3708" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="7.973"
|
||||
cy="7.428"
|
||||
r="0.05"
|
||||
id="circle3710" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="9.342"
|
||||
cy="8.072"
|
||||
r="0.05"
|
||||
id="circle3712" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="8.206"
|
||||
cy="9.315"
|
||||
r="0.05"
|
||||
id="circle3714" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="9.682"
|
||||
cy="9.475"
|
||||
r="0.05"
|
||||
id="circle3716" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="9.688"
|
||||
cy="6.186"
|
||||
r="0.05"
|
||||
id="circle3718" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="3.379"
|
||||
cy="6.296"
|
||||
r="0.05"
|
||||
id="circle3720" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="2.871"
|
||||
cy="8.204"
|
||||
r="0.05"
|
||||
id="circle3722" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.59"
|
||||
cy="8.719"
|
||||
r="0.05"
|
||||
id="circle3724" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="3.181"
|
||||
cy="9.671"
|
||||
r="0.05"
|
||||
id="circle3726" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="5.734"
|
||||
cy="7.315"
|
||||
r="0.05"
|
||||
id="circle3728" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="6.707"
|
||||
cy="6.513"
|
||||
r="0.05"
|
||||
id="circle3730" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="5.730"
|
||||
cy="9.670"
|
||||
r="0.05"
|
||||
id="circle3732" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="6.535"
|
||||
cy="8.373"
|
||||
r="0.05"
|
||||
id="circle3734" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="4.37"
|
||||
cy="7.154"
|
||||
r="0.05"
|
||||
id="circle3736" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="0.622"
|
||||
cy="7.25"
|
||||
r="0.05"
|
||||
id="circle3738" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="0.831"
|
||||
cy="5.679"
|
||||
r="0.05"
|
||||
id="circle3740" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.257"
|
||||
cy="8.519"
|
||||
r="0.05"
|
||||
id="circle3742" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.989"
|
||||
cy="6.877"
|
||||
r="0.05"
|
||||
id="circle3744" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="0.374"
|
||||
cy="3.181"
|
||||
r="0.05"
|
||||
id="circle3746" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.166"
|
||||
cy="1.664"
|
||||
r="0.05"
|
||||
id="circle3748" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.151"
|
||||
cy="0.093"
|
||||
r="0.05"
|
||||
id="circle3750" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.151"
|
||||
cy="10.093"
|
||||
r="0.05"
|
||||
id="circle3752" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="1.302"
|
||||
cy="4.451"
|
||||
r="0.05"
|
||||
id="circle3754" />
|
||||
<circle
|
||||
style="fill:black;stroke:none"
|
||||
cx="3.047"
|
||||
cy="3.763"
|
||||
r="0.05"
|
||||
id="circle3756" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Слой 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g1839">
|
||||
<g
|
||||
id="g1968"
|
||||
inkscape:transform-center-x="3.6166706"
|
||||
transform="matrix(1,0.21019453,0,1,0,-24.662869)"
|
||||
inkscape:transform-center-y="-0.76020432">
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="104.59366"
|
||||
y="55.716232" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-9"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="108.24294"
|
||||
y="55.716232" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-5"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="111.89223"
|
||||
y="55.716232" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-4"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="115.54151"
|
||||
y="55.716232" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-45"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="119.1908"
|
||||
y="55.716232" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-8"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="104.59366"
|
||||
y="59.365517" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-9-6"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="108.24295"
|
||||
y="59.365517" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-5-3"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="111.89223"
|
||||
y="59.365517" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-4-8"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="115.5415"
|
||||
y="59.365517" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-45-9"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="119.1908"
|
||||
y="59.365517" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-48"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="104.59365"
|
||||
y="63.014801" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-9-2"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="108.24294"
|
||||
y="63.014801" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-5-0"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="111.89222"
|
||||
y="63.014801" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-4-7"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="115.5415"
|
||||
y="63.014801" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-45-0"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="119.1908"
|
||||
y="63.014801" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-6"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="104.59365"
|
||||
y="66.664085" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-9-8"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="108.24294"
|
||||
y="66.664085" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-5-6"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="111.89222"
|
||||
y="66.664085" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-4-80"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="115.54151"
|
||||
y="66.664085" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-45-7"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="119.1908"
|
||||
y="66.664085" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-97"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="104.59365"
|
||||
y="70.31337" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-9-0"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="108.24294"
|
||||
y="70.31337" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-5-8"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="111.89222"
|
||||
y="70.31337" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-4-84"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="115.5415"
|
||||
y="70.31337" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
|
||||
id="rect1542-45-2"
|
||||
width="3.6492841"
|
||||
height="3.6492841"
|
||||
x="119.1908"
|
||||
y="70.31337" />
|
||||
<rect
|
||||
style="fill:url(#Polkadots-small);fill-opacity:1.0;stroke:#000000;stroke-width:0.202173;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:0.202173, 0.202173;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="rect1542-54"
|
||||
width="3.7290287"
|
||||
height="3.6492841"
|
||||
x="85.644524"
|
||||
y="94.196358"
|
||||
transform="matrix(0.97861519,-0.20569956,0,1,0,0)" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.202173;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:0.202173, 0.202173;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="rect1542-9-1"
|
||||
width="3.7290287"
|
||||
height="3.6492841"
|
||||
x="89.37355"
|
||||
y="94.196358"
|
||||
transform="matrix(0.97861519,-0.20569956,0,1,0,0)" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.202173;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:0.202173, 0.202173;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="rect1542-5-35"
|
||||
width="3.7290287"
|
||||
height="3.6492841"
|
||||
x="93.102585"
|
||||
y="94.196358"
|
||||
transform="matrix(0.97861519,-0.20569956,0,1,0,0)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.065;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.065, 0.26;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 83.813032,76.579317 104.59366,55.716231"
|
||||
id="path2192"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.065;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.065, 0.26;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 94.760886,77.927422 122.84009,66.664085"
|
||||
id="path2194"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 84.280615,77.005297 2.560116,2.021994"
|
||||
id="path10953" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 90.731699,75.496928 -2.758221,3.33798"
|
||||
id="path10955" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 92.997196,74.980095 v 2.86489"
|
||||
id="path11152" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 105.18822,56.345774 2.38741,2.393547"
|
||||
id="path11267" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 105.23394,59.988394 2.38741,2.393547"
|
||||
id="path11267-3" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 105.20346,63.692745 2.38741,2.393547"
|
||||
id="path11267-4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 108.92172,63.73408 2.38741,2.393547"
|
||||
id="path11267-0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 108.94204,60.062343 2.38741,2.393547"
|
||||
id="path11267-2" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 108.93188,56.356375 2.38741,2.393547"
|
||||
id="path11267-33" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.65014,56.357074 2.38741,2.393547"
|
||||
id="path11267-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.52823,60.090802 2.38741,2.393547"
|
||||
id="path11267-21" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.46728,63.7914 2.38741,2.393547"
|
||||
id="path11267-49" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 111.44628,63.503127 -2.7633,2.693941"
|
||||
id="path11517" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 111.47676,59.869892 -2.7633,2.693941"
|
||||
id="path11517-6" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 111.48692,56.149494 -2.7633,2.693941"
|
||||
id="path11517-7" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 115.21534,56.158217 -2.7633,2.693941"
|
||||
id="path11517-3" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 115.08327,59.944876 -2.7633,2.693941"
|
||||
id="path11517-8" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 115.07311,63.675433 -2.7633,2.693941"
|
||||
id="path11517-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 118.75074,63.562763 -2.7633,2.693941"
|
||||
id="path11517-30" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 118.74058,59.826318 -2.7633,2.693941"
|
||||
id="path11517-53" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 118.60851,56.20693 -2.7633,2.693941"
|
||||
id="path11517-1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 113.83369,56.154015 v 2.651548"
|
||||
id="path11691" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 113.7321,59.959666 v 2.651548"
|
||||
id="path11691-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 113.74226,63.777385 v 2.651548"
|
||||
id="path11691-53" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 117.43004,63.611784 v 2.651548"
|
||||
id="path11691-56" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 117.33861,59.872104 v 2.651548"
|
||||
id="path11691-4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 117.2675,56.168789 v 2.651548"
|
||||
id="path11691-6" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 121.00608,56.175376 v 2.651548"
|
||||
id="path11691-8" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 120.96544,59.963136 v 2.651548"
|
||||
id="path11691-68" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 120.93496,63.545576 v 2.651548"
|
||||
id="path11691-43" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 64 KiB |
|
@ -0,0 +1,233 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="02-dip-04-lab-dropout.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="6.5109376"
|
||||
inkscape:cx="356.40028"
|
||||
inkscape:cy="222.4718"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1387"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible;"
|
||||
id="Arrow2Send"
|
||||
refX="0.0"
|
||||
refY="0.0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(0.3) rotate(180) translate(-2.3,0)"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
style="stroke:context-stroke;fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
id="path1327" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Слой 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846"
|
||||
cx="60.055145"
|
||||
cy="50.055534"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-4"
|
||||
cx="60.055145"
|
||||
cy="60.170086"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill;marker-end:"
|
||||
id="path846-0"
|
||||
cx="70.054764"
|
||||
cy="50.113003"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill;marker-end:"
|
||||
id="path846-3"
|
||||
cx="70.054764"
|
||||
cy="60.055145"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-2"
|
||||
cx="80.054375"
|
||||
cy="49.998066"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-23"
|
||||
cx="80.054375"
|
||||
cy="60.112617"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-1"
|
||||
cx="69.997292"
|
||||
cy="39.998451"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-5"
|
||||
cx="70.054764"
|
||||
cy="70.054764"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-24"
|
||||
cx="105.05341"
|
||||
cy="50.141735"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-4-5"
|
||||
cx="105.05341"
|
||||
cy="60.256287"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-0-5"
|
||||
cx="115.05302"
|
||||
cy="50.199203"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-3-1"
|
||||
cx="115.05302"
|
||||
cy="60.141346"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-2-4"
|
||||
cx="125.05264"
|
||||
cy="50.084267"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-23-3"
|
||||
cx="125.05264"
|
||||
cy="60.198818"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-1-0"
|
||||
cx="114.99555"
|
||||
cy="40.084652"
|
||||
r="2.4711688" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke markers fill"
|
||||
id="path846-5-7"
|
||||
cx="115.05302"
|
||||
cy="70.140968"
|
||||
r="2.4711688" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 67.468651,39.826043 -4.884867,10.200757 4.856135,0.02873"
|
||||
id="path1192" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="M 67.526121,59.968944 62.583784,50.0268 67.554857,70.169698"
|
||||
id="path1194" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="M 67.468651,39.826043 62.526314,60.112616 67.439919,50.05553"
|
||||
id="path1196" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 67.526121,59.968944 -4.999807,0.143672 5.028543,10.057082"
|
||||
id="path1198" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 72.497192,39.883513 5.028542,10.17202"
|
||||
id="path1200" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 72.439725,50.170471 5.086009,-0.114938"
|
||||
id="path1202" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 72.439725,50.170471 5.086009,9.884674"
|
||||
id="path1204" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 72.497192,39.883513 5.028542,20.171632"
|
||||
id="path1206" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="m 77.525734,50.055533 -5.028542,9.913411 5.028542,0.0862"
|
||||
id="path1208" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="M 72.525929,70.227165 77.525734,60.055143"
|
||||
id="path1210" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:"
|
||||
d="M 72.525929,70.227165 77.525734,50.055533"
|
||||
id="path1212" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.48252,50.22702 h -4.95769 l 4.95769,20.155828"
|
||||
id="path1607" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 122.47916,50.145746 h -4.95768 l 5.03895,10.240462"
|
||||
id="path1609" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 122.47916,50.145746 -4.87641,19.952644 4.95768,-9.712182"
|
||||
id="path1611" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.31997,37.182623 5.54692,5.546918"
|
||||
id="path1613" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 117.92784,37.020076 -5.87201,5.872012"
|
||||
id="path1615" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 112.40124,57.297814 5.24214,5.242139"
|
||||
id="path1617" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 117.68402,57.257177 -5.22182,5.221822"
|
||||
id="path1619" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 107.76866,57.460361 -5.5266,5.526598"
|
||||
id="path1623" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 102.20142,57.379089 5.5266,5.526595"
|
||||
id="path1625" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 494 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 128 KiB |