Система автоматизированного анализа пространственной структуры изображений. Подсистема линейной сегментации
Компьютерная графика и обработка изображений электронно-вычислительными машинами являются наиболее важным аспектом использования ЭВМ во всех сферах человеческой деятельности. Разработка "подсистемы линейной сегментации", описание алгоритма и логики.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 23.06.2008 |
Размер файла | 1,1 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
16. Бычин В.Б., Малинин С.В. Нормирование труда: Учебник. - Москва: Издательство «Экзамен», 2002.
17. ГОСТ 12.0.002-80 Система стандартов безопасности труда. Термины и определения - М.: Издательство стандартов, 1984.
18. СанПиН 2.2.4.548-96 Гигиенические требования к микроклимату производственных помещений. -М.: Издательство стандартов, 1996.
19. ГОСТ 12.1.003-89 Система стандартов безопасности труда. Шум. Общие требования безопасности. -М.: Издательство стандартов, 1989.
20. ГОСТ 12.1.009-76 Система стандартов безопасности труда. Электробезопасность. -М.: Издательство стандартов, 1976.
21. ГОСТ 12.1.004-91 Система стандартов безопасности труда. Пожарная безопасность. Общие требования. -М.: Издательство стандартов, 1992.
22. СНиП 24-05-95 Правила устройства электроустановок. -М.: Издательство стандартов, 1995.
23. Сенилов М.А., Почерняев С. В., Килин И. В. Методические указания по дипломному проектированию. - Ижевск: ИжГТУ, 1998.
24. ГОСТ 19.701-90 ЕСПД. Схемы алгоритмов, программ, данных и систем. - М.: Издательство стандартов, 1991.
25. ГОСТ 19.504-79 ЕСПД. Руководство программиста. Требования к содержанию и оформлению. - М.: Издательство стандартов, 1979.
26. ГОСТ 19.505-79 ЕСПД. Руководство оператора. Требования к содержанию и оформлению. - М.: Издательство стандартов, 1979.
ПРИЛОЖЕНИЕ 1
РУКОВОДСТВО ПРОГРАММИСТА
П.1.1. Назначение программы
Программа «Обработка и кодирование сегментов», обозначаемая как SegCode, предназначена для формирования кодов сегментов линий, содержащих координаты необходимых точек в зависимости от типа кодируемого сегмента. В процессе работы с программой обрабатывается массив точек, формируемый на основе входного файла изображения. В результате обработки осуществляется формирование массивов узлов и сегментов, на основании значений которых формируется код определенного сегмента. При этом учитываются типы узлов, а также типы кодируемых сегментов. Полученные результаты обработки могут быть выведены как на экран, так и в файл, и могут быть обработаны в других подсистемах.
Данная программа применяется в составе «Системы автоматизированного анализа пространственной структуры изображений».
П.1.2. Условия применения программы
При работе с программой необходимо обеспечить выполнение следующих требований к комплексу технических средств:
- персональный компьютер IBM PC с процессором не ниже Pentium I;
- клавиатура;
- монитор;
- жесткий диск с объемом свободного пространства не менее 50 МБ;
- оперативная память объемом не менее 128 МБ.
Работа программы возможна только на ЭВМ, которые поддерживают 32-разрядные операционные системы семейства Windows, такие как Windows 95, Windows NT или выше.
Программа реализована в среде программирования Borland C++ Builder 6.
Программа является самостоятельным модулем, не требующим установки дополнительного программного обеспечения
Программа состоит из модулей, каждый из которых обращается к подпрограммам:
Модуль lineseg.cpp:
- actExitExecute - обработка запроса завершения работы программы;
- FormCreate - создание формы обработки изображения;
- actZoomInExecute - режим увеличения изображения;
- actZoomOutExecute - режим уменьшения изображения;
- actOpenFileExecute - открытие файла для обработки;
- actSaveFileExecute - сохранение файла;
- Image2MouseMove - обработка события движения указателя мыши при наведении на элементы изображения;
- Image2MouseDown - обработка события нажатия кнопки мыши при редаутировании изображения;
- actZoom1Execute - режим установки масштаба изображения 100%;
- actAnalyzeExecute - вызов основной функции обработки изображения;
- FormCanResize - изменение размера окна;
- actNewFileExecute - создание нового файла для обработки;
- actGridCheckExecute - изменение режима просмотра сетки;
- actLightCheckExecute - изменение режима подсветки структурных элементов изображения;
- actZoom10Execute - режим установки 10-кратного увеличения изображения;
- actSegLightCheckExecute - изменение режима подсветки сегментов линий;
- actLockViewExecute - изменение режима блокировки изображения;
- actAnalyzeNodeExecute - обработка узлов изображения ;
- actAnalyzeSegExecute - обработка сегментов изображения;
- FormCloseQuery - обработка запроса на закрытие окна;
- actOpenArrayExecute - открытие изображения из файла массива точек;
- actSaveArrayExecute - сохранение изображения в файл массива точек;
- actOptionsExecute - вызов окна настройки;
- actSaveCodeExecute - запись результата обработки изображения в файл;
- actSegCodeOutExecute - выполнение алгоритма формирования координат сегментов;
- ZoomTo -установка заданного масштаба изображения;
- DrawGrid - рисование сетки изображения;
- ShowInfo - отображение информации о текущем состоянии;
- NeigCount - определение количества соседних точек;
- VectMove - осуществление движения координат обработки изобржаения в заданном направлении;
- wlog - вывод информации в журнал вычислений;
- VectToStr - преобразование кода вектора направления в строку;
- ValidateView - обработка свойств доступности элементов панели управления;
- plDistance(x, y, x1, y1, x2, y2) - вычисление расстояние (минимального) от точки (x,y) до прямой, заданной точками (x1,y1) и (x2,y2)
StrToLen - выравнивание строки для образования формата определенной длины;
- NeigNode - рекурсивная обработка соседей точки на принадлежность узлу
- NeigLine - рекурсивная обраобтка соседей точки (x,y) на принадлежность сегменту
- GetLineVect - рекурсивная обработка кода сегмента линии;
- NodeCentre - вычисление значения центра узла;
- FillLine изменение принадлежности точек одного сегмента другому;
- CodeLine - формирование кода сегмента линии.
Модуль lsImgSize:
- btnCancelClick - обработка события отмены создания нового файла;
TfrmImgSize - конструктор диалога создания нового файла;
Модуль lsOptions:
- btnCancelClick - обработка события отмены изменения настроек программы;
- Label1MouseDown - обработка события изменения цвета сетки изображения;
- Label2MouseDown - обработка события изменения цвета подсветки линий изображения;
- Label3MouseDown - обработка события изменения цвета подсветки узлов изображения;
- Label4MouseDown - обработка события изменения шрифта окна журнала;
- Label5MouseDown - обработка события изменения шрифта окна результатов;
- TfrmOptions - конструктор диалога настройки программы;
П.1.3. Характеристики программы
Программа имеет следующие режимы работы:
- импорт/экспорт файлов изображений;
- просмотр и редактирование изображений;
- поиск узлов;
- поиск сегментов;
- кодирование сегментов;
- автоматическая обработка изображения.
Просмотр и редактирование изображений выполняется по мере необходимости.
Импорт/экспорт файлов изображений осуществляется при получении входной информации и также при необходимости ее дополнительного вывода.
Поиск узлов, поиск сегментов и кодирование линий выполняются при необходимости пошаговой обработки изображения.
Автоматическая обработка изображения включает в себя полный цикл обработки изображения, не требующий дополнительных действий и позволяющий нажатием одной кнопки получить готовый результат.
Любой из режимов работы может быть выбран пользователем с выбором соответствующего пункта меню.
П.1.4. Обращение к программе
Для вызова программы необходимо запустить на выполнения исполняемый файл lineseg.exe.
Запуск программы может быть произведен из командной строки любого файлового менеджера или из системного меню программ операционной системы, а также соответствующим ярлыком при его наличии.
П.1.5. Входные и выходные данные
Входными данными программы может являться любое графическое изображение. В работе программы в составе «Системы автоматизированного анализа пространственной структуры изображений» входными данными программы является массив точек изображения, предназначенного для обработки, сформированный в результате работы подсистем фильтрации.
На выходе программы формируется описание сегментов линий изображения, позволяющее выполнять цепное кодирование, а также может быть использовано в других подсистемах.
П.1.6. Сообщения
Сообщения, выдаваемы при работе с программой и действия, которые необходимо выполнить при их получении, приведены в таблице П.1.1.
Таблица П.1.1
Сообщения, выдаваемые при работе программы и необходимые действия при их получении
Сообщение |
Описание |
Действия |
|
1 |
2 |
3 |
|
Размер нового изображения |
Программа предлагает выбрать размер вновь создаваемого изображения в точках |
Ввести значение ширины и высоты изображения |
|
Неверно указано число |
Введенное число не соответствует заданному формату |
Ввести корректное число |
|
Выход ? |
Запрос на подтверждение выхода из программы. Не сохраненные данные могут быть утеряны |
Подтвердить или опровергнуть запрос на выход |
|
Невозможно открыть файл |
Произошла ошибка при попытке открыть указанный файл |
Проверить наличие файла и доступа к нему |
|
Невозможно сохранить файл |
Произошла ошибка при попытке сохранить указанный файл |
Проверить наличие доступа к указанному пути. |
|
Файл уже существует. Перезаписать ? |
Файл с именем, указанным для сохранения, уже существует |
Подтвердить запрос на перезапись или выбрать другое имя файла |
|
Настройка |
Вызван диалог настройки программы |
Выполнить необходимые действия по настройке, затем нажать кнопку «ОК» для сохранения изменений или кнопку «Отмена» для их отмены |
|
Не выполнен поиск узлов |
При пошаговой обработке была вызвана процедура поиска сегментов прежде чем был выполнен поиск узлов |
Сначала необходимо выполнить поиск узлов, а затем выполнять поиск сегментов |
|
Не выполнен поиск сегментов |
При пошаговой обработке была вызвана процедура кодирования сегментов прежде чем был выполнен поиск сегментов |
Сначала необходимо выполнить поиск сегментов, а затем выполнять их кодирование |
П.1.7. Настройка программы
Для работы программы не требуется настройки дополнительных программных средств.
ПРИЛОЖЕНИЕ 2
РУКОВОДСТВО ОПЕРАТОРА
П.2.1. Назначение программы
Программа «Обработка и кодирование сегментов», обозначаемая как SegCode, предназначена для формирования кодов сегментов линий, содержащих координаты необходимых точек в зависимости от типа кодируемого сегмента. В процессе работы с программой осуществляется формирование массивов узлов и сегментов, на основании значений которых формируется код определенного сегмента. При этом учитываются типы узлов, а также типы кодируемых сегментов. Полученные результаты обработки могут быть выведены как на экран, так и в файл, и могут быть обработаны в других подсистемах.
Данная программа применяется в составе «Системы автоматизированного анализа пространственной структуры изображений».
П.2.2. Условия применения программы
При работе с программой необходимо обеспечить выполнение следующих требований к комплексу технических средств:
- персональный компьютер IBM PC с процессором не ниже Pentium I;
- клавиатура;
- монитор;
- жесткий диск с объемом свободного пространства не менее 50 МБ;
- оперативная память объемом не менее 128 МБ.
Работа программы возможна только на ЭВМ, которые поддерживают 32-разрядные операционные системы семейства Windows, такие как Windows 95, Windows NT или выше.
П.2.3. Пуск программы
Для вызова программы необходимо запустить на выполнения исполняемый файл lineseg.exe.
Запуск программы может быть произведен из командной строки любого файлового менеджера или из системного меню программ операционной системы, а также соответствующим ярлыком при его наличии.
П.2.4. Команды оператора
Для удобства доступа основные пункты меню дублируются соответствующими кнопками с аналогичными пиктограммами на панелях инструментов, а также могут быть доступны с помощью «горячих клавиш».
Ниже приведено описание пиктограмм с указанием в скобках «горячих клавиш»:
- Создать новый файл (F2);
- Открыть BMP-файл (F3);
- Открыть массив точек из файла (Ctrl+F3);
- Сохранить BMP-файл (F4);
- Сохранить массив точек в файл (Ctrl+F4);
- Сохранить код линий в файл (Shift+F4);
- Выполнить полную обработку изображения (F9);
- Выполнить поиск узлов (F5);
- Выполнить поиск сегментов линий (F6);
- Выполнить кодирование сегментов линий(F7);
- Уменьшить масштаб изображения (Ctrl+=);
- Увеличить масштаб изображения (Ctrl+-);
- Установить масштаб изображения 100% (Ctrl+1);
- Установить 10-кратное увеличение изображения (Ctrl+0);
- Установить масштаб изображения по размерам окна (Ctrl+\);
- Вкл/Выкл сетку (Ctrl+G);
- Вкл/Выкл подсветку сегментов (Ctrl+J);
- Вкл/Выкл подсветку узлов пересечений (Ctrl+K);
- Вкл/Выкл блокировку изображения (Ctrl+L);
- Показать окно настройки программы (F10);
Окно программы представлено на рис. П.2.1.
Окно программы
Рис. П.2.1
Для открытия файла, содержащего входное изображение следует выбрать в меню «Файл» пункт «Открыть файл» или «Загрузить массив» для получения изображения из файла формата BMP или файла массива точек соответственно (рис. П.2.2). Далее в диалоге выбора файла следует выбрать необходимый файл или ввести его имя и нажать кнопку «Открыть». После этого файл будет загружен и из него будет сформирован массив точек исходного изображения.
Меню «Файл»
Рис. П.2.2
При просмотре изображения для изменения масштаба следует воспользоваться элементами подменю «Масштаб» меню «Вид» (рис. П.2.3).
Для редактирования изображения следует воспользоваться манипулятором мышь. При нажатии левой кнопки на области изображения соответствующая точка изображения окрашивается в черный цвет, что соответствует наличию точки в массиве точек обрабатываемого изображения. При нажатии правой кнопки на области изображения соответствующая точка изображения будет окрашена в белый цвет, что соответствует отсутствию точки в массиве точек обрабатываемого изображения (рис. П.2.4). Данные действия схожи с действиями, выполняемыми при работе в любом графическом редакторе (например, Microsoft Paint)и не представляют особой сложности.
Подменю «Масштаб» меню «Вид»
Рис. П.2.3
Режим редактирования изображения
Рис. П.2.4
Для создания нового изображения следует использовать в меню «Файл» пункт «Новый». При этом будет вызван диалог, позволяющий задать необходимые размеры нового изображения (рис. П.2.5).
Выбор размера нового изображения
Рис. П.2.5
Обработка входного изображения может быть выполнена двумя способами:
- в режиме пошаговой обработки;
- в режиме полной обработки.
Доступ к режимам обработки изображения осуществляется с помощью пунктов меню «Обработка» (рис. П.2.6).
Выполнение анализа входного графического изображения в режиме пошаговой обработки позволяет поочередно выполнить сначала процедуру поиска узловых точек, затем процедуру поиска сегментов линий, а затем процедуру кодирования сегментов линий. Для выполнения данных действий следует воспользоваться соответствующими пунктами меню «Обработка» (рис. П.2.6).
Режим полной обработки позволяет последовательно автоматически выполнить поиск узлов, поиск сегментов и кодирование сегментов, получая на выходе результат, готовый для передачи в подсистему цепного кодирования. Для вызова обработки в данном режиме следует воспользоваться соответствующим пунктом меню «Обработка» (рис. П.2.6).
Меню «Обработка»
Рис. П.2.6
После выполнения обработки изображения ее результаты могут быть просмотрены на самом исходном изображении. Для этого следует воспользоваться пунктами-переключателями меню «Вид» (рис. П.2.7).
Пункт «Сетка» позволяет включить или выключить отображение сетки изображения при его увеличении.
Пункт «Подсветка линий» позволяет включить или выключить подсветку сегментов линий при наведении указателя мыши на различные области изображения (для данного режима требуется предварительное выполнение процедуры «Поиск сегментов»).
Пункт «Подсветка узлов» позволяет включить или выключить подсветку узлов при наведении указателя мыши на различные области изображения (для данного режима требуется предварительное выполнение процедуры «Поиск узлов»).
Пункт «Заблокировать вид» позволяет зафиксировать выделенные элементы изображения, не изменяя подсветку при перемещении курсора мыши в области изображения.
Меню «Вид»
Рис. П.2.7
Пример подсветки узла приведен на рис. П.2.8
Подсветка узла
Рис. П.2.8
Пример подсветки сегмента приведен на рис. П.2.9
Подсветка сегмента
Рис. П.2.9
В результате окончательной обработки изображения в области «Результат обработки» будут выведены коды, предназначенные для последующей передачи в подсистему цепного кодирования (рис. П.2.10). Данные результаты могут быть сохранены в файл. Для этого следует использовать пункт «Сохранить код» в меню «Файл».
Результат кодирования сегментов
Рис. П.2.10
После работы с изображением исходный массив точек может быть сохранен в файл, для этого следует воспользоваться пунктами «Сохранить массив» или «Сохранить файл» в меню «Файл» для сохранения в файл массива точек или в файл формата BMP соответственно. При выборе этих пунктов будет вызван стандартный диалог для сохранения файла, где следует указать имя сохраняемого файла и нажать кнопку «Сохранить».
После работы с программой для корректного ее завершения следует использовать пункт «Выход» в меню «Файл» (рис. П.2.11) или использовать стандартную пиктограмму закрытия окна. При этом будет выдан запрос на подтверждение выхода из программы (рис. П.2.12). Во избежание потери данных при выходе из программы следует убедиться, что все необходимые данные сохранены.
Выход из программы
Рис. П.2.11
Запрос на подтверждение выхода
Рис. П.2.12
П.2.5. Сообщения оператору
Сообщения, выдаваемые при работе с программой и действия, которые необходимо выполнить при их получении, приведены в таблице П.2.1.
Таблица П.2.1
Сообщения, выдаваемые при работе программы и необходимые действия при их получении
Сообщение |
Описание |
Действия |
|
1 |
2 |
3 |
|
Размер нового изображения |
Программа предлагает выбрать размер вновь создаваемого изображения в точках |
Ввести значение ширины и высоты изображения |
|
Неверно указано число |
Введенное число не соответствует заданному формату |
Ввести корректное число |
|
Выход ? |
Запрос на подтверждение выхода из программы. Не сохраненные данные могут быть утеряны |
Подтвердить или опровергнуть запрос на выход |
|
Невозможно открыть файл |
Произошла ошибка при попытке открыть указанный файл |
Проверить наличие файла и доступа к нему |
|
Невозможно сохранить файл |
Произошла ошибка при попытке сохранить указанный файл |
Проверить наличие доступа к указанному пути. |
|
Файл уже существует. Перезаписать ? |
Файл с именем, указанным для сохранения, уже существует |
Подтвердить запрос на перезапись или выбрать другое имя файла |
|
Настройка |
Вызван диалог настройки программы |
Выполнить необходимые действия по настройке, затем нажать кнопку «ОК» для сохранения изменений или кнопку «Отмена» для их отмены |
|
Не выполнен поиск узлов |
При пошаговой обработке была вызвана процедура поиска сегментов прежде чем был выполнен поиск узлов |
Сначала необходимо выполнить поиск узлов, а затем выполнять поиск сегментов |
|
Не выполнен поиск сегментов |
При пошаговой обработке была вызвана процедура кодирования сегментов прежде чем был выполнен поиск сегментов |
Сначала необходимо выполнить поиск сегментов, а затем выполнять их кодирование |
ПРИЛОЖЕНИЕ 3
ТЕКСТ ПРОГРАММЫ
П.3.1. Текст модуля lineseg.h
//---------------------------------------------------------------------------
#ifndef LineSegH
#define LineSegH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ActnList.hpp>
#include <Menus.hpp>
#include <Dialogs.hpp>
#include <Graphics.hpp>
#include <ExtCtrls.hpp>
#include <ComCtrls.hpp>
#include <ToolWin.hpp>
#include <ImgList.hpp>
#include <CustomizeDlg.hpp>
//---------------------------------------------------------------------------
class TfrmLineSeg : public TForm
{
__published: // IDE-managed Components
TStatusBar *sb1;
TPanel *Panel1;
TScrollBox *scb1;
TImage *Image1;
TImage *Image2;
TMainMenu *MainMenu1;
TMenuItem *N1;
TMenuItem *N3;
TMenuItem *N5;
TMenuItem *N4;
TMenuItem *N2;
TMenuItem *N6;
TMenuItem *N10;
TMenuItem *N11;
TMenuItem *N12;
TMenuItem *N1001;
TMenuItem *N10x1;
TMenuItem *N9;
TActionList *ActionList1;
TAction *actExit;
TAction *actOpenFile;
TAction *actSaveFile;
TAction *actNewFile;
TAction *actZoomIn;
TAction *actZoomOut;
TAction *actZoom1;
TAction *actZoom10;
TAction *actAnalyze;
TAction *actGridCheck;
TAction *actLightCheck;
TOpenDialog *OpenDialog1;
TSaveDialog *SaveDialog1;
TImageList *ImageList1;
TCoolBar *CoolBar1;
TToolBar *ToolBar1;
TToolBar *ToolBar2;
TToolBar *ToolBar3;
TToolButton *ToolButton1;
TToolButton *ToolButton2;
TToolButton *ToolButton3;
TToolButton *ToolButton4;
TToolButton *ToolButton5;
TToolButton *ToolButton6;
TToolButton *ToolButton7;
TToolButton *ToolButton8;
TToolButton *ToolButton13;
TToolButton *ToolButton14;
TAction *actLineLightCheck;
TToolButton *ToolButton11;
TToolButton *ToolButton10;
TAction *actSegLightCheck;
TSplitter *Splitter1;
TPanel *Panel2;
TMemo *MemoLog;
TMemo *MemoOut;
TSplitter *Splitter2;
TToolButton *ToolButton12;
TAction *actLockView;
TToolButton *ToolButton16;
TMenuItem *N8;
TMenuItem *N16;
TMenuItem *N17;
TMenuItem *N18;
TToolButton *ToolButton17;
TAction *actAnalyzeNode;
TAction *actAnalyzeSeg;
TToolButton *ToolButton9;
TAction *actMatchLines;
TToolButton *ToolButton18;
TToolButton *ToolButton20;
TAction *actZoomWnd;
TMenuItem *N19;
TToolButton *ToolButton21;
TAction *actMatchOut;
TMenuItem *N7;
TMenuItem *N22;
TAction *actOpenArray;
TAction *actSaveArray;
TMenuItem *N23;
TMenuItem *N24;
TToolButton *ToolButton22;
TToolButton *ToolButton23;
TMemo *mArray;
TAction *actOptions;
TMenuItem *N13;
TToolButton *ToolButton15;
TToolButton *ToolButton19;
TLabel *Label1;
TLabel *Label2;
TToolButton *ToolButton24;
TMenuItem *N14;
TAction *actSaveCode;
TMenuItem *N20;
TToolButton *ToolButton25;
TToolButton *ToolButton26;
TToolButton *ToolButton27;
TAction *actSegCodeOut;
TMenuItem *N15;
void __fastcall actExitExecute(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall actZoomInExecute(TObject *Sender);
void __fastcall actZoomOutExecute(TObject *Sender);
void __fastcall actOpenFileExecute(TObject *Sender);
void __fastcall actSaveFileExecute(TObject *Sender);
void __fastcall Image2MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y);
void __fastcall Image2MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall actZoom1Execute(TObject *Sender);
void __fastcall actAnalyzeExecute(TObject *Sender);
void __fastcall FormCanResize(TObject *Sender, int &NewWidth,
int &NewHeight, bool &Resize);
void __fastcall actNewFileExecute(TObject *Sender);
void __fastcall actGridCheckExecute(TObject *Sender);
void __fastcall actLightCheckExecute(TObject *Sender);
void __fastcall actZoom10Execute(TObject *Sender);
void __fastcall actLineLightCheckExecute(TObject *Sender);
void __fastcall actSegLightCheckExecute(TObject *Sender);
void __fastcall actLockViewExecute(TObject *Sender);
void __fastcall actAnalyzeNodeExecute(TObject *Sender);
void __fastcall actAnalyzeSegExecute(TObject *Sender);
void __fastcall actMatchLinesExecute(TObject *Sender);
void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
void __fastcall actZoomWndExecute(TObject *Sender);
void __fastcall actMatchOutExecute(TObject *Sender);
void __fastcall actOpenArrayExecute(TObject *Sender);
void __fastcall actSaveArrayExecute(TObject *Sender);
void __fastcall actOptionsExecute(TObject *Sender);
void __fastcall actSaveCodeExecute(TObject *Sender);
void __fastcall actSegCodeOutExecute(TObject *Sender);
private: // User declarations
void ZoomTo(double z);
void DrawGrid();
void ShowInfo(int X, int Y);
int __fastcall NeigCount(int x, int y);
int VectMove(int &x, int &y, int vect);
void wlog(AnsiString s);
AnsiString VectToStr(int v);
void ValidateView();
double plDistance(double x,double y,double x1,double y1,double x2,double y2);
// plDistance вычисляет расстояние (минимальное) от точки (x,y)
// до прямой, заданной точками (x1,y1) и (x2,y2)
AnsiString StrToLen(AnsiString str, int len);
// StrToLen возвражает строку длины len
// заполняя пробелями недостающие символы в начале строки str
void __fastcall NeigNode(int x, int y, int n);
// NeigSeg обрабатывает соседей точки (x,y)
// на принадлежность узлу n
// является рекурсивной
void __fastcall NeigLine(int x,int y, int n);
// NeigLine обрабатывает соседей точки (x,y)
// на продолжение линии n
// является рекурсивной
void __fastcall GetLineVect(int x,int y, int n);
// GetLineVect обрабатывает линию в код
// рекурсивная
TPoint NodeCentre(int n);
// NodeCentre возвращает центр узла n (координаты узловой точки)
void __fastcall FillLine(int n1, int n2);
// FillLine присваивает линии n2 пикселы линии n1 (объединение двух линий)
TPoint __fastcall FindMatch(int x, int y);
// FindMatch возвращает точку, соответствующую точке x,y
void __fastcall CodeLine(int x1,int y1,int x2,int y2);
// CodeLine добавляет в глобальную переменную linecode код для отрезка (x1,y1)-(x2,y2)
void __fastcall GetLineVect2(int x,int y, int n);
// GetLineVect2 обрабатывает линию в код
// рекурсивная
public:// User declarations
__fastcall TfrmLineSeg(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmLineSeg *frmLineSeg;
//---------------------------------------------------------------------------
#endif
П.3.2. Текст модуля lineseg.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "LineSeg.h"
#include "lsImgSize.h"
#include "lsOptions.h"
#include <math.h>
#include <values.h>
#include <io.h>
#include <fcntl.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PERFGRAP"
#pragma resource "*.dfm"
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
TfrmLineSeg *frmLineSeg;
double zoom,dzoom,maxzoom;
int w,h,def,defh,selline,selnode,oldselline,oldselnode,isnode;
const int maxw=1024,maxh=1024;
TColor c0,c1,c2,c3,c4,c21,c5;
bool logs; // вести журнал вычислений
int nodescnt,xs1,ys1,xs2,ys2,xs3,ys3;
AnsiString linecode; // содержит код текущей линии
// apix[i][j][0] - массив точек
// apix[i][j][1] - массив линий, номер линии
// apix[i][j][2] - массив узлов, номер узла
// -1 - пиксел не обработан, 0 - нет точки, >0 - номер линии, кот. принадлежит точка
// apix[i][j][3] - массив врЕменных атрибутов
int apix[maxw][maxh][4];
//---------------------------------------------------------------------------
__fastcall TfrmLineSeg::TfrmLineSeg(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actExitExecute(TObject *Sender)
{
frmLineSeg->Close();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::FormCreate(TObject *Sender)
{
scb1->Enabled=false;
logs=true;
zoom=1.0f; dzoom=1.0f;
maxzoom=100.0f;
selline=-1;
Image1->Left=0; Image1->Top=0;
Image2->Left=0; Image2->Top=0;
w=0; h=0;
c0=TColor(RGB(0,0,0)); c1=TColor(RGB(255,255,255));
c2=TColor(RGB(0,255,0)); c3=TColor(RGB(0,0,255));
c4=TColor(RGB(255,0,0)); c21=TColor(RGB(255,255,0));
c5=TColor(RGB(200,200,200));
for(int i=0;i<=maxw-1;i++)
for(int j=0;j<=maxh-1;j++)
{
apix[i][j][0]=0;
apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::FormCloseQuery(TObject *Sender, bool &CanClose)
{
CanClose=MessageBox(Handle,"Выход ?", "ЛС", MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)==ID_YES;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actZoomInExecute(TObject *Sender)
{
zoom+=dzoom;
ZoomTo(zoom);
DrawGrid();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actZoomOutExecute(TObject *Sender)
{
if(zoom>dzoom) zoom-=dzoom;
ZoomTo(zoom);
DrawGrid();
}
//---------------------------------------------------------------------------
void TfrmLineSeg::DrawGrid()
{
if(Image2->Visible)
{
Image2->Picture->Bitmap->Width=Image1->Width;
Image2->Picture->Bitmap->Height=Image1->Height;
Image2->Width=Image1->Width;
Image2->Height=Image1->Height;
Image2->Canvas->Pen->Color=c5;
Image2->Canvas->FillRect(Image2->ClientRect);
if(actGridCheck->Checked)
{
for(int i=1;i<=Image2->Height;i++)
{
Image2->Canvas->MoveTo(int(zoom*i),0);
Image2->Canvas->LineTo(int(zoom*i),Image2->Height);
}
for(int i=1;i<=Image2->Width;i++)
{
Image2->Canvas->MoveTo(0,int(zoom*i));
Image2->Canvas->LineTo(Image2->Width,int(zoom*i));
}
}
} // Image2->Visible
}
void __fastcall TfrmLineSeg::actOpenFileExecute(TObject *Sender)
{
OpenDialog1->Title="Открыть изображение";
OpenDialog1->Filter="Файлы изображений (*.bmp)|*.bmp|Все файлы (*.*)|*.*";
if(OpenDialog1->Execute())
{
sb1->SimplePanel=true; sb1->SimpleText="Открытие файла ...";
Image1->Picture->LoadFromFile(OpenDialog1->FileName);
Image1->Width=Image1->Picture->Bitmap->Width;
Image1->Height=Image1->Picture->Bitmap->Height;
w=Image1->Picture->Width;
h=Image1->Picture->Height;
scb1->Enabled=true;
ZoomTo(zoom);
for(int i=0;i<=w-1;i++) // maxw-1
for(int j=0;j<=h-1;j++) // maxh-1
{
apix[i][j][0]=Image1->Canvas->Pixels[i][j]==c0?1:0;
apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;
}
sb1->SimpleText=""; sb1->SimplePanel=false;
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actSaveFileExecute(TObject *Sender)
{
SaveDialog1->Filter="Файлы изображений (*.bmp)|*.bmp|Все файлы (*.*)|*.*";
SaveDialog1->DefaultExt="*.bmp";
SaveDialog1->Title="Сохранить изображение";
if(SaveDialog1->Execute())
{
Image1->Picture->SaveToFile(SaveDialog1->FileName);
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::Image2MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if (actLockView->Checked) return;
int ix=int(X/zoom),iy=int(Y/zoom);
if(Button==mbLeft)
{
if(Image1->Canvas->Pixels[ix][iy]!=c0)
{
Image1->Canvas->MoveTo(ix,iy);
Image1->Canvas->Pixels[ix][iy]=c0;
apix[ix][iy][0]=1;
}
}
else if(Button==mbRight)
{
if(Image1->Canvas->Pixels[ix][iy]!=c1)
{
Image1->Canvas->MoveTo(ix,iy);
Image1->Canvas->Pixels[ix][iy]=c1;
apix[ix][iy][0]=0;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::Image2MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
ShowInfo(X,Y);
if (actLockView->Checked) return;
int ix=int(X/zoom),iy=int(Y/zoom);
oldselline=selline;
oldselnode=selnode;
selline=apix[ix][iy][1];
selnode=apix[ix][iy][2];
TPoint p=NodeCentre(selnode);
if(Shift.Contains(ssLeft))
{
if(apix[ix][iy][0]!=1)
{
apix[ix][iy][0]=1;
Image1->Canvas->Pen->Color=c0;
Image1->Canvas->Pixels[ix][iy]=c0;
}
else
Image1->Canvas->MoveTo(ix,iy);
}
else if(Shift.Contains(ssRight))
{
if(apix[ix][iy][0]!=0)
{
apix[ix][iy][0]=0;
Image1->Canvas->Pen->Color=c1;
Image1->Canvas->Pixels[ix][iy]=c1;
}
else
Image1->Canvas->MoveTo(ix,iy);
}
if(actLineLightCheck->Checked && selline!=oldselline)
{
if(apix[ix][iy][1]>0) // есть линия
{
DrawGrid();
Image2->Canvas->Pen->Color=c2;
for(int i=0;i<w;i++) // выделяем линию
{
for(int j=0;j<h;j++)
{
if(apix[i][j][1]==selline) // линия
{
Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));
Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));
Image2->Canvas->LineTo(int(zoom*i),int(zoom*j));
if(NeigCount(i,j)==1) // начало линии
{
Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));
Image2->Canvas->MoveTo(int(zoom*(i+1)),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));
}
if(apix[i][j][2]>0) // пересечение линии с узлом
{
Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));
p=NodeCentre(apix[i][j][2]);
Image2->Canvas->Pen->Color=c4;
Image2->Canvas->MoveTo(int(zoom*p.x),int(zoom*p.y));
Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*p.y));
Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*(p.y+1)));
Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*(p.y+1)));
Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*p.y));
Image2->Canvas->Pen->Color=c2;
}
}
} // for j
} // for i
}
} // actLineLightCheck->Checked
if(actSegLightCheck->Checked && selnode!=oldselnode)
{
if(apix[ix][iy][2]>0) // есть узел
{
DrawGrid();
Image2->Canvas->Pen->Color=c3;
for(int i=0;i<w;i++) // выделяем узел
{
for(int j=0;j<h;j++)
{
if(apix[i][j][2]==selnode) // узел
{
Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));
Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));
Image2->Canvas->LineTo(int(zoom*i),int(zoom*j));
if(apix[i][j][1]>0) // пересечение узла с линией
{
Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));
Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));
}
}
} // for j
} // for i
//
Image2->Canvas->Pen->Color=c4;
Image2->Canvas->MoveTo(int(zoom*p.x),int(zoom*p.y));
Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*p.y));
Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*(p.y+1)));
Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*(p.y+1)));
Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*p.y));
}
} // actSegLightCheck->Checked
}
//---------------------------------------------------------------------------
void TfrmLineSeg::ShowInfo(int X,int Y)
{
unsigned char r,g,b;
int ix=int(X/zoom),iy=int(Y/zoom);
if (X>=0 && Y>=0)
{
sb1->Panels->Items[1]->Text=IntToStr(ix);
sb1->Panels->Items[3]->Text=IntToStr(h-1-iy);
r=Image1->Canvas->Pixels[ix][iy];
g=Image1->Canvas->Pixels[ix][iy] >>8;
b=Image1->Canvas->Pixels[ix][iy] >>16;
sb1->Panels->Items[5]->Text=IntToStr(r);
sb1->Panels->Items[7]->Text=IntToStr(g);
sb1->Panels->Items[9]->Text=IntToStr(b);
}
sb1->Panels->Items[11]->Text=IntToStr(int(zoom));
// if(apix[ix][iy][0]!=-1)
{
sb1->Panels->Items[13]->Text=IntToStr(apix[ix][iy][0]);
sb1->Panels->Items[15]->Text=IntToStr(apix[ix][iy][1]);
}
sb1->Panels->Items[17]->Text=IntToStr(apix[ix][iy][2]);
sb1->Panels->Items[19]->Text=IntToStr(apix[ix][iy][3]);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actZoom1Execute(TObject *Sender)
{
zoom=1.0f;
Image1->Width=Image1->Picture->Width;
Image1->Height=Image1->Picture->Height;
DrawGrid();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actAnalyzeExecute(TObject *Sender)
{
MemoLog->Clear();
actAnalyzeNodeExecute(Sender);
actAnalyzeSegExecute(Sender);
}
//---------------------------------------------------------------------------
int __fastcall TfrmLineSeg::NeigCount(int x, int y)
{
int n=0;
if(Image1->Canvas->Pixels[x-1][y-1]==c0 && x>0 && y>0) n+=1; // lu=1
if(Image1->Canvas->Pixels[x ][y-1]==c0 && y>0) n+=1; // u=2
if(Image1->Canvas->Pixels[x+1][y-1]==c0 && x<w && y>0) n+=1; // ru=3
if(Image1->Canvas->Pixels[x-1][y ]==c0 && x>0 ) n+=1; // l=4
if(Image1->Canvas->Pixels[x+1][y ]==c0 && x<w ) n+=1; // r=5
if(Image1->Canvas->Pixels[x-1][y+1]==c0 && x>0 && y<h) n+=1; // ld=6
if(Image1->Canvas->Pixels[x ][y+1]==c0 && y<h) n+=1; // d=7
if(Image1->Canvas->Pixels[x+1][y+1]==c0 && x<w && y<h) n+=1; // rd=8
return (n);
}
//---------------------------------------------------------------------------
int TfrmLineSeg::VectMove(int &x, int &y, int vect)
{
int res=0;
if(vect>0) wlog("VectMove: new point");
else if(vect<0 && vect>-10) wlog("VectMove: new node");
else if(vect<-10 && vect>-20) wlog("VectMove: existing node");
else wlog("VectMove: ERROR POINT");
int amvect=abs(vect) % 10;
switch(amvect)
{
// точка принадлежит линии
case 1: x-=1; y-=1; res=1; break;
case 2: y-=1; res=1; break;
case 3: x+=1; y-=1; res=1; break;
case 4: x-=1; res=1; break;
case 5: x+=1; res=1; break;
case 6: x-=1; y+=1; res=1; break;
case 7: y+=1; res=1; break;
case 8: x+=1; y+=1; res=1; break;
}
return res;
}
void __fastcall TfrmLineSeg::FormCanResize(TObject *Sender, int &NewWidth,
int &NewHeight, bool &Resize)
{
if(NewHeight<300) Resize=false;
}
//---------------------------------------------------------------------------
void TfrmLineSeg::ZoomTo(double z)
{
if(z<0.1) zoom=0.1f;
else if(z>maxzoom) zoom=maxzoom;
else zoom=z;
Image1->Width=int(Image1->Picture->Width*zoom);
Image1->Height=int(Image1->Picture->Height*zoom);
DrawGrid();
ShowInfo(-1,-1);
}
//---------------------------------------------------------------------------
AnsiString TfrmLineSeg::VectToStr(int v)
{
switch(v)
{
case 1:return ("LU");
case 2:return ("U");
case 3:return ("RU");
case 4:return ("L");
case 5:return ("R");
case 6:return ("LD");
case 7:return ("D");
case 8:return ("RD");
case -1:return ("LUn");
case -2:return ("Un");
case -3:return ("RUn");
case -4:return ("Ln");
case -5:return ("Rn");
case -6:return ("LDn");
case -7:return ("Dn");
case -8:return ("RDn");
default:return("");
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actNewFileExecute(TObject *Sender)
{
if(frmImgSize->ShowModal()==mrOk)
{
try
{
w=StrToInt(frmImgSize->edtWidth->Text);
h=StrToInt(frmImgSize->edtHeight->Text);
Image1->Picture->Bitmap->Width=w;
Image1->Picture->Bitmap->Height=h;
Image1->Width=w;
Image1->Height=h;
Image1->Canvas->FillRect(Image1->ClientRect);
zoom=1.0f;
scb1->Enabled=true;
for(int i=0;i<=w-1;i++) // maxw-1
for(int j=0;j<=h-1;j++) // maxh-1
{
apix[i][j][0]=Image1->Canvas->Pixels[i][j]==c0?1:0;
apix[i][j][1]=apix[i][j][2]=-1;
}
}
catch (...)
{
MessageBox(Handle,"Неверно указано число", "Ошибка", MB_OK);
}
DrawGrid();
ShowInfo(-1,-1);
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actGridCheckExecute(TObject *Sender)
{
ValidateView();
DrawGrid();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actLightCheckExecute(TObject *Sender)
{
ValidateView();
DrawGrid();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actZoom10Execute(TObject *Sender)
{
ZoomTo(10.0f);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actLineLightCheckExecute(TObject *Sender)
{
ValidateView();
DrawGrid();
}
//---------------------------------------------------------------------------
void TfrmLineSeg::wlog(AnsiString s)
{
if(logs)
if(s!="")
MemoLog->Lines->Add(s);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actSegLightCheckExecute(TObject *Sender)
{
ValidateView();
DrawGrid();
}
//---------------------------------------------------------------------------
void TfrmLineSeg::ValidateView()
{
Image2->Visible=actGridCheck->Checked
|| actLightCheck->Checked
|| actLineLightCheck->Checked
|| actSegLightCheck->Checked;
}
double TfrmLineSeg::plDistance(double x,double y,double x1,double y1,double x2,double y2)
{
double R=0.0f;
try
{
R=((y1-y2)*x+(x2-x1)*y+(x1*y2-x2*y1))/sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
catch(...)
{ }
return fabs(R);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actLockViewExecute(TObject *Sender)
{
ValidateView();
}
//---------------------------------------------------------------------------
AnsiString TfrmLineSeg::StrToLen(AnsiString str, int len)
{
AnsiString s=str;
while(s.Length()<len) s=" "+s;
return s;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::NeigNode(int x, int y, int n)
{
int i,j;
AnsiString s;
if(x<0 || y<0 || x>=w || y>=h) return; //если не принадлежит области изображения
if(apix[x][y][0]!=1) return; // если не является точкой
if(apix[x][y][2]!=-1) return; // если уже обработана на принадлежность узлу
if(NeigCount(x,y)<=2) return;// если мало соседей для сегментации
if(apix[x][y][2]==-1) // если точка не обработана
apix[x][y][2]=n; // точка будет принадлежать узлу n
// wlog(IntToStr(x)+","+IntToStr(y));
// обрабатываем ее соседей
NeigNode(x-1,y-1,n); NeigNode(x,y-1,n); NeigNode(x+1,y-1,n);
NeigNode(x-1,y ,n); NeigNode(x+1,y ,n);
NeigNode(x-1,y+1,n); NeigNode(x,y+1,n); NeigNode(x+1,y+1,n);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actAnalyzeNodeExecute(TObject *Sender)
{
sb1->SimplePanel=true; sb1->SimpleText="Поиск узлов ...";
AnsiString s;
TPoint p;
int i,j,x,y,x1,y1,x2,y2,ssize,nsegs, v,oldv;
for(i=0;i<=w-1;i++) // maxw-1
for(j=0;j<=h-1;j++) // maxh-1
apix[i][j][2]=-1;
i=0; j=0;
nsegs=0;
wlog("Поиск узлов ...");
while(j<h)
{
while(i<w)
{
if( apix[i][j][0]==1 // есть точка
&& apix[i][j][2]==-1 // не обработана на принадлежность узлу
&& NeigCount(i,j)>2 ) // является частью узла
{// начинаем выделение узла
nsegs+=1;
wlog("Найден узел №"+IntToStr(nsegs));
// wlog("Точки в области узла:");
NeigNode(i,j,nsegs); // обрабатываем точки вокруг узла
p=NodeCentre(nsegs);
wlog("Координаты узла: "+IntToStr(p.x)+","+IntToStr(h-1-p.y));
}
i+=1;
} // while i
i=0; j+=1;
} // while j
DrawGrid();
wlog("Поиск узлов завершен");
wlog("ВСЕГО УЗЛОВ: "+IntToStr(nsegs));
sb1->SimpleText=""; sb1->SimplePanel=false;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::NeigLine(int x,int y, int n)
{
int nc=NeigCount(x,y);
if(nc==1 || nc==2) // если начало или продолжение линии
{
apix[x][y][1]=n;
wlog(IntToStr(x)+","+IntToStr(h-1-y));
// если ( есть точка И не обработана на принадлежность линии )
if(apix[x-1][y-1][0]==1 && apix[x-1][y-1][1]==-1) NeigLine(x-1,y-1,n);
if(apix[x ][y-1][0]==1 && apix[x ][y-1][1]==-1) NeigLine(x ,y-1,n);
if(apix[x+1][y-1][0]==1 && apix[x+1][y-1][1]==-1) NeigLine(x+1,y-1,n);
if(apix[x-1][y ][0]==1 && apix[x-1][y ][1]==-1) NeigLine(x-1,y ,n);
if(apix[x+1][y ][0]==1 && apix[x+1][y ][1]==-1) NeigLine(x+1,y ,n);
if(apix[x-1][y+1][0]==1 && apix[x-1][y+1][1]==-1) NeigLine(x-1,y+1,n);
if(apix[x ][y+1][0]==1 && apix[x ][y+1][1]==-1) NeigLine(x ,y+1,n);
if(apix[x+1][y+1][0]==1 && apix[x+1][y+1][1]==-1) NeigLine(x+1,y+1,n);
}
else if(nc>2) // соединение с узлом
{
apix[x][y][1]=n;
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actAnalyzeSegExecute(TObject *Sender)
{
sb1->SimplePanel=true; sb1->SimpleText="Поиск сегментов линий ...";
AnsiString s;
int i,j,x,y,x1,y1,x2,y2,llen,nlines, v,oldv;
for(i=0;i<=w-1;i++) // maxw-1
for(j=0;j<=h-1;j++) // maxh-1
apix[i][j][1]=-1;
i=0; j=0;
nlines=0;
wlog("Поиск сегментов ...");
while(j<h)
{
while(i<w)
{
if( apix[i][j][0]==1 // есть точка
&& apix[i][j][1]==-1 // и она не обработана на принадлежность сегменту линии
&& (NeigCount(i,j)==1 // и является началом (1 сосед)
|| NeigCount(i,j)==2 )) // или продолжением линии (2 соседа)
{// начинаем выделение сегмента
nlines+=1;
wlog("Найден сегмент №"+IntToStr(nlines)+": ["+IntToStr(i)+","+IntToStr(h-1-j)+"]");
wlog("Точки сегмента:");
NeigLine(i,j,nlines); // обрабатываем сегмент линии
}
i+=1;
} // while i
i=0; j+=1;
} // while j
DrawGrid();
wlog("Поиск сегментов завершен");
wlog("ВСЕГО СЕГМЕНТОВ: "+IntToStr(nlines));
sb1->SimpleText=""; sb1->SimplePanel=false;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actMatchLinesExecute(TObject *Sender)
{
sb1->SimplePanel=true; sb1->SimpleText="Поиск линий ...";
int i,j,cline,cseg,x,y;
double dist,mindist;
TPoint p;
wlog("Поиск линий ...");
for(i=0;i<=w-1;i++) // maxw-1
for(j=0;j<=h-1;j++) // maxh-1
apix[i][j][3]=-1;
i=0; j=0;
while(j<h)
{
while(i<w)
{
if(apix[i][j][1]>0 && apix[i][j][2]>0 // есть соединение с сегментом
&& apix[i][j][3]==-1 // точка не обработана
)
{ // обрабатываем точку и выполняем поиск ей соответствующей
apix[i][j][3]=1;
cline=apix[i][j][1]; // текущая линия
cseg=apix[i][j][2]; // текущий сегмент
p=NodeCentre(cseg);
mindist=MAXDOUBLE;
x=y=-1;
wlog("Поиск соответствия фрагменту "+IntToStr(apix[i][j][1])+" ["+IntToStr(i)+","+IntToStr(j)+"]");
wlog("Центр сегмента "+IntToStr(cseg)+" ["+IntToStr(p.x)+","+IntToStr(p.y)+"]");
for(int j1=0;j1<h;j1++) // поиск точки соответствия
for(int i1=0;i1<w;i1++)
{
if(apix[i1][j1][0]==1 // есть точка
&& apix[i1][j1][3]==-1 // не обработана на соответствие линий
&& apix[i1][j1][1]>0 && apix[i1][j1][2]==cseg // является пересечением этого сегмента с одной из линий
)
{
if((dist=plDistance(p.x,p.y,i,j,i1,j1))<=mindist) // если образует наименьшее отклонение от центра сегмента
{ // запоминаем точку как самую подходящую
x=i1; y=j1;
mindist=dist;
wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - соотв.:"+FloatToStr(dist));
}
else
{
wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - не соотв:"+FloatToStr(dist));
}
}
}
if(x>0 && y>0)
{
wlog("Найдено соответствие фрагментов: "+IntToStr(cline)+" и "+IntToStr(apix[x][y][1]));
apix[x][y][3]=1; // точка обработана
FillLine(apix[x][y][1],cline); // заполняем линию
}
}
i+=1;
} // while i
i=0; j+=1;
} // while j
DrawGrid();
wlog("Line matching end");
sb1->SimpleText=""; sb1->SimplePanel=false;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::FillLine(int n1, int n2)
{
for(int i=0;i<=w-1;i++) // maxw-1
for(int j=0;j<=h-1;j++) // maxh-1
if(apix[i][j][1]==n1) apix[i][j][1]=n2;
}
//---------------------------------------------------------------------------
TPoint TfrmLineSeg::NodeCentre(int n)
{
int i=0, j=0, cnt=0, xsum=0, ysum=0,x=0,y=0;
while(j<h)
{
while(i<w)
{
if( apix[i][j][2]==n // точка принадлежит этому узлу
// && apix[i][j][1]>0 // есть пересечение с линией
)
{
xsum+=i;
ysum+=j;
cnt+=1;
}
i+=1;
} // while i
i=0; j+=1;
} // while j
if(cnt>0)
{
x=xsum/cnt;
y=ysum/cnt;
}
return Point(x,y);
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actZoomWndExecute(TObject *Sender)
{
if(w>0 || h>0)
{
zoom=min(scb1->Width,scb1->Height)/max(w,h);
ZoomTo(zoom);
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::GetLineVect(int x,int y,int n)
{
TPoint p;
if(apix[x][y][1]==n && apix[x][y][3]==-1) // принадлежит этой линии и не обработана в код
{
// обработка текущей точки
apix[x][y][3]=1;
if(linecode=="")
linecode+=IntToStr(x)+","+IntToStr(y);
else
linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);
// обрабтка продолжения линии
if(apix[x][y][2]>0) // если пересечение с сегментом
{// обработка линии внутри сегмента
p=FindMatch(x,y);
CodeLine(x,y,p.x,p.y); // вывод кода линии внутри сегмента
x=p.x;
y=p.y;
apix[x][y][3]=1;
if(linecode=="")
linecode+=IntToStr(x)+","+IntToStr(y);
else
linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);
}
GetLineVect(x-1,y-1,n); GetLineVect(x,y-1,n); GetLineVect(x+1,y-1,n);
GetLineVect(x-1,y ,n); GetLineVect(x+1,y ,n);
GetLineVect(x-1,y+1,n); GetLineVect(x,y+1,n); GetLineVect(x+1,y+1,n);
}
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::CodeLine(int x1,int y1,int x2,int y2)
{
wlog("Кодирование линии ["+IntToStr(x1)+","+IntToStr(h-1-y1)+"]-["+IntToStr(x2)+","+IntToStr(h-1-y2)+"]:");
if(abs(x1-x2)>abs(y1-y2)) // точек по x больше
{
wlog("Цикл по оси x. Точки линии:");
int x, y, xa=min(x1,x2), xb=max(x1,x2);
double k=double(y2-y1)/(x2-x1), b=y1-x1*k;
x=xa+1;
while(x<xb)
{
y=k*x+b;
if(linecode=="")
linecode+=IntToStr(x)+","+IntToStr(h-1-y);
else
linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);
wlog(IntToStr(x)+","+IntToStr(h-1-y));
x+=1;
}
}
else // точек по y больше
{
wlog("Цикл по оси y. Точки линии:");
int x, y, ya=min(y1,y2), yb=max(y1,y2);
double k=double(x2-x1)/(y2-y1), b=x1-y1*k;
y=ya+1;
while(y<yb)
{
x=k*y+b;
if(linecode=="")
linecode+=IntToStr(x)+","+IntToStr(h-1-y);
else
linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);
wlog(IntToStr(x)+","+IntToStr(h-1-y));
y+=1;
}
}
}
//---------------------------------------------------------------------------
TPoint __fastcall TfrmLineSeg::FindMatch(int x, int y)
{
int i,j;
TPoint p;
p.x=x;
p.y=y;
i=0; j=0;
while(j<h)
{
while(i<w)
{
if(apix[i][j][1]==apix[x][y][1] // если принадлежит той же линии
&& apix[i][j][2]==apix[x][y][2] // и принадлежит тому же сегменту
&& (i!=x || j!=y) // и это другая точка
)
{ // это искомая точка
p.x=i;
p.y=j;
}
i+=1;
} // while i
i=0; j+=1;
} // while j
return p;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLineSeg::actMatchOutExecute(TObject *Sender)
{
int i,j,lineno,lnum;
sb1->SimplePanel=true; sb1->SimpleText="Вывод кода линий ...";
for(j=0;j<h;j++) // инициализация массива временных атрибутов
for(i=0;i<w;i++)
apix[i][j][3]=-1;
MemoOut->Clear();
lnum=0;
for(j=0;j<h;j++)
for(i=0;i<w;i++)
{
if( apix[i][j][1]>0// есть линия
&& apix[i][j][3]==-1 // и она не обработана
&& (NeigCount(i,j)==1 // точка является началом линии
|| apix[i][j][2]>0) // или узлом
)
{ // формируем код для этой линии
lineno=apix[i][j][1];
lnum+=1;
linecode="";
GetLineVect(i,j,lineno);
MemoOut->Lines->Add(IntToStr(lnum)+":"+linecode);
wlog(IntToStr(lnum)+"(line #"+IntToStr(lineno)+"):"+linecode);
}
}
sb1->SimpleText=""; sb1->SimplePanel=false;
}
//---------------------------------------------------------------------------
Подобные документы
Современные системы текстурного анализа изображений. Примеры текстурной сегментации одноканальных изображений. Использование признаков, полученных на основе гистограммы яркостей второго порядка, для классификации спектрозональных аэрофотоснимков.
реферат [573,5 K], добавлен 15.01.2017Исследование вертикальных проекций яркости и размаха яркости. Программная реализация алгоритма автоматического анализа цифровых изображений номерных знаков с целью сегментации цифробуквенных символов. Разработка графического пользовательского интерфейса.
дипломная работа [1,5 M], добавлен 12.04.2013Компьютерная графика как одно из популярных направлений использования компьютера, ее виды и особенности применения. Порядок и способы создания цифровых изображений, средства и обработка. Программы САПР и их использование в инженерной деятельности.
реферат [19,1 K], добавлен 14.09.2009Компьютерная графика как наука, предметом изучения которой является создание, хранение и обработка моделей и их изображений с помощью ЭВМ. Области применения графических редакторов: Adobe Photoshop и Illustrator, Corel Draw. Растровая и векторная графика.
презентация [31,7 M], добавлен 17.01.2012Выбор методов обработки и сегментации изображений. Математические основы примененных фильтров. Гистограмма яркости изображения. Программная реализация комплексного метода обработки изображений. Тестирование разработанного программного обеспечения.
курсовая работа [1,3 M], добавлен 18.01.2017Изучение и программная реализация в среде Matlab методов обработки, анализа, фильтрации, сегментации и улучшения качества рентгеновских медицинских изображений. Цифровые рентгенографические системы. Разработка статически обоснованных алгоритмов.
курсовая работа [4,7 M], добавлен 20.01.2016Требования, состав задач, критерии функционирования, условия и программно-технические требования. Программа центроидной релаксации: математическая постановка, алгоритмы вычисления кольцевой фильтр, центр масс, кривизны. Безопасность, экологичность.
дипломная работа [1,4 M], добавлен 28.05.2008Обработка изображений на современных вычислительных устройствах. Устройство и представление различных форматов изображений. Исследование алгоритмов обработки изображений на базе различных архитектур. Сжатие изображений на основе сверточных нейросетей.
дипломная работа [6,1 M], добавлен 03.06.2022Компьютерная графика как инструмент для синтеза (создания) изображений. Характеристика векторного, растрового и фрактального типов представления изображений, трёхмерная графика. Интерфейс программы "Photoshop", пример работы по коррекции фотографий.
курсовая работа [4,5 M], добавлен 19.01.2011Анализ и постановка задач дисциплины "Компьютерная графика". Разработка структуры, функциональной схемы и программной документации. Руководство программисту и оператору. Выбор и обоснование языка программирования. Описание процедур, функций, оценок.
дипломная работа [3,6 M], добавлен 16.11.2011