BMSTU/02-dip-lab-01-report.tex

495 lines
68 KiB
TeX
Raw Normal View History

2023-01-27 22:32:16 +03:00
\documentclass[a4paper,fontsize=14bp]{article}
\input{../common-preamble}
\input{../bmstu-preamble}
\input{../fancy-listings-preamble}
\numerationTop
\begin{document}
\thispagestyle{empty}
\makeBMSTUHeader
% ... работе, номер, тема, предмет, ?а, кто
\makeReportTitle{лабораторной}{1}{Распознавание объекта по форме}{Цифровая обработка изображений}{}{Большаков В.Э.}
\newpage
\thispagestyle{empty}
\tableofcontents
\newpage
\pagestyle{fancy}
\section{Цель}
Основной целью лабораторной работы является изучение методов распознания объекта по форме с помощью библиотеки цифровой обработки изображений scikit-image языка Python.
\section{Задание}
Требуется запрограммировать работу программы распознавания фрукта в зависимости от формы объекта из обучающей выборки. В таблице \hrf{table:indi-task} представлено индивидуальное задание на лабораторную работу.
\begin{table}[ht]
\centering
\begin{tabular}{|l|c|c|c|}
\hline
№ варианта & Фрукт1 & Фрукт2 & Оператор \\ [0.5ex]
\hline
11 & Corn & Quince & Кэнни \\ [1ex]
\hline
\end{tabular}
\caption{Индивидуальное задание на разработку}
\label{table:indi-task}
\end{table}
\section{Выполнение}
В качестве исходного материала были получены обучающая и тестовая выборки изображений двух овощей/фруктов в соответствии с вариантом. Примеры изображений приведены на рис. \hrf{pic:train-samples}.
\begin{figure}[ht]
\centering
\begin{subfigure}[b]{0.45\textwidth}
\centering
\includegraphics[width=0.8\textwidth]{c_100.jpg}
\caption{Corn}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.45\textwidth}
\centering
\includegraphics[width=0.8\textwidth]{q_100.jpg}
\caption{Quince}
\end{subfigure}
\caption{Изображения для тренировки алгоритма}
\label{pic:train-samples}
\end{figure}
Для работы были использованы следующие инструменты:
\begin{itemize}
\item JetBrains PyCharm CE;
\item Python 3.9;
\item scikit-image 0.19.2.
\end{itemize}
\subsection{Теоретическая часть}
Выделение границ — термин в теории обработки изображения и компьютерного зрения, частично из области поиска объектов и выделения объектов, основывается на алгоритмах, которые выделяют точки цифрового изображения, в которых резко изменяется яркость или есть другие виды неоднородностей. Основным принципом большинства методов выделения контура является вычисление частных производных от функции яркости по координатам \cite{dip:enhancing-bitmaps}. Пример выделения границ представлен на рис \hrf{pic:canny-sample}.
\begin{figure}[ht]
\centering
\includegraphics[height=4cm]{01-canny-01.png}
\caption{Пример работы фильтра Кэнни (Canny)}
\label{pic:canny-sample}
\end{figure}
Фильтр (алгоритм) Кэнни представляет собой многоступенчатый детектор границ. Он использует фильтр, основанный на производной Гаусса, чтобы вычислить интенсивность градиентов. Гауссиан уменьшает влияние шума, присутствующего в изображении. Затем потенциальные края прореживаются до однопиксельных кривых путем удаления немаксимальных пикселей величины градиента\footnote{non-maximum pixels of the gradient magnitude}. Наконец, краевые пиксели сохраняются или удаляются с использованием порогового значения гистерезиса\footnote{Для гистерезиса характерно явление «насыщения», а также неодинаковость траекторий между крайними состояниями} для величины градиента.
Фильтр Кэнни имеет три регулируемых параметра: ширину гауссовой кривой (чем шумнее изображение, тем больше ширина), а также нижний и верхний пороги для гистерезисной пороговой обработки.
Для получения итоговых измерений каждой из фигур возможно получить тензор однородного тела единичной массы, имеющего форму каждой из них и получить тензоры, описывающие основные оси (X и Y) представленного на изображении тела относительно его центра массы.
Тензор инерции - это матричная величина, описывающая меру инертности тела, при вращательном движении, подобно тому, как масса тела является мерой его инертности при поступательном движении. Вычислим тензор однородного тела единичной массы, чтобы найти только его габариты. Изображение является плоским, поэтому у тензора будет две основные оси, а не три. Возможно представить тензор объекта в виде матрицы
\[ \widehat{J}\bar{w} =
\begin{pmatrix}
J_{xx} & J_{xy} \\
J_{yx} & J_{yy} \\
\end{pmatrix}
\begin{pmatrix}
W_{x} \\
W_{y} \\
\end{pmatrix}.
\]
Приведя данную матрицу к диагональному виду получим
\[
\begin{pmatrix}
J_{x} & 0 \\
0 & J_{y} \\
\end{pmatrix},
\]
где $J_{x}$ и $J_{y}$ - это моменты инерции главных осей фигур на изображениях. То есть такие измерения, которые можно будет сравнить и понять, к какому классу относится та или иная фигура (кукуруза или груша). Компоненты тензора инерции вычисляются по формуле
\begin{equation*}
J_{xx} = \sum_m y^2 \Delta m = \sum_n y^2\frac{1}{n}.
\end{equation*}
Аналогично, $J_{yy} = \sum_n x^2\frac{1}{n}$, а $J_{xy} = J_{yx} = -\sum_n xy\frac{1}{n}$.
\subsection{Разработка программы}
Библиотека skimage предоставляет лаконичный интерфейс загрузки изображений (строка \hrf{line:img-read}) в программу, поэтому пример, представленный на официальной странице библиотеки, повторён почти полностью и представлен в приложении \hrf{appendix:file-loading}. Также в приложении запрограммирован перевод цифрового изображения в полутоновой формат, с использованием стандартной функции, на строке \hrf{line:img-to-greyscale}.
Для написания программы тренировки и проверки наборов изображений были написаны общие функции преобразования изображений (листинг \hrf{code:tensor}), загрузки каждого файла с изображением из папки (листинг \hrf{code:folder}) и частные функции запуска тренировки и тестирования.
\begin{lstlisting}[language=Python,style=PyCodeStyle, caption={Функции получения тензора и нахождения собственных значений}, label={code:tensor}]
def solve_matrix(A):
L = []
D = (A[0][0] + A[1][1]) * (A[0][0] + A[1][1]) - 4 * (A[0][0] * A[1][1] - A[1][0] * A[0][1])
L.append(((A[0][0] + A[1][1]) + sqrt(D)) / 2)
L.append(((A[0][0] + A[1][1]) - sqrt(D)) / 2)
return L
def tensor(image): # вычисление тензора инерции по формулам
sum_x = None
sum_y = None
n = 0
# находим среднюю точку в каждой строке изображения
for y, itemy in enumerate(image): # находим строки
for x, itemx in enumerate(itemy): # берём столбцы
sum_x = 0
sum_y = 0
if itemx == 1: # если пиксель белый
sum_x += x
sum_y += y
n += 1
x_c = sum_x / n # вычисляем среднее арифметическое
y_c = sum_y / n
Jxx = 0
Jyy = 0
Jxy = 0
# также попиксельно рассматриваем изображение
for y, itemy in enumerate(image):
for x, itemx in enumerate(itemy):
if itemx == 1: # если пиксель белый
Jxx += ((y - y_c) * (y - y_c))/n # находим тензор по формуле
Jyy += ((x - x_c) * (x - x_c))/n
Jxy -= ((x - x_c) * (y - y_c))/n
return [[Jxx, Jxy], [Jxy, Jyy]]
\end{lstlisting}
\begin{lstlisting}[language=Python,style=PyCodeStyle, caption={Работа с изображениями в папке}, label={code:folder}]
def get_list_image(path):
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) # Получаем путь до изображения
picture = io.imread(path) # Загружаем изображение в формате narray
picture_gray = rgb2gray(picture) # Переводим изображений в полутон
picture_canny = feature.canny(picture_gray, sigma=3, mode='constant', cval=1)
picture_chull = convex_hull_image(picture_canny) # заливка контуров изображения
picture_chull = picture_chull.astype(np.uint8)
list_image.append((picture_chull, f)) # Добавляем полученное изображение в список
return list_image
\end{lstlisting}
Внутри функции загрузки изображения также сразу применяются функции получения границ фильтром Кэнни и заливки полученного изображения. В соответствии с вариантом (№11) был запрограммирован оператор фильтрации Кэнни со значением $\sigma = 3$, где сигма - это порог чувствительности распознавания границ. После работы оператора выделения границ фигура была залита и вычислен тензор инерции получившегося тела. Тренировка (листинг \hrf{code:training}) производилась на наборе изображений и результаты тренировки программы были записаны в словарь, содержащий значения минимума и максимума разности между главными осями тензоров инерции.
\begin{lstlisting}[language=Python,style=PyCodeStyle, caption={Код тренировки программы}, label={code:training}]
def training(training_path, fruit):
fruit_path = os.path.join(training_path, fruit)
some_prop_arr = []
list_image = get_list_image(fruit_path)
for image in list_image:
own_numbers = solve_matrix(tensor(image[0]))
some_prop_arr.append(abs(own_numbers[0] - own_numbers[1]))
return [min(some_prop_arr), max(some_prop_arr)]
\end{lstlisting}
В результате обучения были получены данные, представленные на рис. \hrf{fig:train-results}.
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=530, ymin=0, ymax=690,
width=140mm,height=110mm,
xlabel=Изображение,
ylabel=Разность моментов инерции главных осей тела,]
\addplot [blue] coordinates {
(0, 627.4607824733928) (1, 629.2695974371966) (2, 629.9554209593027) (3, 630.268029411357) (4, 630.6295207372107) (5, 625.8339628526348) (6, 625.8964369035497) (7, 626.5979015434887) (8, 625.2306613383677) (9, 626.3775276856277) (10, 625.5107854804395) (11, 626.0106043125209) (12, 626.2790447001885) (13, 624.6416933628533) (14, 624.7076264930304) (15, 628.9294293909321) (16, 632.31798020164) (17, 628.1644353897714) (18, 629.8765461117398) (19, 626.2943583644901) (20, 628.0866902299505) (21, 629.8275781255102) (22, 628.3092960981805) (23, 630.1023612272243) (24, 628.5292523585598) (25, 626.5508191041822) (26, 622.8590799056508) (27, 629.9440538380633) (28, 632.3036707519555) (29, 624.3833706404721) (30, 627.4726707741063) (31, 629.6878364997913) (32, 630.5185348477605) (33, 630.5124812282145) (34, 636.2054380967727) (35, 634.7046427336187) (36, 633.8497417207475) (37, 636.5278834340088) (38, 633.5647680943287) (39, 635.8154523751514) (40, 636.3225349655222) (41, 626.3773602069499) (42, 640.4644159348825) (43, 640.2429954451036) (44, 642.2688682295008) (45, 636.2357221747043) (46, 634.3971664974526) (47, 641.9238940534283) (48, 641.3886134400684) (49, 643.0213260492852) (50, 641.2751718926081) (51, 639.0920937675796) (52, 624.8137537147923) (53, 632.4407802739498) (54, 634.2504737332504) (55, 635.123316950992) (56, 632.5400024530343) (57, 631.024464097855) (58, 633.272977201304) (59, 635.8882466624875) (60, 630.6793826213832) (61, 624.9122374754847) (62, 634.3047639782453) (63, 631.941137136622) (64, 632.3867375860023) (65, 627.5326898417975) (66, 625.4646494959436) (67, 623.658538055161) (68, 625.0179763139789) (69, 624.590576865256) (70, 621.6883973855956) (71, 626.6429715100707) (72, 623.9650414779394) (73, 625.3945458330404) (74, 627.9641569696935) (75, 625.1165070677858) (76, 624.7243922218458) (77, 621.8411823174158) (78, 624.8167888979496) (79, 625.8303922721636) (80, 626.9775572684015) (81, 626.9667198752054) (82, 626.4799542502055) (83, 612.0555075531094) (84, 624.4035774020192) (85, 628.2825448647161) (86, 627.5007077260182) (87, 629.9434339330244) (88, 627.4373225862212) (89, 627.3721458119073) (90, 628.031602776535) (91, 622.6824154884432) (92, 627.0096845957587) (93, 626.5661917834273) (94, 624.7495703774318) (95, 623.0111874385307) (96, 622.2817386665105) (97, 626.1873004845656) (98, 621.6711068487709) (99, 624.4232253048453) (100, 621.7135775336171) (101, 623.0069773773184) (102, 634.5139645875552) (103, 622.4447909411745) (104, 620.7712794231238) (105, 616.5278675541269) (106, 619.3745091102379) (107, 618.5704355056066) (108, 622.0954703789457) (109, 616.0835351534836) (110, 631.7721435271798) (111, 620.7251419468425) (112, 619.42788225753) (113, 616.7683377335743) (114, 617.5203098468523) (115, 624.1094773315817) (116, 615.2902027826132) (117, 609.2277619472329) (118, 618.8286002133661) (119, 621.2064945034929) (120, 626.5853861369799) (121, 621.9851478186949) (122, 625.8678173982206) (123, 631.4421405634038) (124, 630.7048751744294) (125, 631.163498676287) (126, 634.2707686327126) (127, 634.7839280940477) (128, 636.411718598489) (129, 629.8499907076861) (130, 637.530004560821) (131, 635.2424498643154) (132, 635.9948941618518) (133, 635.166180070554) (134, 634.5650851594451) (135, 636.2836647928797) (136, 634.8374148898588) (137, 636.9667104276721) (138, 637.7991427851275) (139, 626.4054897146805) (140, 634.5752477931796) (141, 636.8651866208634) (142, 637.0527448158831) (143, 628.764830749955) (144, 635.9138563520996) (145, 635.008770779174) (146, 631.6951826947329) (147, 632.5796661507305) (148, 632.4555711376579) (149, 630.6666000338996) (150, 636.2885095939138) (151, 597.3948260380142) (152, 598.5143479462397) (153, 595.2680800798375) (154, 603.0608167306659) (155, 608.898241939918) (156, 612.5974351209122) (157, 613.8606035925711) (158, 611.8131953676086) (159, 604.8415705274656) (160, 617.2142476072188) (161, 641.9704936188414) (162, 618.5909062827875) (163, 626.1712220279785) (164, 627.399386735337) (165, 630.5624572919661) (166, 631.5745439169859) (167, 639.9364042057691) (168, 634.48595789571
};
\addplot [red] coordinates {
(0, 173.51242311267396) (1, 226.56468376945395) (2, 227.2128790606232) (3, 228.80979958275339) (4, 229.00661476467667) (5, 227.7773552530195) (6, 227.1400372238188) (7, 227.7280628790279) (8, 223.38898073349634) (9, 221.50976541647174) (10, 219.264282572698) (11, 217.6438689308548) (12, 212.43262157854406) (13, 209.06321520889782) (14, 203.06777034194198) (15, 203.06102278721391) (16, 199.9207834366171) (17, 198.58630343161053) (18, 196.68354258971243) (19, 195.4182799948153) (20, 189.27510661404494) (21, 187.22908617944375) (22, 185.19119949876904) (23, 183.92035332026586) (24, 183.42132197776613) (25, 183.48806596832918) (26, 180.61143390944244) (27, 177.58458247604062) (28, 175.9406922344877) (29, 174.54001651342872) (30, 171.99889125873892) (31, 170.60644472409058) (32, 169.05174623765078) (33, 168.57232084674234) (34, 168.96992205783295) (35, 167.570810757333) (36, 166.94265776448782) (37, 165.7726082271745) (38, 167.7328001560154) (39, 169.11527251133663) (40, 169.43277923657683) (41, 172.5509148371089) (42, 172.72150791802056) (43, 174.491136729493) (44, 175.7288507493529) (45, 177.5005171769717) (46, 178.45187359467695) (47, 179.80358263123276) (48, 179.76981579366452) (49, 180.52707676683917) (50, 180.35004115061412) (51, 179.85468675267794) (52, 179.14599346043087) (53, 179.2473979927782) (54, 181.0362629602473) (55, 180.72325111901546) (56, 181.25624714830474) (57, 178.69220676301507) (58, 179.31661022035428) (59, 182.9305532216797) (60, 183.16762399923965) (61, 181.92984593877253) (62, 184.30568549033842) (63, 181.58199597905536) (64, 182.50323477665705) (65, 186.490902542115) (66, 183.87109298489122) (67, 185.39111331070058) (68, 185.0394833185585) (69, 185.32262163112273) (70, 191.89228328673357) (71, 192.28682234935837) (72, 192.7635948338334) (73, 188.906153664788) (74, 189.68758016499714) (75, 193.32600166696312) (76, 191.75814655909556) (77, 168.8224626879811) (78, 193.43085019793517) (79, 193.4148643403953) (80, 188.78053845023123) (81, 186.41910456041018) (82, 185.71667531135836) (83, 184.18057353191267) (84, 181.53451689079907) (85, 181.1804028143206) (86, 181.4093489171994) (87, 179.9772603674271) (88, 181.10610587236306) (89, 180.83252149031176) (90, 180.5774610953183) (91, 179.3240984762383) (92, 181.04893497236577) (93, 179.8866102083585) (94, 184.67420233617054) (95, 184.25114524528476) (96, 185.15654325472195) (97, 181.3425673025256) (98, 181.30397824653) (99, 185.06774820786546) (100, 186.56305829495886) (101, 181.76567436124833) (102, 181.70587136221707) (103, 182.34958157699026) (104, 187.16223833604317) (105, 187.65818898138446) (106, 187.51769132613276) (107, 188.6309994241701) (108, 191.53486936415038) (109, 196.36822131498957) (110, 197.53616842969512) (111, 197.04912421890504) (112, 198.6181838772997) (113, 200.1446845708881) (114, 204.07152562906816) (115, 205.34928604590505) (116, 205.7700842909901) (117, 211.5522665173625) (118, 212.79692872591545) (119, 213.58136969802467) (120, 215.93233954765992) (121, 216.68927322340545) (122, 218.0631256899958) (123, 215.71905386835624) (124, 219.80168889572906) (125, 218.1396527048646) (126, 219.8947847989645) (127, 219.97287730928338) (128, 222.4371715941873) (129, 225.98003024871372) (130, 225.25253611192005) (131, 228.08159374052184) (132, 230.22535678466647) (133, 233.2388071258331) (134, 234.85040711621946) (135, 235.42534657605165) (136, 234.5844627230942) (137, 233.55302273146293) (138, 237.73451317838652) (139, 236.8956794358843) (140, 238.22978340672262) (141, 237.82942741115653) (142, 236.73053200217646) (143, 231.38345624955298) (144, 226.83189132907256) (145, 225.85711833727532) (146, 222.576656609363) (147, 224.46227260015849) (148, 220.7940680131219) (149, 220.2853720058726) (150, 212.96115990445008) (151, 210.74787827412808) (152, 208.32784239690045) (153, 203.4766905094806) (154, 197.60157593891785) (155, 195.84074470736437) (156, 194.81961077029064) (157, 190.59796851158694) (158, 187.22333820443083) (159, 186.67245218894072) (160, 186.04712473861196) (161, 183.54978523756904) (162, 178.1907457824583) (163, 178.22027896362
};
\end{axis}
\end{tikzpicture}
\caption{Данные тренировки}
\label{fig:train-results}
\end{figure}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=170, ymin=0, ymax=690,
width=140mm,height=110mm,
xlabel=Изображение,
ylabel=Разность моментов инерции главных осей тела,]
\addplot [blue, only marks] coordinates {
(0, 173.29764182010757) (1, 172.6389865077026) (2, 173.149352035025) (3, 170.03767210208844) (4, 174.94166790227098) (5, 178.9239885772716) (6, 178.30395376707702) (7, 178.7542860541896) (8, 179.91099808492322) (9, 180.59798146508496) (10, 180.5012626982387) (11, 184.87771903147103) (12, 179.07031756694306) (13, 181.53630773096444) (14, 184.41087015555996) (15, 182.9962549413138) (16, 183.9495773915944) (17, 183.63330975240683) (18, 186.1461796983633) (19, 180.651263928851) (20, 180.74957122449678) (21, 183.90010227329986) (22, 182.5549496487668) (23, 183.10330011133885) (24, 182.64618865766988) (25, 180.85013541771013) (26, 181.2670499174219) (27, 180.72609703165637) (28, 180.75293296190875) (29, 180.15323226079659) (30, 182.76669619393556) (31, 182.85348420399578) (32, 181.35249930838427) (33, 183.8049567748934) (34, 184.09189377612688) (35, 185.7283997349616) (36, 188.33369524814105) (37, 190.4952359597906) (38, 191.82551356428513) (39, 192.89921640555383) (40, 192.8210404698495) (41, 193.68686749053018) (42, 196.0864301316655) (43, 172.31125120179695) (44, 169.04931376644566) (45, 169.86514484518756) (46, 198.3700133498171) (47, 174.17877154682304) (48, 173.3844128259703) (49, 173.54590410832157) (50, 171.47524504342744) (51, 172.83319776922235) (52, 174.68315817974127) (53, 180.26177125596837) (54, 180.25433818207784) (55, 182.00770456617806) (56, 181.66843852471885) (57, 201.5413394316525) (58, 181.84970369175772) (59, 182.40091882524848) (60, 183.99821335577622) (61, 187.00110172159293) (62, 191.21229408486556) (63, 191.00878749191747) (64, 191.14138702139707) (65, 190.99291975623208) (66, 190.64309832943383) (67, 193.70519931080344) (68, 205.80956225992531) (69, 195.640486613529) (70, 198.7398962957193) (71, 203.61106667796116) (72, 204.24560080814257) (73, 205.01459978514265) (74, 204.9053758209588) (75, 206.65084637672874) (76, 218.4782631176463) (77, 170.7641597237909) (78, 169.23124635127192) (79, 169.08727584723107) (80, 174.8284346579918) (81, 173.80038908954003) (82, 172.9261443634212) (83, 176.6490344663075) (84, 183.4001998705088) (85, 185.20335067893757) (86, 197.1646169444748) (87, 199.08743325457067) (88, 202.21628921532556) (89, 210.6626116192133) (90, 211.8693191263049) (91, 214.34520467075805) (92, 220.9442932752288) (93, 225.22607026426766) (94, 226.10329757553927) (95, 225.47626463754432) (96, 224.10929074576484) (97, 228.35920265487516) (98, 226.4320784640609) (99, 224.05243699323995) (100, 222.3875457513655) (101, 216.8160288775743) (102, 210.9622953460107) (103, 203.03837539385785) (104, 209.64679821274837) (105, 202.94174593478562) (106, 198.6230459854212) (107, 193.3418402530417) (108, 197.6684571727463) (109, 191.03703787050745) (110, 196.27624651128707) (111, 186.0867507236499) (112, 157.86589946075264) (113, 171.73828545411084) (114, 163.92596896255668) (115, 170.71655891582395) (116, 170.5372251421989) (117, 175.92897305871202) (118, 178.58896093850467) (119, 185.69540338002588) (120, 186.23217573930492) (121, 186.44025429282635) (122, 186.66501327829252) (123, 186.6503995964335) (124, 173.8510594801719) (125, 190.07254019970878) (126, 189.06032060957455) (127, 193.1345087547479) (128, 191.56622264297044) (129, 191.8477911115283) (130, 194.0415200343075) (131, 196.01261668301726) (132, 191.68644168600417) (133, 176.50473671074428) (134, 180.53010852647208) (135, 184.05798546459073) (136, 186.53864341386662) (137, 186.2807485476228) (138, 188.75026329680804) (139, 188.01659159726773) (140, 187.24367349121098) (141, 191.58116671245733) (142, 192.01637825118542) (143, 189.73962873249565) (144, 193.57828256986772) (145, 192.9997668146757) (146, 195.9931824868134) (147, 191.066264073414) (148, 190.62920965433977) (149, 189.3061256052108) (150, 187.7076993203002) (151, 190.48967645851826) (152, 188.05225502574154) (153, 184.7015855333878) (154, 181.72580337621395) (155, 182.0073361769107) (156, 183.36080785274362) (157, 180.4239253409844) (158, 184.89952087917436) (159, 183.26371266127666) (160, 176.6950436565437) (161, 177.2941686542481) (162, 175.51560457518218) (163, 173.19055397920988
};
\addplot [red, only marks] coordinates {
(0, 632.8931699822933) (1, 629.7038316620205) (2, 625.5013602550243) (3, 637.9479118254721) (4, 635.784476882296) (5, 629.0900104139605) (6, 628.307820854963) (7, 626.0424996951442) (8, 631.6984517078465) (9, 630.6725267963852) (10, 630.6086224641941) (11, 624.1401063364196) (12, 623.686716719738) (13, 621.6113845119769) (14, 620.3068927688273) (15, 622.8482459106467) (16, 624.5830594422794) (17, 620.8978857895659) (18, 623.0057912390344) (19, 610.5611643344187) (20, 622.6607347837121) (21, 623.4048567112111) (22, 622.7979515091522) (23, 624.1046390149496) (24, 625.5979617243534) (25, 626.3452201961579) (26, 633.9202721111658) (27, 623.727719628704) (28, 623.7376087997175) (29, 620.8573777418496) (30, 620.8051690722007) (31, 620.934345370192) (32, 619.463807403215) (33, 620.0400587181165) (34, 621.7440979178523) (35, 619.3000997892827) (36, 618.7151210878569) (37, 615.415529253858) (38, 616.8641613947239) (39, 614.5406877169245) (40, 614.5212611665879) (41, 621.8106168796833) (42, 621.493603326729) (43, 620.0563202016983) (44, 620.6157091834348) (45, 625.0921743024971) (46, 630.6061184845965) (47, 634.5309767186541) (48, 636.1592791984662) (49, 619.5119695461385) (50, 432.7849376830029) (51, 414.85554093268877) (52, 402.5637803166401) (53, 395.6289079093242) (54, 367.0696582980438) (55, 367.96165478471363) (56, 353.9202625616549) (57, 315.44691280758894) (58, 243.29723235968913) (59, 216.1450637919022) (60, 211.2433337504151) (61, 214.77336051935356) (62, 192.89889085747876) (63, 227.57301738713363) (64, 255.60402289057862) (65, 293.7496240153587) (66, 373.1518621965313) (67, 402.5317275945274) (68, 421.3552941983651) (69, 447.33389207735854) (70, 460.64473696411574) (71, 477.90778403433114) (72, 492.9190960492312) (73, 329.42504606184184) (74, 276.37916603230826) (75, 257.0969230704086) (76, 237.9359923032116) (77, 217.63441613840206) (78, 189.57337744276134) (79, 144.82041846199866) (80, 124.06275663469887) (81, 94.86463055078798) (82, 57.0416111903769) (83, 43.68987693744498) (84, 38.589038001010294) (85, 30.962040401506783) (86, 24.46658420394192) (87, 26.721696591810087) (88, 48.540961521352074) (89, 88.4142216054247) (90, 125.40487924607874) (91, 197.28731453402224) (92, 229.8385257062983) (93, 256.97479000271545) (94, 284.3930572959491) (95, 307.16974825755193) (96, 325.05736443395375) (97, 352.03079765591633) (98, 369.1596572138391) (99, 387.60246662779787) (100, 357.380302995957) (101, 334.6630211198651) (102, 315.8144106212038) (103, 296.01304475342783) (104, 263.72056321834066) (105, 203.37843524117216) (106, 172.9659998363727) (107, 140.56728754758478) (108, 106.28972147131753) (109, 51.686933273975455) (110, 41.28449832694878) (111, 40.76620110041972) (112, 42.95481060875386) (113, 37.83427370347977) (114, 43.826271894231695) (115, 36.612635480213385) (116, 74.78745646327366) (117, 107.71892696334089) (118, 135.51135524360188) (119, 209.06019221722045) (120, 241.38331606375345) (121, 275.8713738407264) (122, 300.96102573203007) (123, 316.7352734702408) (124, 367.1689648282829) (125, 391.8209961394373) (126, 404.58824831771585) (127, 421.63351876129116) (128, 359.1309905971775) (129, 338.4575964215583) (130, 314.38356570027923) (131, 290.94087787016895) (132, 234.82476349332978) (133, 202.51480955923716) (134, 178.18015015344713) (135, 156.32753515825402) (136, 138.26972918427714) (137, 133.8558506359691) (138, 127.99689973687447) (139, 168.08725547216403) (140, 206.86455063620224) (141, 242.82078906480683) (142, 269.97425464635177) (143, 300.2739783372019) (144, 350.5724224528708) (145, 366.6897691365413) (146, 393.1298418583999) (147, 404.94304648961565) (148, 432.24598337735745) (149, 448.2804663651735)
};
\addplot [black] coordinates {
(0,346.02779819908665) (170,346.02779819908665)
};
\addplot [black] coordinates {
(0,647.416671344422) (170,647.416671344422)
};
% ошибки 2 рода
\addplot [green, only marks] coordinates{
(0, -1) (1, -1) (2, -1) (3, -1) (4, -1) (5, -1) (6, -1) (7, -1) (8, -1) (9, -1) (10, -1) (11, -1) (12, -1) (13, -1) (14, -1) (15, -1) (16, -1) (17, -1) (18, -1) (19, -1) (20, -1) (21, -1) (22, -1) (23, -1) (24, -1) (25, -1) (26, -1) (27, -1) (28, -1) (29, -1) (30, -1) (31, -1) (32, -1) (33, -1) (34, -1) (35, -1) (36, -1) (37, -1) (38, -1) (39, -1) (40, -1) (41, -1) (42, -1) (43, -1) (44, -1) (45, -1) (46, -1) (47, -1) (48, -1) (49, -1) (50, -1) (51, -1) (52, -1) (53, -1) (54, -1) (55, -1) (56, -1) (57, 315.44691280758894) (58, 243.29723235968913) (59, 216.1450637919022) (60, 211.2433337504151) (61, 214.77336051935356) (62, 192.89889085747876) (63, 227.57301738713363) (64, 255.60402289057862) (65, 293.7496240153587) (66, -1) (67, -1) (68, -1) (69, -1) (70, -1) (71, -1) (72, -1) (73, 329.42504606184184) (74, 276.37916603230826) (75, 257.0969230704086) (76, 237.9359923032116) (77, 217.63441613840206) (78, 189.57337744276134) (79, 144.82041846199866) (80, 124.06275663469887) (81, 94.86463055078798) (82, 57.0416111903769) (83, 43.68987693744498) (84, 38.589038001010294) (85, 30.962040401506783) (86, 24.46658420394192) (87, 26.721696591810087) (88, 48.540961521352074) (89, 88.4142216054247) (90, 125.40487924607874) (91, 197.28731453402224) (92, 229.8385257062983) (93, 256.97479000271545) (94, 284.3930572959491) (95, 307.16974825755193) (96, 325.05736443395375) (97, -1) (98, -1) (99, -1) (100, -1) (101, 334.6630211198651) (102, 315.8144106212038) (103, 296.01304475342783) (104, 263.72056321834066) (105, 203.37843524117216) (106, 172.9659998363727) (107, 140.56728754758478) (108, 106.28972147131753) (109, 51.686933273975455) (110, 41.28449832694878) (111, 40.76620110041972) (112, 42.95481060875386) (113, 37.83427370347977) (114, 43.826271894231695) (115, 36.612635480213385) (116, 74.78745646327366) (117, 107.71892696334089) (118, 135.51135524360188) (119, 209.06019221722045) (120, 241.38331606375345) (121, 275.8713738407264) (122, 300.96102573203007) (123, 316.7352734702408) (124, -1) (125, -1) (126, -1) (127, -1) (128, -1) (129, 338.4575964215583) (130, 314.38356570027923) (131, 290.94087787016895) (132, 234.82476349332978) (133, 202.51480955923716) (134, 178.18015015344713) (135, 156.32753515825402) (136, 138.26972918427714) (137, 133.8558506359691) (138, 127.99689973687447) (139, 168.08725547216403) (140, 206.86455063620224) (141, 242.82078906480683) (142, 269.97425464635177) (143, 300.2739783372019) (144, -1) (145, -1) (146, -1) (147, -1) (148, -1) (149, -1)
};
\end{axis}
\end{tikzpicture}
\caption{Данные тестирования для предельных значений кукурузы}
\label{fig:test-results-corn}
\end{figure}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=170, ymin=0, ymax=690,
width=140mm,height=110mm,
xlabel=Изображение,
ylabel=Разность моментов инерции главных осей тела,]
\addplot [blue, only marks] coordinates {
(0, 173.29764182010757) (1, 172.6389865077026) (2, 173.149352035025) (3, 170.03767210208844) (4, 174.94166790227098) (5, 178.9239885772716) (6, 178.30395376707702) (7, 178.7542860541896) (8, 179.91099808492322) (9, 180.59798146508496) (10, 180.5012626982387) (11, 184.87771903147103) (12, 179.07031756694306) (13, 181.53630773096444) (14, 184.41087015555996) (15, 182.9962549413138) (16, 183.9495773915944) (17, 183.63330975240683) (18, 186.1461796983633) (19, 180.651263928851) (20, 180.74957122449678) (21, 183.90010227329986) (22, 182.5549496487668) (23, 183.10330011133885) (24, 182.64618865766988) (25, 180.85013541771013) (26, 181.2670499174219) (27, 180.72609703165637) (28, 180.75293296190875) (29, 180.15323226079659) (30, 182.76669619393556) (31, 182.85348420399578) (32, 181.35249930838427) (33, 183.8049567748934) (34, 184.09189377612688) (35, 185.7283997349616) (36, 188.33369524814105) (37, 190.4952359597906) (38, 191.82551356428513) (39, 192.89921640555383) (40, 192.8210404698495) (41, 193.68686749053018) (42, 196.0864301316655) (43, 172.31125120179695) (44, 169.04931376644566) (45, 169.86514484518756) (46, 198.3700133498171) (47, 174.17877154682304) (48, 173.3844128259703) (49, 173.54590410832157) (50, 171.47524504342744) (51, 172.83319776922235) (52, 174.68315817974127) (53, 180.26177125596837) (54, 180.25433818207784) (55, 182.00770456617806) (56, 181.66843852471885) (57, 201.5413394316525) (58, 181.84970369175772) (59, 182.40091882524848) (60, 183.99821335577622) (61, 187.00110172159293) (62, 191.21229408486556) (63, 191.00878749191747) (64, 191.14138702139707) (65, 190.99291975623208) (66, 190.64309832943383) (67, 193.70519931080344) (68, 205.80956225992531) (69, 195.640486613529) (70, 198.7398962957193) (71, 203.61106667796116) (72, 204.24560080814257) (73, 205.01459978514265) (74, 204.9053758209588) (75, 206.65084637672874) (76, 218.4782631176463) (77, 170.7641597237909) (78, 169.23124635127192) (79, 169.08727584723107) (80, 174.8284346579918) (81, 173.80038908954003) (82, 172.9261443634212) (83, 176.6490344663075) (84, 183.4001998705088) (85, 185.20335067893757) (86, 197.1646169444748) (87, 199.08743325457067) (88, 202.21628921532556) (89, 210.6626116192133) (90, 211.8693191263049) (91, 214.34520467075805) (92, 220.9442932752288) (93, 225.22607026426766) (94, 226.10329757553927) (95, 225.47626463754432) (96, 224.10929074576484) (97, 228.35920265487516) (98, 226.4320784640609) (99, 224.05243699323995) (100, 222.3875457513655) (101, 216.8160288775743) (102, 210.9622953460107) (103, 203.03837539385785) (104, 209.64679821274837) (105, 202.94174593478562) (106, 198.6230459854212) (107, 193.3418402530417) (108, 197.6684571727463) (109, 191.03703787050745) (110, 196.27624651128707) (111, 186.0867507236499) (112, 157.86589946075264) (113, 171.73828545411084) (114, 163.92596896255668) (115, 170.71655891582395) (116, 170.5372251421989) (117, 175.92897305871202) (118, 178.58896093850467) (119, 185.69540338002588) (120, 186.23217573930492) (121, 186.44025429282635) (122, 186.66501327829252) (123, 186.6503995964335) (124, 173.8510594801719) (125, 190.07254019970878) (126, 189.06032060957455) (127, 193.1345087547479) (128, 191.56622264297044) (129, 191.8477911115283) (130, 194.0415200343075) (131, 196.01261668301726) (132, 191.68644168600417) (133, 176.50473671074428) (134, 180.53010852647208) (135, 184.05798546459073) (136, 186.53864341386662) (137, 186.2807485476228) (138, 188.75026329680804) (139, 188.01659159726773) (140, 187.24367349121098) (141, 191.58116671245733) (142, 192.01637825118542) (143, 189.73962873249565) (144, 193.57828256986772) (145, 192.9997668146757) (146, 195.9931824868134) (147, 191.066264073414) (148, 190.62920965433977) (149, 189.3061256052108) (150, 187.7076993203002) (151, 190.48967645851826) (152, 188.05225502574154) (153, 184.7015855333878) (154, 181.72580337621395) (155, 182.0073361769107) (156, 183.36080785274362) (157, 180.4239253409844) (158, 184.89952087917436) (159, 183.26371266127666) (160, 176.6950436565437) (161, 177.2941686542481) (162, 175.51560457518218) (163, 173.19055397920988
};
\addplot [red, only marks] coordinates {
(0, 632.8931699822933) (1, 629.7038316620205) (2, 625.5013602550243) (3, 637.9479118254721) (4, 635.784476882296) (5, 629.0900104139605) (6, 628.307820854963) (7, 626.0424996951442) (8, 631.6984517078465) (9, 630.6725267963852) (10, 630.6086224641941) (11, 624.1401063364196) (12, 623.686716719738) (13, 621.6113845119769) (14, 620.3068927688273) (15, 622.8482459106467) (16, 624.5830594422794) (17, 620.8978857895659) (18, 623.0057912390344) (19, 610.5611643344187) (20, 622.6607347837121) (21, 623.4048567112111) (22, 622.7979515091522) (23, 624.1046390149496) (24, 625.5979617243534) (25, 626.3452201961579) (26, 633.9202721111658) (27, 623.727719628704) (28, 623.7376087997175) (29, 620.8573777418496) (30, 620.8051690722007) (31, 620.934345370192) (32, 619.463807403215) (33, 620.0400587181165) (34, 621.7440979178523) (35, 619.3000997892827) (36, 618.7151210878569) (37, 615.415529253858) (38, 616.8641613947239) (39, 614.5406877169245) (40, 614.5212611665879) (41, 621.8106168796833) (42, 621.493603326729) (43, 620.0563202016983) (44, 620.6157091834348) (45, 625.0921743024971) (46, 630.6061184845965) (47, 634.5309767186541) (48, 636.1592791984662) (49, 619.5119695461385) (50, 432.7849376830029) (51, 414.85554093268877) (52, 402.5637803166401) (53, 395.6289079093242) (54, 367.0696582980438) (55, 367.96165478471363) (56, 353.9202625616549) (57, 315.44691280758894) (58, 243.29723235968913) (59, 216.1450637919022) (60, 211.2433337504151) (61, 214.77336051935356) (62, 192.89889085747876) (63, 227.57301738713363) (64, 255.60402289057862) (65, 293.7496240153587) (66, 373.1518621965313) (67, 402.5317275945274) (68, 421.3552941983651) (69, 447.33389207735854) (70, 460.64473696411574) (71, 477.90778403433114) (72, 492.9190960492312) (73, 329.42504606184184) (74, 276.37916603230826) (75, 257.0969230704086) (76, 237.9359923032116) (77, 217.63441613840206) (78, 189.57337744276134) (79, 144.82041846199866) (80, 124.06275663469887) (81, 94.86463055078798) (82, 57.0416111903769) (83, 43.68987693744498) (84, 38.589038001010294) (85, 30.962040401506783) (86, 24.46658420394192) (87, 26.721696591810087) (88, 48.540961521352074) (89, 88.4142216054247) (90, 125.40487924607874) (91, 197.28731453402224) (92, 229.8385257062983) (93, 256.97479000271545) (94, 284.3930572959491) (95, 307.16974825755193) (96, 325.05736443395375) (97, 352.03079765591633) (98, 369.1596572138391) (99, 387.60246662779787) (100, 357.380302995957) (101, 334.6630211198651) (102, 315.8144106212038) (103, 296.01304475342783) (104, 263.72056321834066) (105, 203.37843524117216) (106, 172.9659998363727) (107, 140.56728754758478) (108, 106.28972147131753) (109, 51.686933273975455) (110, 41.28449832694878) (111, 40.76620110041972) (112, 42.95481060875386) (113, 37.83427370347977) (114, 43.826271894231695) (115, 36.612635480213385) (116, 74.78745646327366) (117, 107.71892696334089) (118, 135.51135524360188) (119, 209.06019221722045) (120, 241.38331606375345) (121, 275.8713738407264) (122, 300.96102573203007) (123, 316.7352734702408) (124, 367.1689648282829) (125, 391.8209961394373) (126, 404.58824831771585) (127, 421.63351876129116) (128, 359.1309905971775) (129, 338.4575964215583) (130, 314.38356570027923) (131, 290.94087787016895) (132, 234.82476349332978) (133, 202.51480955923716) (134, 178.18015015344713) (135, 156.32753515825402) (136, 138.26972918427714) (137, 133.8558506359691) (138, 127.99689973687447) (139, 168.08725547216403) (140, 206.86455063620224) (141, 242.82078906480683) (142, 269.97425464635177) (143, 300.2739783372019) (144, 350.5724224528708) (145, 366.6897691365413) (146, 393.1298418583999) (147, 404.94304648961565) (148, 432.24598337735745) (149, 448.2804663651735)
};
\addplot [black] coordinates {
(0,238.22978340672262) (170,238.22978340672262)
};
\addplot [black] coordinates {
(0,2.788195025603045) (170,2.788195025603045)
};
% ошибки 1 рода
\addplot [green, only marks] coordinates{
(0, -1) (1, -1) (2, -1) (3, -1) (4, -1) (5, -1) (6, -1) (7, -1) (8, -1) (9, -1) (10, -1) (11, -1) (12, -1) (13, -1) (14, -1) (15, -1) (16, -1) (17, -1) (18, -1) (19, -1) (20, -1) (21, -1) (22, -1) (23, -1) (24, -1) (25, -1) (26, -1) (27, -1) (28, -1) (29, -1) (30, -1) (31, -1) (32, -1) (33, -1) (34, -1) (35, -1) (36, -1) (37, -1) (38, -1) (39, -1) (40, -1) (41, -1) (42, -1) (43, -1) (44, -1) (45, -1) (46, -1) (47, -1) (48, -1) (49, -1) (50, -1) (51, -1) (52, -1) (53, -1) (54, -1) (55, -1) (56, -1) (57, -1) (58, -1) (59, 216.1450637919022) (60, 211.2433337504151) (61, 214.77336051935356) (62, 192.89889085747876) (63, 227.57301738713363) (64, -1) (65, -1) (66, -1) (67, -1) (68, -1) (69, -1) (70, -1) (71, -1) (72, -1) (73, -1) (74, -1) (75, -1) (76, 237.9359923032116) (77, 217.63441613840206) (78, 189.57337744276134) (79, 144.82041846199866) (80, 124.06275663469887) (81, 94.86463055078798) (82, 57.0416111903769) (83, 43.68987693744498) (84, 38.589038001010294) (85, 30.962040401506783) (86, 24.46658420394192) (87, 26.721696591810087) (88, 48.540961521352074) (89, 88.4142216054247) (90, 125.40487924607874) (91, 197.28731453402224) (92, 229.8385257062983) (93, -1) (94, -1) (95, -1) (96, -1) (97, -1) (98, -1) (99, -1) (100, -1) (101, -1) (102, -1) (103, -1) (104, -1) (105, 203.37843524117216) (106, 172.9659998363727) (107, 140.56728754758478) (108, 106.28972147131753) (109, 51.686933273975455) (110, 41.28449832694878) (111, 40.76620110041972) (112, 42.95481060875386) (113, 37.83427370347977) (114, 43.826271894231695) (115, 36.612635480213385) (116, 74.78745646327366) (117, 107.71892696334089) (118, 135.51135524360188) (119, 209.06019221722045) (120, -1) (121, -1) (122, -1) (123, -1) (124, -1) (125, -1) (126, -1) (127, -1) (128, -1) (129, -1) (130, -1) (131, -1) (132, 234.82476349332978) (133, 202.51480955923716) (134, 178.18015015344713) (135, 156.32753515825402) (136, 138.26972918427714) (137, 133.8558506359691) (138, 127.99689973687447) (139, 168.08725547216403) (140, 206.86455063620224) (141, -1) (142, -1) (143, -1) (144, -1) (145, -1) (146, -1) (147, -1) (148, -1) (149, -1)
};
\end{axis}
\end{tikzpicture}
\caption{Данные тестирования для предельных значений груши}
\label{fig:test-results-quince}
\end{figure}
Далее был организован и проведён эксперимент на тестовой выборке.
\begin{lstlisting}[language=Python,style=PyCodeStyle, caption={Код эксперимента на тестовой выборке}, label={code:testing}]
def testing(fruit_path, limits, inverse=False):
list_image = get_list_image(fruit_path)
true_array = []
for image in list_image:
own_numbers = solve_matrix(tensor(image[0]))
delta = (abs(own_numbers[0] - own_numbers[1]))
if (limits[0] < delta < limits[1]) ^ inverse:
true_array.append(image[1])
return true_array
\end{lstlisting}
и вычислены ошибки первого и второго рода. Ошибки первого рода - это когда программа приняла кукурузу за грушу. Ошибка второго рода - это когда программа не приняла кукурузу за кукурузу. В результате обработки тестовой выборки было выявлено:
\begin{table}[H]
\centering
\begin{tabular}{|c|c|c|}
\hline
& Первого рода (шт.) & Второго рода (шт.)\\
\hline
Corn & 0 & 71 \\
\hline
Quince & 25 & 0 \\
\hline
\end{tabular}
\caption{Ошибки при обработке тестовой выборки}
\label{tab:testing-errors}
\end{table}
Диаграмма работы программы имеет следующий вид:
\begin{center}
\begin{sequencediagram}
\newthread{m}{:Main}
\newinst[1]{tr}{:Training}
\newinst[1]{ts}{:Testing}
\newinst[1]{ip}{:Image processing}
\newinst[1]{sd}{:Stat dictionary}
\begin{sdblock}{Training}{gathering stats}
\begin{call}{m}{invoke}{tr}{}
\begin{call}{tr}{invoke with train path}{ip}{tensor delta}
\begin{call}{ip}{tensor}{ip}{} \end{call}
\begin{call}{ip}{solve}{ip}{} \end{call}
\end{call}
\begin{call}{tr}{write deltas}{sd}{} \end{call}
\end{call}
\end{sdblock}
\begin{sdblock}{Testing}{checking pics}
\begin{call}{m}{invoke}{ts}{}
\begin{call}{ts}{invoke test path}{ip}{tensor delta}
\begin{call}{ip}{tensor}{ip}{} \end{call}
\begin{call}{ip}{solve}{ip}{} \end{call}
\end{call}
\begin{call}{ts}{}{sd}{read deltas} \end{call}
\begin{call}{ts}{check deltas}{ts}{} \end{call}
\begin{call}{ts}{write errors}{sd}{} \end{call}
\end{call}
\end{sdblock}
\end{sequencediagram}
\end{center}
Выполнение алгоритма преобразования было разделено на несколько шагов, показанных на рис. \hrf{pic:cstages} и \hrf{pic:qstages}. Каждое изображение было преобразовано в градации серого, далее был применён фильтр Кэнни и произведена заливка контура.
\begin{figure}
\centering
\includegraphics{01-picture.png}
\includegraphics{01-picture_gray.png}
\includegraphics{01-picture_canny.png}
\includegraphics{01-picture_chull.png}
\caption{Изменения изображения кукурузы}
\label{pic:cstages}
\end{figure}
\begin{figure}
\centering
\includegraphics{02-picture.png}
\includegraphics{02-picture_gray.png}
\includegraphics{02-picture_canny.png}
\includegraphics{02-picture_chull.png}
\caption{Изменения изображения груши}
\label{pic:qstages}
\end{figure}
На рис. \hrf{fig:test-results-quince} и \hrf{fig:test-results-corn} зелёным отмечены изображения, которые продемонстрировали ошибки первого и второго рода, соответственно.
\section{Заключение и выводы}
С использованием фильтра, определяющего границы и некоторых дополнительных расчётов с большой долей точности возможно определить, какое именно изображение было передано программе. Очевидно, что категоризировать изображение только по его форме почти невозможно, несмотря на то, что был выбран достаточно гибкий способ определения формы через вычисление тензора инерции, и это возможно доказать подобрав изображения близких по форме предметов.
\nocite{dip:gonzales-dip}
\nocite{dip:math-an}
\nocite{dip:recognition-dip}
\newpage
\printbibliography[heading=bibintoc, title={Список литературы}]
\newpage
\appendix
\section*{Приложения}
\addcontentsline{toc}{section}{Приложения}
\renewcommand{\thesubsection}{\Alph{subsection}}
\subsection{Исходный пример работы фильтра Кэнни.}
\label{appendix:file-loading}
\begin{lstlisting}[language=Python,style=PyCodeStyle]
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from skimage import feature
from skimage import io
from skimage.color import rgb2gray
image = io.imread(....) # loading image <@\label{line:img-read}@>
im_gray = rgb2gray(image) # modifying to greyscale <@\label{line:img-to-greyscale}@>
# Compute the Canny filter for two values of sigma (from example
edges1 = feature.canny(im_gray)
edges2 = feature.canny(im_gray, sigma=3)
# display results
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(8, 3))
ax[0].imshow(image, cmap='gray')
ax[0].set_title('noisy image', fontsize=20)
ax[1].imshow(edges1, cmap='gray')
ax[1].set_title(r'Canny filter, $\sigma=1$', fontsize=20)
ax[2].imshow(edges2, cmap='gray')
ax[2].set_title(r'Canny filter, $\sigma=3$', fontsize=20)
for a in ax:
a.axis('off')
fig.tight_layout()
plt.show()
\end{lstlisting}
\newpage
\subsection{Математическое обоснование работы функции вычисления тензора инерции}
Тензор инерции величина связывающая момент импульса тела с его угловой скоростью \(\bar{L} = \widehat{J}\bar{w}\). Для тела состоящего из N точек величина момента n-й точки вычисляется по формуле \(\bar{L}_n = \bar{r} \times \bar{p}\). Тогда момент импульса тела можно представить как:
\[\bar{L} = \sum_{n=1}^{N} \bar{r} \times \bar{p}.\]
Импульс тела массой m равен \(\bar{p} = m\bar{v}\), тогда выражая скорость через угловую скорость (\(\bar{v} = [\bar{w} \times \bar{r}]\)), получаем выражение для момента инерции тела:
\[\bar{L} = \sum_{n=1}^{N} \bar{r} \times m_n [\bar{w} \times \bar{r}].\]
Так как масса - это скалярная величина получаем:
\[\bar{L} = \sum_{n=1}^{N} m_n[\bar{r} \times [\bar{w} \times \bar{r}]]\]
Применив формулу Лагранжа для двойного векторного произведения
\[[\bar{r} \times [\bar{w} \times \bar{r}]] = \bar{w} (\bar{r}, \bar{r}) - \bar{r}(\bar{w},\bar{r})\]
Так как для ортонормированного базиса \((\bar{w} , \bar{r}) = w_x x + w_y y + w_z z\) получаем:
\[ \bar{L} = \sum_{n=1}^N m_n[\bar{r} \times [\bar{w} \times \bar{r}]] = \sum_{n=1}^N m_n (\bar{w} r^2 - \bar{r}(w_x x + w_y y + w_z z)).\]
Пусть векторы базиса i,j,k:
\begin{equation*}
\begin{gathered}
\sum_{n=1}^N m_n ((\bar{i}w_x r^2 + \bar{j}w_y r^2 + \bar{k}w_z r^2) - (\bar{i}x + \bar{j}y + \bar{k}z)(w_x x + w_y y + w_z z)) = \\
= \sum_{n=1}^N m_n ((\bar{i}w_x (x^2 + y^2 + z^2) + \bar{j}w_y (x^2 + y^2 + z^2) + \bar{k}w_z (x^2 + y^2 + z^2)) -\\
- (\bar{i}w_x x^2 + \bar{j}w_y y^2 + \bar{k}w_z z^2 + \bar{i}w_y x y + \bar{i}w_z x z + \bar{j}w_x y x + \bar{j}w_z y z + \bar{k}w_x z x + \bar{k}w_y z y ))
\end{gathered}
\end{equation*}
Сокращая члены выражения получаем:
\begin{equation*}
\begin{gathered}
\sum_{n=1}^N m_n ((\bar{i}w_x (y^2 + z^2) + \bar{j}w_y (x^2 +z^2) + \bar{k}w_z (x^2 + y^2)) -\\
-(\bar{i}w_y x y + \bar{i}w_z x z + \bar{j}w_x y x + \bar{j}w_z y z + \bar{k}w_x z x +\bar{k}w_y z y )) \\
\end{gathered}
\end{equation*}
Так как масса тела находится в одной плоскости, выражение примет вид:
\[\bar{L} = \sum_{n=1}^{N} m_n ((\bar{i}{w}_x (y^2) + \bar{j}{w}_y (x^2) - (\bar{i}{w}_y x y + \bar{j}{w}_x y x))\]
Запишем L в виде вектора:
\[
\bar{L} =
\begin{pmatrix}
\sum_{n=1}^{N} m_n(w_{x}y^2 - w_{y}x y) \\
\sum_{n=1}^{N} m_n(w_{y}x^2 - w_{x}y x) \\
\end{pmatrix}
\bar{w} =
\begin{pmatrix}
w_{x} \\
w_{y} \\
\end{pmatrix}
\]
то есть, \(\bar{L} = \widehat{J}\bar{w}\). Представляя \(\widehat{J}\) в виде:
\[
\widehat{J} = \begin{pmatrix}
J_{xx} & J_{xy} \\
J_{yx} & J_{yy} \\
\end{pmatrix}
\]
Получаем:
\[
\begin{pmatrix}
\sum_{n=1}^{N} m_n(w_{x}y^2 - w_{y}x y) \\
\sum_{n=1}^{N} m_n(w_{y}x^2 - w_{x}y x) \\
\end{pmatrix}=
\begin{pmatrix}
J_{xx} & J_{xy} \\
J_{yx} & J_{yy} \\
\end{pmatrix}
\begin{pmatrix}
w_{x} \\
w_{y} \\
\end{pmatrix}
\]
\[
\begin{pmatrix}
\sum_{n=1}^{N} m_n(w_{x}y^2 - w_{y}x y) \\
\sum_{n=1}^{N} m_n(w_{y}x^2 - w_{x}y x) \\
\end{pmatrix}=
\begin{pmatrix}
J_{xx} w_{x} + J_{xy} w_{y}\\
J_{yx} w_{x} + J_{yy} w_{y} \\
\end{pmatrix}
\]
\[
\begin{pmatrix}
\sum_{n=1}^{N} m_n(w_{x}y^2) - \sum_{n=1}^{N} m_n(w_{y}x y) \\
\sum_{n=1}^{N} m_n(w_{y}x^2) - \sum_{n=1}^{N} m_n(w_{x}y x) \\
\end{pmatrix}=
\begin{pmatrix}
J_{xx} w_{x} + J_{xy} w_{y}\\
J_{yx} w_{x} + J_{yy} w_{y} \\
\end{pmatrix}
\]
Тогда компоненты \(\widehat{J}\) можно представить в виде:
\begin{equation*}
\begin{gathered}
J_{xx} = \sum_{n=1}^{N} m_n(y^2)\\
J_{xy} = -\sum_{n=1}^{N} m_n(xy)\\
J_{yx} = -\sum_{n=1}^{N} m_n(yx)\\
J_{yy} = \sum_{n=1}^{N} m_n(x^2)\\
\end{gathered}
\end{equation*}
\end{document}