From aa6754f2a1c3e1123baf0b0e448133f8d33f51dd Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 20 Sep 2023 18:56:32 +0300 Subject: [PATCH 01/11] first example md_parser --- app/main/reports/md_parser/example.md | 158 ++++++++++++++++++++++++ app/main/reports/md_parser/md_parser.py | 64 ++++++++++ 2 files changed, 222 insertions(+) create mode 100644 app/main/reports/md_parser/example.md create mode 100644 app/main/reports/md_parser/md_parser.py diff --git a/app/main/reports/md_parser/example.md b/app/main/reports/md_parser/example.md new file mode 100644 index 00000000..d243a05d --- /dev/null +++ b/app/main/reports/md_parser/example.md @@ -0,0 +1,158 @@ +# Описание бенчмарка для сравнения влияния алгоритмов выявления особых RGB-точек в изображении на точность локализации мобильного робота. + +Ключевые слова: алгоритмы выявления особых RGB-точек(признаков), визуальная одометрия, бенчмарк. + +## Аннотация + +В статье представлен обзор существующих алгоритмов выявлениях особых RGB-точек(признаков). Сформированы требования к бенчмарку для сравнения влияния алгоритмов выявления признаков на точность локализации мобильного робота. Кратко изложены этапы вычисления местоположения робота методом визуальной одометрии, которые будут использоваться в бенчмарке. Приведены инструменты для реализации бенчмарка. + +## Введение + + С быстрым развитием области мобильной робототехники, возрастает необходимость в точной локализации роботов. Одним из методов отслеживания движения является визуальная одометрия, которая использует поток изображений с камеры робота. Выявление и описание признаков в изображении является одним из первых и важнейших этапов визуальной одометрии [2]. Необходимо провести исследования влияния алгоритмов выявления признаков в изображении на точность локализации мобильного робота. + +Целью данной работы является разработать архитектуру бенчмарка для исследования алгоритмов выявления особых RGB-точек(признаков) изображений на точность локализации мобильного робота. + +Для достижения цели были поставлены следующие задачи: + +1. Изучить существующие алгоритмы выявления признаков. +2. Определить метод сравнения алгоритмов выявления признаков. +3. Описать способ реализации бенчмарка алгоритмов выявления признаков. + +Объектом исследования являются алгоритмы выявления признаков. + +Предметом исследования являются влияния алгоритмов выявления признаков на точность локализации мобильного робота. + +## Обзор предметной области + +### Принцип отбора аналогов + +Для создания бенчмарка необходимо провести обзор существующих алгоритмов выявления признаков. Для поиска алгоритмов выявления признаков использовался следующий запрос: feature detection and description algorithms. + +#### SIFT + +Один из популярнейших алгоритмов выявления и описания признаков в изображении, предложенный в 2004 году[3]. Состоит из нескольких этапов: + +1. **Поиск особых точек.** Для достижения инвариантности относительно масштаба строятся пирамиды гауссианов. Гауссиан - это изображение после применения гауссового фильтра[4]. Далее из разностей соседних гауссианов в пирамиде получают пирамиду разности гауссиан. После ищутся локальные экстремумы в пирамиде разностей гауссиан. +2. **Локализация ключевых точек.** Используется разложение масштабного пространства в ряд Тейлора для получения более точных значений экстремумов. +3. **Поиск ориентации ключевых точек**. Для инвариантности к вращению ключевым точкам назначается ориентация. Направление ключевой точки находиться исходя из её окрестности - для соседних точек вычисляется величина и направление градиента. +4. **Описание ключевой точки**. Описание (дескриптор) состоит из окрестности 16x16 вокруг ключевой точки. Также принимаются некоторые меры для обеспечения устойчивости к освещению, вращению и т.п. + +#### SURF + +Модификация SIFT, нацеленная на ускорение вычислений[5]. Вместо разности гауссианов используется коробчатый фильтр (Box Filter), уменьшающий количество вычислений и позволяющий выполнять их параллельно для разных масштабов. Также для обнаружения особых точек используется детерминант матрицы Гессе, что дополнительно снижает траты на вычисления. За счёт улучшений SURF требует гораздо меньше времени на вычисления, чем SIFT, но при этом немного теряет в устойчивости перед изменением освещения и сменой точки обзора. + +#### KAZE + +Метод выявления и описания признаков, работающий в нелинейном масштабном пространстве [6]. Построение нелинейного масштабного пространства происходит с помощью техник AOS[7]. Далее обнаруживаются максимумы с помощью детерминанта матрицы Гессе, нормализованный по масштабу. На последнем шаге вычисляется ориентация ключевых точек (как в SURF) и получают описание(дескриптор) размером 24x24. Алгоритм KAZE уменьшает шум и имеет более высокую точность (чем SIFT и SURF) за счёт небольшого увеличения вычислений. + +#### BRISK + +Был предложен в 2011 году как альтернатива SURF с более низкими вычислительными затратами[8]. Алгоритм основан на алгоритме обнаружения углов AGAST [9] (который является модификацией FAST[10]). Описание (дескриптор) состоит из бинарной битовой строки, соответствующей расстоянию Хэмминга, что позволяет ускорить вычисления. + +#### ORB + +Алгоритм основан на модификациях алгоритма выявления особых точек FAST[10] и алгоритма описания признаков BRIEF[11] и предложен в 2011 году[12]. Вычисляются особые точки с помощью алгоритма FAST, затем точки фильтруются алгоритмом обнаружения углов Харриса[13]. Далее вычисляется ориентация ключевой точки. После используется модифицированный алгоритм BRIEF - точки, предназначенные для сравнения, поворачиваются на угол ориентации ключевой точки (таким образом лишая недостатка BRIEF в неустойчивости к вращениям). + +### Сравнение аналогов + +Были выбраны следующие основные параметры сравнения: + +1. Повторяемость - среднее количество признаков, обнаруженных на изображениях после применения различных геометрических и фотометрических преобразований. В данном обзоре рассмотрены вращение и масштабирование. Высокое значение данного параметра позволяет говорить о том, что найденные признаки будут обнаружены и на других изображениях. +2. Точность при сопоставлении изображений. Исключение выбросов увеличит точность локализации мобильного робота. +3. Время выявления и описания признаков. Вычислительно эффективные алгоритмы позволяют обработать большее количество данных. + +В табл.1 представлено сравнение алгоритмов по данным из статьи[14]. + +Таблица 1 - Сравнительный анализ алгоритмов по количественным критериям + +| Алгоритмы | Повторяемость, % | Повторяемость, % | Повторяемость, % | Повторяемость, % | Повторяемость, % | Процент ошибки, % | Процент ошибки, % | Процент ошибки, % | Процент ошибки, % | Процент ошибки, % | Среднее время выявления и описания признаков, c | +| --------- | ---------------- | ---------------- | ---------------- | ---------------- | ---------------- | ----------------- | ----------------- | ----------------- | ----------------- | ----------------- | ----------------------------------------------- | +| | Масштаб | Масштаб | Масштаб | Вращение | Вращение | Масштаб | Масштаб | Масштаб | Вращение | Вращение | | +| | 50% | 150% | 200% | 30° | 60° | 50% | 150% | 200% | 30° | 60° | | +| SIFT | 78 | 80 | 82 | 78 | 78 | 0 | 0 | 0 | 0 | 0 | 0.198 | +| SURF | 81 | 77 | 83 | 73 | 72 | 0.08 | 0.18 | 0.22 | 0 | 0.01 | 0.138 | +| KAZE | 70 | 70 | 73 | 88 | 88 | 0.17 | 0 | 0.3 | 0 | 0 | 0.242 | +| BRISK | 81 | 83 | 85 | 82 | 84 | 0 | 0 | 0.2 | 0.01 | 0.01 | 0.045 | +| ORB | 85 | 83 | 66 | 89 | 89 | 0.2 | 0.1 | 0.5 | 0.01 | 0.01 | 0.01 | + + + +В среднем повторяемость выше у BRISK и ORB, но при этом у ORB сильно снижается значения при увеличении масштаба более чем на 150%. У KAZE высокие значения для вращений. Самым точным алгоритмом является SIFT. ORB имеет наибольший процент ошибок. Самым вычислительно трудоёмким является KAZE, самым эффективным ORB, за ним по эффективности идёт BRISK. + +## Выбор метода решения + +Бенчмарк должен предоставлять выбор различных алгоритмов выявления и описания признаков. Пользователю предоставляется возможность загрузить набор изображений и файлы с эталонными значениям и местоположения. Пользователь может узнать промежуточные значения работы бенчмарка, например, количество найденных признаков. По набору изображений будут найдены признаки и их описание, далее на основе этих признаков бенчмарк будет определять текущее местоположение мобильного робота. + +Исходя из обзора алгоритмов, бенчмарк должен: + +1. Определять точность локализации мобильного робота. Бенчмарк выдаёт результат в виде графиков, по которым можно отследить ошибку определения местоположения. +2. Предоставлять возможность применять геометрические и фотометрические преобразования над изображениями для оценивания инвариантности алгоритмов. Например, к части изображений может быть применён эффект размытия или добавлен шум. +3. Рассчитывать время выполнения алгоритмов. По окончанию работы бенчмарк выдаёт общее время на расчёт определения местоположения. + +## Описание метода решения + +Для исследования влияния алгоритмов выявления признаков на точность локализации мобильного робота, необходимо воспользоваться методом визуальной одометрии и рассчитать местоположение робота. Метод визуальной одометрии, который будет реализован в бенчмарке, основывается на статьях [1] и [2]. Ниже приведены подробности данного метода: + +1. **Выявление и описание признаков**. На данном этапе работает один из алгоритмов, описанных в разделе "Cравнение аналогов". Для повышения точности дальнейших расчётов признаки должны быть равномерно распределены по всему изображению. Для этого изображения разбивают на сетку, в каждом фрагменте ищется определенное количество признаков. +2. **Отслеживание признаков**. После обнаружения признаков на первом изображении, необходимо найти эти признаки на остальных изображениях, таким образом отслеживая перемещение признаков между изображениями. Одним из быстрых и эффективных методов отслеживания является трекер Канаде-Лукаса-Томаси[15]. +3. **Расчёт движения**. На основе информации о том, как менялись признаки на изображении, можно рассчитать движение самого мобильного робота. Для расчёта движения используется существенная матрица, описывающая геометрическую связь между двумя изображениями[16]. Из существенной матрицы можно получить значения вращение и перемещение между изображениями. На основании данной информации можно высчитать координаты перемещения. +4. **Удаление выбросов**. Обычно в изображениях содержится множество выбросов, которые не учитываются алгоритмами выявления и описания признаков. С удалением выбросов хорошо справляется алгоритм RANSAC[17]. В данном случае для алгоритма RANSAC моделью является существенная матрица, а параметрами - признаки на изображении. +5. **Оптимизация**. При расчёте местоположения со временем будет накапливаться ошибка("scale drift") [18]. Одной из оптимизаций является обнаружение циклов[19]. Для этого возвращаются к предыдущим признакам, которые давно не появлялись на изображениях, и сравнивают с текущими. Если признаки совпали, применяют глобальную оптимизацию и исправляют траекторию движения робота. + +В качестве результата выполнения приведенного выше метода, будут доступны график с вычисленной траекторией и настоящей, и график, показывающий накопления ошибки с течением времени. По данным графиков можно будет оценить степень влияния алгоритмов выявления признаков на точность локализации мобильного робота. Также отдельно будет выводиться время выполнения алгоритмов для оценки их эффективности. + +В качестве основного инструмента реализации бенчмарка была выбрана библиотека OpenCV[20]. В неё включены все приведенные в обзоре алгоритмы выявления и описания признаков, а так же в ней есть множество функций по обработке изображений, которые будут необходимы для вычисления местоположения мобильного робота. В качестве языка программирования был выбран Python, из-за простого синтаксиса языка. + +Бенчмарк будет представлять из себя консольное приложение. Пользователь может выбрать один из предложенных алгоритмов выявления и описания признаков и выбрать папку с набором изображений (если у пользователя нет набора изображений, программа может использовать свой внутренний). Далее пользователь может выбрать, будет ли данные изображения подвергаться различными преобразованиям (например, добавления в изображение размытия или шума). После начинает работу алгоритм, вычисляющий местоположение робота. По завершению бенчмарк выведет количество времени, потраченное на вычисления и создаст два файла с графиками. + +## Заключение + +В ходе работы был проведён обзор существующих алгоритмов выявления признаков(особых RGB-точек), в ходе которого были выявлены основные требования к бенчмарку. Был представлен метод сравнения алгоритмов выявления признаков - непосредственное вычисление методом визуальной одометрии местоположение робота и дальнейшее сравнение результатов для различных алгоритмов выявления признаков. Также были предложены инструменты для реализации бенчмарка и описан способ реализации бенчмарка - консольное приложение, принимающие на вход набор изображение и выдающее график с траекторией мобильного робота. + +В дальнейшем следует расширять возможности бенчмарка: добавить больше алгоритмов выявления признаков и увеличить количество различных преобразований над набором изображений. Также в дальнейших работах можно расширить существующее решение, чтобы исследовать влияние алгоритмов вычисления признаков на SLAM[21]. + + + +## Список литературы + +[1] Fraundorfer, Friedrich ; Scaramuzza, Davide. Visual Odometry [Tutorial] // IEEE Robotics & Automation Magazine 18, 2011. + +[2] Fraundorfer, Friedrich ; Scaramuzza, Davide. Visual Odometry: Part II - Matching, Robustness, and Applications // IEEE Robotics & Automation Magazine 19, 2012. + +[3]David G. Lowe. Distinctive Image Features from Scale-Invariant Keypoints // International Journal of Computer Vision 60, 2004. + +[4]Mark Nixon, Alberto Aguado. Feature Extraction and Image Processing for Computer Vision, 2002, C.86-88. + +[5]Herbert Bay, Tinne Tuytelaars, Luc Van Gool. SURF: Speeded up robust features // Proceedings of the 9th European conference on Computer Vision - Volume Part I, 2006. + +[6]Pablo Fernández Alcantarilla. KAZE Features // European Conference on Computer Vision (ECCV), 2012. + +[7]J. Weickert; B.M.T.H. Romeny; M.A. Viergever. Efficient and reliable schemes for nonlinear diffusion filtering // IEEE, 1998. + +[8]Stefan Leutenegger,Margarita Chli, Roland Y.Siegwart. BRISK: Binary Robust Invariant Scalable Keypoints // IEEE International Conference on Computer Vision, 2011. + +[9]E. Mair,G. D. Hager,D. Burschka, M.Suppa, and G. Hirzinger. Adaptiveand generic corner detection based on the accelerated segment test // European Conference on Computer Vision, 2010. + +[10]Edward Rosten and Tom Drummond. Machine learning for high-speed corner detection // 9th European Conference on Computer Vision, 2006. + +[11]Michael Calonder, Vincent Lepetit, Christoph Strecha, Pascal Fua. "BRIEF: Binary Robust Independent Elementary Features" // 11th European Conference on Computer Vision (ECCV), 2010. + +[12]Ethan Rublee. ORB: an efficient alternative to SIFT or SURF // IEEE International Conference on Computer Vision, 2011. + +[13]Chris Harris, Mike Stephens. A Combined Corner and Edge Detector // Alvey Vision Conference, 1988. + +[14]Shaharyar Ahmed Khan Tareen, Zahra Saleem. A comparative analysis of SIFT, SURF, KAZE, AKAZE, ORB, and BRISK // 2018 International Conference on Computing, Mathematics and Engineering Technologies, 2018. + +[15]C. Tomasi and J. Shi, "Good features to track" // *Proc. CVPR*, 1994. + +[16]H. C. Longuet-Higgins. A computer algorithm for reconstructing a scene from two projections. // Nature, 293:133–135, 1981. + +[17]Martin A. Fischler and Robert C. Bolles. Random Sample Consensus: A Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography // Comm. Of the ACM, 1981. + +[18]L. Matthies and S. Shafer, "Error modeling in stereo navigation" // IEEE J. Robot. Automat., vol. 3, no. 3, 1987. + +[19] T. Bailey and H. Durrant-Whyte, "Simultaneous localisation and mapping (SLAM): Part II. State of the art" // IEEE Robot. Automat. Mag., vol. 13, no. 3, 2006. + +[20] OpenCV [Электронный ресурс]. URL: https://opencv.org/ (дата обращения 19.12.2022). + +[21] Alif Ridzuan Khairuddin, Mohamad Shukor Talib, Habibollah Haron. Review on simultaneous localization and mapping (SLAM) // IEEE International Conference on Control System, Computing and Engineering, 2015. \ No newline at end of file diff --git a/app/main/reports/md_parser/md_parser.py b/app/main/reports/md_parser/md_parser.py new file mode 100644 index 00000000..c9a36929 --- /dev/null +++ b/app/main/reports/md_parser/md_parser.py @@ -0,0 +1,64 @@ +import markdown +import re + +class MdParser: + def __init__(self): + self.path_to_md_file = '/home/marina/src/2/mse_auto_checking_slides_vaganov/app/main/reports/md_parser/example.md' + self.headers = [] + self.chapters = [] + self.paragraphs = [] + self.html_text = '' + self.tables = [] + self.chapter_with_text = [] + self.literature_header = [] + self.headers_page = 0 + + def get_html_from_md(self): + with open(self.path_to_md_file, "r", encoding="utf-8") as f: + text = f.read() + self.html_text = markdown.markdown(text) + self.paragraphs = self.html_text.split('\n') + return(self.paragraphs, self.html_text) + + def get_headers(self): + header_regex = "

(.*?)<\/h1>" + self.headers = re.findall(header_regex, self.html_text) + return self.headers + + def get_chapters(self): + chapter_regex = "

(.*?)<\/h2>" + self.chapters = re.findall(chapter_regex, self.html_text) + return(self.chapters) + + def get_chapter_with_text(self): + text = self.html_text + chapter_name = '' + for chapter in self.chapters: + self.split_chapter = text.split("

" + chapter + "

") + self.chapter_with_text.append(chapter_name + self.split_chapter[-2]) + chapter_name = chapter + text = self.split_chapter[-1] + if chapter == self.chapters[len(self.chapters)-1]: + self.chapter_with_text.append(chapter_name + text) + return self.chapter_with_text + + def get_tables_size(self): + count_table_line = 0 + count_paragraph = len(self.paragraphs) + for line in self.paragraphs: + if "|" in line: + count_table_line +=1 + return (count_table_line, count_table_line/count_paragraph) + + + +file = MdParser() +file.get_html_from_md() +# print(file.get_headers()) +# print(file.get_chapters()) +# print(file.get_chapter_with_text()) +print(file.get_tables_size()) + +# if __name__ == '__main__':e +# get_html_from_md() + From 526060124cafa81dfd68d18d98f180df33e2d86c Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 20 Sep 2023 18:58:51 +0300 Subject: [PATCH 02/11] md_parser_example --- app/main/reports/md_parser/md_parser.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/main/reports/md_parser/md_parser.py b/app/main/reports/md_parser/md_parser.py index c9a36929..0bc68f1b 100644 --- a/app/main/reports/md_parser/md_parser.py +++ b/app/main/reports/md_parser/md_parser.py @@ -3,7 +3,7 @@ class MdParser: def __init__(self): - self.path_to_md_file = '/home/marina/src/2/mse_auto_checking_slides_vaganov/app/main/reports/md_parser/example.md' + self.path_to_md_file = '' #insert path to file self.headers = [] self.chapters = [] self.paragraphs = [] @@ -58,7 +58,3 @@ def get_tables_size(self): # print(file.get_chapters()) # print(file.get_chapter_with_text()) print(file.get_tables_size()) - -# if __name__ == '__main__':e -# get_html_from_md() - From f80330a989ba61583956a92a1e62fc28fdc4894e Mon Sep 17 00:00:00 2001 From: Marina Date: Thu, 21 Sep 2023 11:10:07 +0300 Subject: [PATCH 03/11] change structure --- app/main/reports/md_parser/md_parser.py | 45 +++++++++++++------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/app/main/reports/md_parser/md_parser.py b/app/main/reports/md_parser/md_parser.py index 0bc68f1b..d14a4fd4 100644 --- a/app/main/reports/md_parser/md_parser.py +++ b/app/main/reports/md_parser/md_parser.py @@ -2,33 +2,32 @@ import re class MdParser: - def __init__(self): - self.path_to_md_file = '' #insert path to file + def __init__(self, path_to_md_file): + self.path_to_md_file = path_to_md_file self.headers = [] self.chapters = [] self.paragraphs = [] self.html_text = '' self.tables = [] self.chapter_with_text = [] - self.literature_header = [] - self.headers_page = 0 + # self.literature_header = '' - def get_html_from_md(self): + def read_md_file(self): with open(self.path_to_md_file, "r", encoding="utf-8") as f: - text = f.read() - self.html_text = markdown.markdown(text) + md_text = f.read() + return md_text + + def get_html_from_md(self, md_text): + self.html_text = markdown.markdown(md_text) self.paragraphs = self.html_text.split('\n') - return(self.paragraphs, self.html_text) def get_headers(self): header_regex = "

(.*?)<\/h1>" self.headers = re.findall(header_regex, self.html_text) - return self.headers def get_chapters(self): chapter_regex = "

(.*?)<\/h2>" self.chapters = re.findall(chapter_regex, self.html_text) - return(self.chapters) def get_chapter_with_text(self): text = self.html_text @@ -38,9 +37,7 @@ def get_chapter_with_text(self): self.chapter_with_text.append(chapter_name + self.split_chapter[-2]) chapter_name = chapter text = self.split_chapter[-1] - if chapter == self.chapters[len(self.chapters)-1]: - self.chapter_with_text.append(chapter_name + text) - return self.chapter_with_text + self.chapter_with_text.append(chapter_name + text) def get_tables_size(self): count_table_line = 0 @@ -48,13 +45,17 @@ def get_tables_size(self): for line in self.paragraphs: if "|" in line: count_table_line +=1 - return (count_table_line, count_table_line/count_paragraph) - + return count_table_line/count_paragraph + + def parse_md_file(self): + md_text = self.read_md_file() + self.get_html_from_md(md_text) + self.get_headers() + self.get_chapters() + self.get_chapter_with_text() + self.get_tables_size() + return f"{self.headers} \n {self.chapters} \n {self.chapter_with_text} \n {self.get_tables_size()}" - -file = MdParser() -file.get_html_from_md() -# print(file.get_headers()) -# print(file.get_chapters()) -# print(file.get_chapter_with_text()) -print(file.get_tables_size()) + +md_file = MdParser('') +print(md_file.parse_md_file()) From 8061d8dba3d0983564bb7d27b09ac92dbb325730 Mon Sep 17 00:00:00 2001 From: Marina Date: Thu, 21 Sep 2023 12:00:01 +0300 Subject: [PATCH 04/11] delete changes from previos branch --- app/main/check_packs/pack_config.py | 3 --- app/servants/pre_luncher.py | 4 ++-- assets/scripts/upload.js | 4 +--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/main/check_packs/pack_config.py b/app/main/check_packs/pack_config.py index 9740df11..1def2e45 100644 --- a/app/main/check_packs/pack_config.py +++ b/app/main/check_packs/pack_config.py @@ -45,7 +45,6 @@ DEFAULT_TYPE = 'pres' REPORT_TYPES = ('LR', 'VKR') DEFAULT_REPORT_TYPE_INFO = {'type': 'report', 'report_type': REPORT_TYPES[1]} -# DEFAULT_REPORT_TYPE_INFO = {'type': 'report', 'report_type': REPORT_TYPES[0]} DEFAULT_PRES_TYPE_INFO = {'type': 'pres'} DEFAULT_TYPE_INFO = DEFAULT_PRES_TYPE_INFO @@ -54,6 +53,4 @@ name="BasePresentationCriterionPack"), 'report': BaseCriterionPack(BASE_REPORT_CRITERION, DEFAULT_REPORT_TYPE_INFO, min_score=1.0, name="BaseReportCriterionPack ") - # 'report': BaseCriterionPack(BASE_REPORT_CRITERION, DEFAULT_REPORT_TYPE_INFO, min_score=1.0, - # name="LabReportPack ") } diff --git a/app/servants/pre_luncher.py b/app/servants/pre_luncher.py index 47836e2a..9e1b3331 100644 --- a/app/servants/pre_luncher.py +++ b/app/servants/pre_luncher.py @@ -3,7 +3,7 @@ from db.db_methods import add_user, get_user, get_client, edit_user, save_criteria_pack from main.check_packs.pack_config import BASE_PACKS, DEFAULT_REPORT_TYPE_INFO -# LabReportPack + from pymongo.errors import ConnectionFailure from server import ALLOWED_EXTENSIONS @@ -41,7 +41,7 @@ def init(app, debug): user.criteria = BASE_PACKS[file_type].name user.formats = list(ALLOWED_EXTENSIONS.get(file_type)) user.two_files = True - # user.two_files = False + edit_user(user) logger.info(f"Создан администратор по умолчанию: логин: {user.username}, пароль уточняйте у разработчика") diff --git a/assets/scripts/upload.js b/assets/scripts/upload.js index cb5ca78d..cf152e27 100644 --- a/assets/scripts/upload.js +++ b/assets/scripts/upload.js @@ -7,8 +7,6 @@ const file_input = $("#upload_file"); const file_label = $("#upload_file_label"); const return_file_label = file_label.text(); -const pt = $("#upload_file_pdf"); -pdf_uploaded = pt.length > 0 ? !!pt.prop("files")[0] : false; //проверка наличия pdf const pdf_file_input = $("#upload_file_pdf"); const pdf_file_label = $("#upload_file_label_pdf"); const return_pdf_file_label = pdf_file_label.text(); @@ -60,7 +58,7 @@ const resetFileUpload = () => { const changeUploadButton = () => { if (pdf_uploaded || file_uploaded) { - const pdf_size = pdf_uploaded ? (pt.prop("files")[0]?.size || 0) : 0; + const pdf_size = pdf_file_input.prop("files")[0]?.size || 0; const file_size = file_input.prop("files")[0]?.size || 0; if (pdf_size + file_size <= file_upload_limit) { if (file_uploaded) From 00e1b63c60e8983284d5190922b78f0268eedece Mon Sep 17 00:00:00 2001 From: Marina Date: Thu, 21 Sep 2023 12:20:49 +0300 Subject: [PATCH 05/11] add folder 'playground' --- {app/main/reports => playground}/md_parser/example.md | 0 {app/main/reports => playground}/md_parser/md_parser.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {app/main/reports => playground}/md_parser/example.md (100%) rename {app/main/reports => playground}/md_parser/md_parser.py (94%) diff --git a/app/main/reports/md_parser/example.md b/playground/md_parser/example.md similarity index 100% rename from app/main/reports/md_parser/example.md rename to playground/md_parser/example.md diff --git a/app/main/reports/md_parser/md_parser.py b/playground/md_parser/md_parser.py similarity index 94% rename from app/main/reports/md_parser/md_parser.py rename to playground/md_parser/md_parser.py index d14a4fd4..38a8ce17 100644 --- a/app/main/reports/md_parser/md_parser.py +++ b/playground/md_parser/md_parser.py @@ -57,5 +57,5 @@ def parse_md_file(self): return f"{self.headers} \n {self.chapters} \n {self.chapter_with_text} \n {self.get_tables_size()}" -md_file = MdParser('') +md_file = MdParser('/home/marina/src/2/mse_auto_checking_slides_vaganov/playground/md_parser/example.md') print(md_file.parse_md_file()) From 5a55f6cb559dafce0b45666cc778048c43e7337c Mon Sep 17 00:00:00 2001 From: Marina Date: Fri, 22 Sep 2023 11:43:47 +0300 Subject: [PATCH 06/11] add if-name-main-construction --- playground/md_parser/md_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/playground/md_parser/md_parser.py b/playground/md_parser/md_parser.py index 38a8ce17..510db381 100644 --- a/playground/md_parser/md_parser.py +++ b/playground/md_parser/md_parser.py @@ -45,7 +45,7 @@ def get_tables_size(self): for line in self.paragraphs: if "|" in line: count_table_line +=1 - return count_table_line/count_paragraph + return round(count_table_line/count_paragraph, 4) def parse_md_file(self): md_text = self.read_md_file() @@ -56,6 +56,6 @@ def parse_md_file(self): self.get_tables_size() return f"{self.headers} \n {self.chapters} \n {self.chapter_with_text} \n {self.get_tables_size()}" - -md_file = MdParser('/home/marina/src/2/mse_auto_checking_slides_vaganov/playground/md_parser/example.md') -print(md_file.parse_md_file()) +if __name__ == "__main__": + md_file = MdParser('playground/md_parser/example.md') + print(md_file.parse_md_file()) From b0872746288893d6d96caf66691606c5da4f5207 Mon Sep 17 00:00:00 2001 From: Marina Date: Fri, 22 Sep 2023 15:57:28 +0300 Subject: [PATCH 07/11] improved view --- app/main/check_packs/pack_config.py | 2 +- playground/md_parser/md_parser.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/main/check_packs/pack_config.py b/app/main/check_packs/pack_config.py index 1def2e45..0639689b 100644 --- a/app/main/check_packs/pack_config.py +++ b/app/main/check_packs/pack_config.py @@ -52,5 +52,5 @@ 'pres': BaseCriterionPack(BASE_PRES_CRITERION, DEFAULT_PRES_TYPE_INFO, min_score=1.0, name="BasePresentationCriterionPack"), 'report': BaseCriterionPack(BASE_REPORT_CRITERION, DEFAULT_REPORT_TYPE_INFO, min_score=1.0, - name="BaseReportCriterionPack ") + name="BaseReportCriterionPack") } diff --git a/playground/md_parser/md_parser.py b/playground/md_parser/md_parser.py index 510db381..0c6a1b95 100644 --- a/playground/md_parser/md_parser.py +++ b/playground/md_parser/md_parser.py @@ -1,4 +1,4 @@ -import markdown +import markdown #installation: pip install markdown import re class MdParser: @@ -54,7 +54,7 @@ def parse_md_file(self): self.get_chapters() self.get_chapter_with_text() self.get_tables_size() - return f"{self.headers} \n {self.chapters} \n {self.chapter_with_text} \n {self.get_tables_size()}" + return f"Заголовки:\n{self.headers}\n\nГлавы:\n{self.chapters}\n\nГлавы с текстом:\n{self.chapter_with_text}\n\nДоля таблиц в тексте:\n{self.get_tables_size()}" if __name__ == "__main__": md_file = MdParser('playground/md_parser/example.md') From 48cbea1e90bc0cb6caec3ce1876989607fc0d9f1 Mon Sep 17 00:00:00 2001 From: Marina Date: Tue, 3 Oct 2023 15:57:03 +0300 Subject: [PATCH 08/11] first-step package md_uploader --- app/main/reports/README.md | 11 +++- app/main/reports/md_uploader/__init__.py | 1 + app/main/reports/md_uploader/__main__.py | 21 ++++++++ app/main/reports/md_uploader/md_uploader.py | 60 +++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 app/main/reports/md_uploader/__init__.py create mode 100644 app/main/reports/md_uploader/__main__.py create mode 100644 app/main/reports/md_uploader/md_uploader.py diff --git a/app/main/reports/README.md b/app/main/reports/README.md index 16904d47..4c591479 100644 --- a/app/main/reports/README.md +++ b/app/main/reports/README.md @@ -1,6 +1,6 @@ # Запуск и тестирование -Пререквизиты: `argparse`, `python-docx`, `docx2python`, `re`, `subprocess`. Для парсинга `.doc`-файлов потребуется +Пререквизиты: `argparse`, `python-docx`, `docx2python`, `re`, `subprocess`, `markdown`. Для парсинга `.doc`-файлов потребуется LibreOffice. Здесь и далее считается, что корневая директория репозитория добавлена в `PYTHONPATH`. @@ -65,3 +65,12 @@ Proof-of-concept парсинг файлов `.docx` с выводом стру ```bash $ python3 -m app.main.mse22.pdf_document text_from_pages --filename path_to_file ``` + +## `MD` + +Парсинг файлов `.md` с выводом структуры файла в текстовом виде в stdout. + +```bash +$ python3 -m app.main.reports.md_uploader md_parser --mdfile path_to_md_file +``` + diff --git a/app/main/reports/md_uploader/__init__.py b/app/main/reports/md_uploader/__init__.py new file mode 100644 index 00000000..ef406550 --- /dev/null +++ b/app/main/reports/md_uploader/__init__.py @@ -0,0 +1 @@ +from .md_uploader import MdUpload \ No newline at end of file diff --git a/app/main/reports/md_uploader/__main__.py b/app/main/reports/md_uploader/__main__.py new file mode 100644 index 00000000..f69ae975 --- /dev/null +++ b/app/main/reports/md_uploader/__main__.py @@ -0,0 +1,21 @@ +import argparse + +from .md_uploader import main as md_uploader_main + + +def parse_args(): + parser = argparse.ArgumentParser(description='File md parser') + subparsers = parser.add_subparsers() + md_parser = subparsers.add_parser('md_parser', help='md document') + md_parser.add_argument('--mdfile', type=str, required=True, help='path to md file') + md_parser.set_defaults(func=md_uploader_main) + return parser.parse_args() + + +def main(): + args = parse_args() + args.func(args) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/app/main/reports/md_uploader/md_uploader.py b/app/main/reports/md_uploader/md_uploader.py new file mode 100644 index 00000000..1df1284a --- /dev/null +++ b/app/main/reports/md_uploader/md_uploader.py @@ -0,0 +1,60 @@ +import markdown #installation: pip install markdown +import re + +class MdUpload: + def __init__(self, path_to_md_file): + self.path_to_md_file = path_to_md_file + self.headers = [] + self.chapters = [] + self.paragraphs = [] + self.html_text = '' + self.tables = [] + self.chapter_with_text = [] + + def read_md_file(self): + with open(self.path_to_md_file, "r", encoding="utf-8") as f: + md_text = f.read() + return md_text + + def get_html_from_md(self, md_text): + self.html_text = markdown.markdown(md_text) + self.paragraphs = self.html_text.split('\n') + + def get_headers(self): + header_regex = "

(.*?)<\/h1>" + self.headers = re.findall(header_regex, self.html_text) + + def get_chapters(self): + chapter_regex = "

(.*?)<\/h2>" + self.chapters = re.findall(chapter_regex, self.html_text) + + def get_chapter_with_text(self): + text = self.html_text + chapter_name = '' + for chapter in self.chapters: + self.split_chapter = text.split("

" + chapter + "

") + self.chapter_with_text.append(chapter_name + self.split_chapter[-2]) + chapter_name = chapter + text = self.split_chapter[-1] + self.chapter_with_text.append(chapter_name + text) + + def get_tables_size(self): + count_table_line = 0 + count_paragraph = len(self.paragraphs) + for line in self.paragraphs: + if "|" in line: + count_table_line +=1 + return round(count_table_line/count_paragraph, 4) + + def parse_md_file(self): + md_text = self.read_md_file() + self.get_html_from_md(md_text) + self.get_headers() + self.get_chapters() + self.get_chapter_with_text() + self.get_tables_size() + return f"Заголовки:\n{self.headers}\n\nГлавы:\n{self.chapters}\n\nГлавы с текстом:\n{self.chapter_with_text}\n\nДоля таблиц в тексте:\n{self.get_tables_size()}" + +def main(args): + md_file = MdUpload(args.mdfile) + print(md_file.parse_md_file()) From 9019fc96f59507bdb96e2994904a24306b2f8b89 Mon Sep 17 00:00:00 2001 From: Marina Date: Tue, 3 Oct 2023 16:02:27 +0300 Subject: [PATCH 09/11] add empty string --- app/main/reports/md_uploader/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/reports/md_uploader/__init__.py b/app/main/reports/md_uploader/__init__.py index ef406550..31cb93c1 100644 --- a/app/main/reports/md_uploader/__init__.py +++ b/app/main/reports/md_uploader/__init__.py @@ -1 +1 @@ -from .md_uploader import MdUpload \ No newline at end of file +from .md_uploader import MdUpload From 63193e346dcda2091def01bf8ab16649b335dfdb Mon Sep 17 00:00:00 2001 From: Marina Date: Tue, 3 Oct 2023 16:03:10 +0300 Subject: [PATCH 10/11] add empty string2 --- app/main/reports/md_uploader/md_uploader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/main/reports/md_uploader/md_uploader.py b/app/main/reports/md_uploader/md_uploader.py index 1df1284a..926052ea 100644 --- a/app/main/reports/md_uploader/md_uploader.py +++ b/app/main/reports/md_uploader/md_uploader.py @@ -58,3 +58,4 @@ def parse_md_file(self): def main(args): md_file = MdUpload(args.mdfile) print(md_file.parse_md_file()) + From 5c09bc20fc99bf13794fb50b2b1d0f0311244161 Mon Sep 17 00:00:00 2001 From: Marina Date: Thu, 5 Oct 2023 15:06:05 +0300 Subject: [PATCH 11/11] add markdown in requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 6ec862a4..0d87cf6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,3 +27,4 @@ pdfplumber==0.6.1 pytest~=7.1.2 filetype==1.2.0 language-tool-python==2.7.1 +markdown==3.4.4