Разработка редактора растровых изображений
Анализ влияния сглаживающего шума на различные категории томографических изображений. Разработка программного обеспечения для снижения помех и увеличения четкости очертаний крупных объектов. Метод рисования прямоугольников, ограничивающих все контуры.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | практическая работа |
Язык | русский |
Дата добавления | 28.09.2019 |
Размер файла | 1006,7 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://allbest.ru
Задание на практику
1. Подготовить исходные данные (изображения) для проведения эксперимента;
2. Написать программное обеспечение, выполняющее:
- открытие исходных изображений;
- выполнение необходимых операций над ними: наложение шума методом адаптивного сглаживания, бинаризация по методу итерационного поиска порога, выделение контуров по методу однородного края;
- подсчет числа получившихся объектов и их геометрических характеристик.
3. Провести эксперимент и зафиксировать его результаты.
4. Проанализировать результаты эксперимента.
Выполнение заданий
1. Исходные данные представляют собой файлы специального формата (NIFTI) - серии изображений компьютерной томографии органов человека. Для проведения эксперимента взяли по одному изображению из пяти категорий: Легкое, Печень, Селезенка, Сердце, Толстая кишка. Для преобразования файлов из формата nii в png было использовано специальное программное обеспечение Aliza.
2. Программное обеспечение было написано с использованием библиотек машинного зрения АForge.Net. Оно позволяет загружать из файлов и просматривать исходные изображения, а также изображения с шумом, изображения, полученные в результате бинаризации и в результате выделения контуров. Для текущего просматриваемого изображения можно в таблицу вывести все его контура и их геометрические характеристики. Для анализа результатов эксперимента программа выводит графики зависимости таких характеристик как количество контуров, суммы площадей контуров и суммы периметров контуров от номера изображения для исходных изображений и изображений с шумом (рисунки 4 - 8).
Ниже приведен текст программы
программный шум четкость изображение
XAML - разметка основного окна программы
<Window x:Class="НИР.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:НИР"
mc:Ignorable="d"
Title="НИР" Height="600" Width="1000"
Icon="Resources/Icon.png"
WindowStartupLocation="CenterScreen" MinWidth="600" MinHeight="400">
<Grid Background="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}">
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<Menu>
<MenuItem Header="Выбор папки с изображениями" Click="Load_Click"/>
<MenuItem x:Name="Parameters" Header="Параметры контуров" IsEnabled="False" Click="Parameters_Click"/>
<MenuItem x:Name="Analiz" Header="Анализ результатов" IsEnabled="False" Click="Analiz_Click"/>
</Menu>
</StackPanel>
<Grid DockPanel.Dock="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Slider Grid.Column="0" Margin="10"
Value="{Binding Val, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Maximum="{Binding Max, Mode=OneWay}"
Minimum="1" ValueChanged="Slider_ValueChanged"/>
<TextBox Grid.Column="1"
IsReadOnly="True"
Margin="10"
Text="{Binding Val}"/>
</Grid>
<TabControl DockPanel.Dock="Left">
<TabControl.Resources>
<ControlTemplate x:Key="ImageItem" TargetType="{x:Type Label}">
<Canvas x:Name="MyCanvas" ToolTip="{Binding FileName, Mode=OneWay}" MouseUp="MyCanvas_MouseUp">
<Canvas.Background>
<ImageBrush ImageSource="{Binding BlobImage, UpdateSourceTrigger=PropertyChanged}" Stretch="Uniform"/>
</Canvas.Background>
</Canvas>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding ="{Binding ElementName = dataGrid, Path = SelectedIndex}" Value ="-1"/>
<Condition Binding ="{Binding ElementName = NoiceDataGrid, Path = SelectedIndex}" Value ="-1"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="MyCanvas" Property="Background">
<Setter.Value>
<ImageBrush ImageSource="{Binding FileName, UpdateSourceTrigger=PropertyChanged}" Stretch="Uniform"/>
</Setter.Value>
</Setter>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="DataGrid">
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="RowHeaderWidth" Value="0"/>
</Style>
</TabControl.Resources>
<TabItem x:Name="Image" Header="Исходное избражение" GotFocus="Image_GotFocus">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TabControl Grid.Column="0">
<TabItem x:Name="OriginalImage" Header="Оригинал" GotFocus="Original_GotFocus">
<Label Template="{DynamicResource ImageItem}"/>
</TabItem>
<TabItem x:Name="BinaryImage" Header="Бинарное" GotFocus="Binary_GotFocus">
<Label Template="{DynamicResource ImageItem}"/>
</TabItem>
<TabItem x:Name="ContourImage" Header="Контуры" GotFocus="Contour_GotFocus">
<Label x:Name="ContourLabel" Template="{DynamicResource ImageItem}" SizeChanged="ContourLabel_SizeChanged"/>
</TabItem>
</TabControl>
<DataGrid Grid.Column="1" ItemsSource="{Binding BlobList}" x:Name="dataGrid" SelectionChanged="DataGrid_SelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn CanUserSort="False" Header="Контур">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Bmp}" Width="100" Height="100"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Area}" CanUserSort="False" Header="Площадь"/>
<DataGridTextColumn Binding="{Binding Perimeter}" CanUserSort="False" Header="Периметр"/>
<DataGridTextColumn Binding="{Binding CenterOfGravity}" CanUserSort="False" Header="Центр тяжести"/>
<DataGridTextColumn Binding="{Binding Fullness}" CanUserSort="False" Header="Наполненность"/>
<DataGridTextColumn Binding="{Binding Width}" CanUserSort="False" Header="Ширина"/>
<DataGridTextColumn Binding="{Binding Height}" CanUserSort="False" Header="Высота"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</TabItem>
<TabItem x:Name="NoiceImage" Header="Изображение с шумом" GotFocus="Noice_GotFocus">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TabControl>
<TabItem x:Name="NoiceOriginalImage" Header="Оригинал" GotFocus="Noice_Original_GotFocus">
<Label Template="{DynamicResource ImageItem}"/>
</TabItem>
<TabItem x:Name="NoiceBinaryImage" Header="Бинарное" GotFocus="Noice_Binary_GotFocus">
<Label Template="{DynamicResource ImageItem}"/>
</TabItem>
<TabItem x:Name="NoiceContourImage" Header="Контуры" GotFocus="Noice_Contour_GotFocus">
<Label x:Name="NoiceContourLabel" Template="{DynamicResource ImageItem}" SizeChanged="NoiceContourLabel_SizeChanged"/>
</TabItem>
</TabControl>
<DataGrid Grid.Column="1" ItemsSource="{Binding BlobList}" x:Name="NoiceDataGrid" SelectionChanged="NoiceDataGrid_SelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn CanUserSort="False" Header="Контур">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Bmp}" Width="100" Height="100"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Area}" CanUserSort="False" Header="Площадь"/>
<DataGridTextColumn Binding="{Binding Perimeter}" CanUserSort="False" Header="Периметр"/>
<DataGridTextColumn Binding="{Binding CenterOfGravity}" CanUserSort="False" Header="Центр тяжести"/>
<DataGridTextColumn Binding="{Binding Fullness}" CanUserSort="False" Header="Наполненность"/>
<DataGridTextColumn Binding="{Binding Width}" CanUserSort="False" Header="Ширина"/>
<DataGridTextColumn Binding="{Binding Height}" CanUserSort="False" Header="Высота"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</TabItem>
</TabControl>
</DockPanel>
</Grid>
</Window>
Обработчик событий основного окна программы
namespace НИР
{
/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Processing Proc, NoiseProc; // Объекты обработки изображений
public MainWindow()
{
InitializeComponent();
DataContext = new ViewClass();
}
// Обработка выбора папки с файлами
private void Load_Click(object sender, RoutedEventArgs e)
{
// Выбор каталога с изображениями в диалоговом окне
FolderBrowserDialog FBD = new FolderBrowserDialog();
if (FBD.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
((ViewClass)DataContext).FileName = null;
// Создание объекта обработки исходных изображений
Proc = new Processing(FBD.SelectedPath);
// Подписка на событие ошибки
Proc.OnException += Proc_OnException;
// Запуск обработки исходных изображений
Proc.Run();
// Создание каталога изображений с шумом
string path = Proc.GetNoiseImages();
// Создание объекта обработки изображений с шумом
NoiseProc = new Processing(path);
// Подписка на событие ошибки
NoiseProc.OnException += Proc_OnException;
// Запуск обработки изображений с шумом
NoiseProc.Run();
// Отображение первого изображения в каталоге
((ViewClass)DataContext).Val = 1;
((ViewClass)DataContext).Max = Proc.Filenames.Count;
((ViewClass)DataContext).FileName = Proc.Filenames[0];
Image.IsSelected = true;
OriginalImage.IsSelected = true;
System.Windows.MessageBox.Show("Для просмотра всех изображений выберите " +
"соответствующую вкладку и перемещайте ползунок");
Parameters.IsEnabled = true;
Analiz.IsEnabled = true;
}
}
// Обработка вычисления параметров контуров
private void Parameters_Click(object sender, RoutedEventArgs e)
{
if (Image.IsSelected)
{
ContourImage.Focus();
Proc.GetBlobs(((ViewClass)DataContext).FileName);
((ViewClass)DataContext).BlobList = Proc.BlobsParameters;
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
DrawRectangles(can, Proc);
}
else
{
NoiceContourImage.Focus();
NoiseProc.GetBlobs(((ViewClass)DataContext).FileName);
((ViewClass)DataContext).BlobList = NoiseProc.BlobsParameters;
Canvas can = (Canvas) NoiceContourLabel.Template.FindName("MyCanvas", NoiceContourLabel);
DrawRectangles(can, NoiseProc);
}
}
// Метод рисования прямоугольника ограничивающего контур на холсте
private void DrawRectangle(Canvas can, BlobParameters bp)
{
// Вычисление положения и размеров прямоугольника
double ww = can.ActualWidth,
hw = can.ActualHeight,
wi = bp.Bmp.Width,
hi = bp.Bmp.Height,
x = 0,
y = 0,
w = 0,
h = 0;
if (hw / ww >= hi / wi)
{
x = ww * bp.X / wi;
y = (hw - ww * hi / wi) / 2 + ww * bp.Y / wi;
w = ww * bp.Width / wi;
h = ww * bp.Height / wi;
}
else
{
y = hw * bp.Y / hi;
x = (ww - hw * wi / hi) / 2 + hw * bp.X / hi;
w = hw * bp.Width / hi;
h = hw * bp.Height / hi;
}
// Создание объекта прямоугольника
Rectangle rect = new Rectangle()
{
Width = w,
Height = h,
Stroke = Brushes.Blue
};
// Помещение прямоугольника на холст
can.Children.Add(rect);
Canvas.SetLeft(rect, x);
Canvas.SetTop(rect, y);
}
// Метод рисования прямоугольников ограничивающих все контуры
private void DrawRectangles(Canvas can, Processing proc)
{
if (can != null)
{
can.Children.Clear();
if (proc.BlobsParameters != null)
foreach (BlobParameters bp in proc.BlobsParameters)
{
DrawRectangle(can, bp);
}
}
}
#region Обработчики выбора вкладок
private void Original_GotFocus(object sender, RoutedEventArgs e)
{
if(Proc!=null)
((ViewClass)DataContext).FileName =
Proc.Filenames[((ViewClass)DataContext).Val-1];
dataGrid.SelectedIndex = -1;
NoiceDataGrid.SelectedIndex = -1;
}
private void Binary_GotFocus(object sender, RoutedEventArgs e)
{
if (Proc != null)
{
string path = Proc.SelectedPath + "\\Binary";
((ViewClass)DataContext).FileName =
Proc.Filenames[((ViewClass)DataContext).Val - 1]
.Replace(Proc.SelectedPath, path);
}
dataGrid.SelectedIndex = -1;
NoiceDataGrid.SelectedIndex = -1;
}
private void Contour_GotFocus(object sender, RoutedEventArgs e)
{
if (Proc != null)
{
string path = Proc.SelectedPath + "\\Contour";
((ViewClass)DataContext).FileName =
Proc.Filenames[((ViewClass)DataContext).Val - 1]
.Replace(Proc.SelectedPath, path);
// Рисование прямоугольников
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
DrawRectangles(can, Proc);
}
}
private void Noice_Original_GotFocus(object sender, RoutedEventArgs e)
{
if (NoiseProc != null)
((ViewClass)DataContext).FileName =
NoiseProc.Filenames[((ViewClass)DataContext).Val-1];
dataGrid.SelectedIndex = -1;
NoiceDataGrid.SelectedIndex = -1;
}
private void Noice_Binary_GotFocus(object sender, RoutedEventArgs e)
{
if (NoiseProc != null)
{
string path = NoiseProc.SelectedPath + "\\Binary";
((ViewClass)DataContext).FileName =
NoiseProc.Filenames[((ViewClass)DataContext).Val - 1]
.Replace(NoiseProc.SelectedPath, path);
}
dataGrid.SelectedIndex = -1;
NoiceDataGrid.SelectedIndex = -1;
}
private void Noice_Contour_GotFocus(object sender, RoutedEventArgs e)
{
if (NoiseProc != null)
{
string path = NoiseProc.SelectedPath + "\\Contour";
((ViewClass)DataContext).FileName =
NoiseProc.Filenames[((ViewClass)DataContext).Val - 1]
.Replace(NoiseProc.SelectedPath, path);
// Рисование прямоугольников
Canvas can = (Canvas) NoiceContourLabel.Template.FindName ("MyCanvas", NoiceContourLabel);
DrawRectangles(can, NoiseProc);
}
}
private void Image_GotFocus(object sender, RoutedEventArgs e)
{
if (Proc != null)
{
((ViewClass)DataContext).BlobList = Proc.BlobsParameters;
// Рисование прямоугольников
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
DrawRectangles(can, Proc);
}
}
private void Noice_GotFocus(object sender, RoutedEventArgs e)
{
if (NoiseProc != null)
{
((ViewClass)DataContext).BlobList = NoiseProc.BlobsParameters;
// Рисование прямоугольников
Canvas can = (Canvas) NoiceContourLabel.Template.FindName ("MyCanvas", NoiceContourLabel);
DrawRectangles(can, NoiseProc);
}
}
#endregion
// Обработка выбора контура без шума в таблице
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((ViewClass)DataContext).BlobList != null && dataGrid.SelectedIndex >= 0)
{
((ViewClass)DataContext).BlobImage = ((ViewClass)DataContext).BlobList[dataGrid.SelectedIndex].Bmp;
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
if (can != null)
{
can.Children.Clear();
if (Proc.BlobsParameters != null)
DrawRectangle(can, ((ViewClass)DataContext).BlobList[dataGrid.SelectedIndex]);
}
}
}
// Обработка выбора контура с шумом в таблице
private void NoiceDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((ViewClass)DataContext).BlobList != null && NoiceDataGrid.SelectedIndex >= 0)
{
((ViewClass)DataContext).BlobImage = ((ViewClass)DataContext).BlobList[NoiceDataGrid.SelectedIndex].Bmp;
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", NoiceContourLabel);
if (can != null)
{
can.Children.Clear();
if (NoiseProc.BlobsParameters != null)
DrawRectangle(can, ((ViewClass)DataContext).BlobList[NoiceDataGrid.SelectedIndex]);
}
}
}
// Обработка клика по окну с изображением
// Сброс выбранного в таблице контура
private void MyCanvas_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
dataGrid.SelectedIndex = -1;
NoiceDataGrid.SelectedIndex = -1;
// Рисование прямоугольников
if (Image.IsSelected)
{
if (Proc != null)
{
Canvas can = (Canvas) ContourLabel.Template.FindName("MyCanvas", ContourLabel);
DrawRectangles(can, Proc);
}
}
else
{
if (NoiseProc != null)
{
Canvas can = (Canvas) NoiceContourLabel.Template.FindName("MyCanvas", NoiceContourLabel);
DrawRectangles(can, NoiseProc);
}
}
}
// Смена изображений на текущей вкладке при движении ползунка
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (Image != null && ((ViewClass)DataContext).FileName != null)
{
string oldFile = ((ViewClass)DataContext).FileName;
string newFile = Proc.Filenames[((ViewClass)DataContext).Val - 1];
newFile = oldFile.Substring(0, oldFile.LastIndexOf('\\'))
+ newFile.Substring(newFile.LastIndexOf('\\'));
((ViewClass)DataContext).FileName = newFile;
Proc.ClearStat();
NoiseProc.ClearStat();
((ViewClass)DataContext).BlobList = null;
// Очистка холстов от прямоугольников
Canvas can;
can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
if (can != null)
can.Children.Clear();
can = (Canvas)NoiceContourLabel.Template.FindName("MyCanvas", NoiceContourLabel);
if (can != null)
can.Children.Clear();
}
}
// Вызов окна графического анализа параметров контуров
private void Analiz_Click(object sender, RoutedEventArgs e)
{
Proc.GetAnalize();
NoiseProc.GetAnalize();
Analize NewWindow = new Analize(Proc.AnalizeResults, NoiseProc.AnalizeResults)
{
Owner = this
};
NewWindow.ShowDialog();
}
// Обработка изменения размеров области для рисования контура без шума
private void ContourLabel_SizeChanged(object sender, SizeChangedEventArgs e)
{
if(Image.IsSelected && ContourImage.IsSelected)
{
if (Proc != null)
{
Canvas can = (Canvas)ContourLabel.Template.FindName("MyCanvas", ContourLabel);
if (dataGrid.SelectedIndex < 0)
DrawRectangles(can, Proc);
else
{
if (can != null)
{
can.Children.Clear();
if (Proc.BlobsParameters != null)
DrawRectangle(can, ((ViewClass)DataContext).BlobList[dataGrid.SelectedIndex]);
}
}
}
}
}
// Обработка изменения размеров области для рисования контура с шумом
private void NoiceContourLabel_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (NoiceImage.IsSelected && NoiceContourImage.IsSelected)
{
if (NoiseProc != null)
{
Canvas can = (Canvas)NoiceContourLabel.Template.FindName("MyCanvas", NoiceContourLabel);
if (NoiceDataGrid.SelectedIndex < 0)
DrawRectangles(can, NoiseProc);
else
{
if (can != null)
{
can.Children.Clear();
if (NoiseProc.BlobsParameters != null)
DrawRectangle(can, ((ViewClass)DataContext).BlobList[NoiceDataGrid.SelectedIndex]);
}
}
}
}
}
// Обработка ошибок в объектах обработки изображений
private void Proc_OnException(string Message)
{
System.Windows.MessageBox.Show(Message);
}
}
}
Класс обработки изображений
namespace НИР
{
public delegate void OnExceptionHandler(string text);
// Класс обработки изображений
public class Processing
{
private List<string> filenames; // Список обрабатываемых файлов
private string selectedPath; // Текущий каталог с файлами
private List<BlobParameters> blobsParameters;
private List<AnalizeResult> analizeResults;
#region Public properties
public List<string> Filenames
{ get { return filenames; } }
public string SelectedPath
{ get { return selectedPath; } }
public List<BlobParameters> BlobsParameters
{ get { return blobsParameters; } }
public List<AnalizeResult> AnalizeResults
{ get { return analizeResults; } }
#endregion
// Конструктор
public Processing(string path)
{
filenames = Directory.GetFiles(path, "*.png").ToList();
selectedPath = path;
}
// Метод запуска обработки изображений
public void Run()
{
// Создание каталогов для бинарных изображений и контуров
string path = selectedPath + "\\Binary";
Directory.CreateDirectory(path);
path = selectedPath + "\\Contour";
Directory.CreateDirectory(path);
path = selectedPath;
try
{
foreach (string filename in filenames)
{
if (!File.Exists(filename.Replace(selectedPath, selectedPath + "\\Binary")) &&
!File.Exists(filename.Replace(selectedPath, selectedPath + "\\Contour")))
{
// Создание объектов фильтров
Grayscale filterGray = new Grayscale(0.2125, 0.7154, 0.0721);
GrayscaleToRGB filterRGB = new GrayscaleToRGB();
IterativeThreshold binary = new IterativeThreshold();
HomogenityEdgeDetector contour = new HomogenityEdgeDetector();
// Считывание изображения из файла
Bitmap image = new Bitmap(filename);
// Получение бинарного изображений
Bitmap binaryImage = binary.Apply(filterGray.Apply(image));
// Получение контура
Bitmap contourImage = contour.Apply(binaryImage);
// Сохранение бинарного изображения
path = selectedPath + "\\Binary";
image = filterRGB.Apply(binaryImage);
binaryImage.Dispose();
image.Save(filename.Replace(selectedPath, path),
System.Drawing.Imaging.ImageFormat.Png);
// Сохранение контура
path = selectedPath + "\\Contour";
image = filterRGB.Apply(contourImage);
contourImage.Dispose();
image.Save(filename.Replace(selectedPath, path),
System.Drawing.Imaging.ImageFormat.Png);
image.Dispose();
// Периодическая очистка памяти
if (GC.GetTotalMemory(true) > 1000000000) GC.Collect();
}
}
}
catch (Exception ex)
{
OnException(ex.Message);
}
}
// Метод создания каталога изображений с шумом
public string GetNoiseImages()
{
// Создание каталога для изображений с шумом
string path = selectedPath + "\\Noise";
Directory.CreateDirectory(path);
try
{
foreach (string filename in filenames)
{
string newfilename = filename.Replace(selectedPath, path);
if (!File.Exists(newfilename))
{
// Создание объектов фильтров
Grayscale filterGray = new Grayscale(0.2125, 0.7154, 0.0721);
GrayscaleToRGB filterRGB = new GrayscaleToRGB();
AdaptiveSmoothing noise = new AdaptiveSmoothing();
// Считывание изображения из файла
Bitmap image = new Bitmap(filename);
// Получение изображения с шумом
image = filterRGB.Apply(noise.Apply(filterGray.Apply(image)));
// Сохранение изображения с шумом
image.Save(newfilename, System.Drawing.Imaging.ImageFormat.Png);
image.Dispose();
// Периодическая очистка памяти
if (GC.GetTotalMemory(true) > 1000000000) GC.Collect();
}
}
}
catch (Exception ex)
{
OnException(ex.Message);
}
return path;
}
// Получение параметров контуров
public void GetBlobs(string filename)
{
// Создание объектов фильтров
BlobCounter bc = new BlobCounter();
Grayscale filterGray = new Grayscale(0.2125, 0.7154, 0.0721);
try
{
// Считывание изображения из файла
Bitmap image = new Bitmap(filename);
image = filterGray.Apply(image);
bc.ProcessImage(image);
Blob[] blobs = bc.GetObjects(image, true);
blobsParameters = new List<BlobParameters>();
foreach (Blob blob in blobs)
{
blobsParameters.Add(new BlobParameters(blob, bc));
}
image.Dispose();
}
catch (Exception ex)
{
OnException(ex.Message);
}
}
// Анализ параметров контуров
public void GetAnalize ()
{
string path = selectedPath + "\\Contour";
analizeResults = new List<AnalizeResult>();
try
{
foreach (string _filename in filenames)
{
// Создание объектов фильтров
BlobCounter bc = new BlobCounter();
Grayscale filterGray = new Grayscale(0.2125, 0.7154, 0.0721);
string filename = _filename.Replace(selectedPath, path);
// Считывание изображения из файла
Bitmap image = new Bitmap(filename);
image = filterGray.Apply(image);
bc.ProcessImage(image);
Blob[] blobs = bc.GetObjects(image, true);
image.Dispose();
int sumAreas = 0;
int sumPerimeters = 0;
foreach (Blob blob in blobs)
{
sumAreas += blob.Area;
sumPerimeters += bc.GetBlobsEdgePoints(blob).Count;
}
analizeResults.Add(new AnalizeResult(blobs.Length, sumAreas, sumPerimeters));
// Периодическая очистка памяти
if (GC.GetTotalMemory(true)>1000000000) GC.Collect();
}
}
catch (Exception ex)
{
OnException(ex.Message);
}
}
// Очистка данных о параметрах контуров
public void ClearStat()
{
blobsParameters = null;
}
// Событие ошибки в программе
public event OnExceptionHandler OnException;
}
// Класс параметров контура
public class BlobParameters
{
private BitmapImage bmp;
private int area;
private int perimeter;
private AForge.Point centerOfGravity;
private double fullness;
private int width;
private int height;
private int x;
private int y;
#region Открытые свойства
public BitmapImage Bmp
{ get { return bmp; } }
public int Area
{ get { return area; } }
public int Perimeter
{ get { return perimeter; } }
public AForge.Point CenterOfGravity
{ get { return centerOfGravity; } }
public double Fullness
{ get { return fullness; } }
public int Width
{ get { return width; } }
public int Height
{ get { return height; } }
public int X
{ get { return x; } }
public int Y
{ get { return y; } }
#endregion
// Конструктор
public BlobParameters(Blob blob, BlobCounter bc)
{
Bitmap bmpBlob = blob.Image.ToManagedImage();
bmp = BitmapToImageSource(bmpBlob);
area = blob.Area;
perimeter = bc.GetBlobsEdgePoints(blob).Count;
centerOfGravity = blob.CenterOfGravity;
fullness = blob.Fullness;
width = blob.Rectangle.Width;
height = blob.Rectangle.Height;
x = blob.Rectangle.X;
y = blob.Rectangle.Y;
}
// Преобразование изображения из Bitmap в BitmapImage
private BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
}
// Класс параметров изображения для графического анализа
public class AnalizeResult
{
private int contoursCount; // Количество контуров
private int sumAreas; // Сумма площадей контуров
private int sumPerimeters; // Сумма периметров контуров
#region Открытые свойства
public int ContoursCount
{ get { return contoursCount; } }
public int SumAreas
{ get { return sumAreas; } }
public int SumPerimeters
{ get { return sumPerimeters;} }
#endregion
// Конструктор
public AnalizeResult(int _count, int _sumAreas, int _sumPerim)
{
contoursCount = _count;
sumAreas = _sumAreas;
sumPerimeters = _sumPerim;
}
}
}
XAML-разметка окна вывода графиков
<Window x:Class="НИР.Analize"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:НИР"
mc:Ignorable="d"
Title="Анализ результатов" Height="600" Width="800"
Icon="Resources/Icon2.png"
WindowStartupLocation="CenterScreen" MinWidth="400" MinHeight="300">
<Grid SizeChanged="Grid_SizeChanged">
<TabControl x:Name="TabCa" SelectionChanged="TabCa_SelectionChanged">
<TabControl.Resources>
<Style TargetType="Line">
<Setter Property="StrokeThickness" Value="2"/>
</Style>
<Style TargetType="Polyline">
<Setter Property="StrokeThickness" Value="2"/>
</Style>
</TabControl.Resources>
<TabItem Header="Количество контуров" x:Name="NumCont">
<Border Margin="10" BorderThickness="2"
BorderBrush="DarkGray">
<Grid>
<Canvas x:Name="CanvasNum" Margin="10" Loaded="CanvasNum_Loaded">
<Polyline Name="NumLine" Stroke="DarkBlue"
Points="{Binding Graphici}"/>
<Polyline Name="NoiceNumLine" Stroke="Orange"
Points="{Binding GraphiciNoice}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row ="0" Grid.Column="0">
Без шума
</TextBlock>
<TextBlock Grid.Row ="1" Grid.Column="0">
С шумом
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="0"
HorizontalAlignment="Right">
Max =
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="1"
Text="{Binding MaxValue}"
HorizontalAlignment="Left"/>
<Line Grid.Row ="0" Grid.Column="1" Stroke="DarkBlue"
X1="5" X2="40" Y1="10" Y2="10" />
<Line Grid.Row ="1" Grid.Column="1" Stroke="Orange"
X1="5" X2="40" Y1="10" Y2="10"/>
</Grid>
<Line X1="0" X2="0" Y1="40" Stroke="Black" StrokeThickness="1"
Y2="{Binding ElementName=CanvasNum, Path=ActualHeight}"/>
<Line X1="0" Stroke="Black" StrokeThickness="1"
X2="{Binding ElementName=CanvasNum, Path=ActualWidth}"
Y2="{Binding ElementName=CanvasNum, Path=ActualHeight}"
Y1="{Binding ElementName=CanvasNum, Path=ActualHeight}"/>
</Canvas>
</Grid>
</Border>
</TabItem>
<TabItem Header="Сумма площадей контуров" x:Name="AreaCont">
<Border Margin="10" BorderThickness="2"
BorderBrush="DarkGray">
<Grid>
<Canvas x:Name="CanvasArea" Margin="10" Loaded="CanvasArea_Loaded">
<Polyline Name="AreaLine" Stroke="DarkBlue"
Points="{Binding Graphici}"/>
<Polyline Name="NoiceAreaLine" Stroke="Orange"
Points="{Binding GraphiciNoice}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row ="0" Grid.Column="0">
Без шума
</TextBlock>
<TextBlock Grid.Row ="1" Grid.Column="0">
С шумом
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="0"
HorizontalAlignment="Right">
Max =
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="1"
Text="{Binding MaxValue}"
HorizontalAlignment="Left"/>
<Line Grid.Row ="0" Grid.Column="1" Stroke="DarkBlue"
X1="5" X2="40" Y1="10" Y2="10" />
<Line Grid.Row ="1" Grid.Column="1" Stroke="Orange"
X1="5" X2="40" Y1="10" Y2="10"/>
</Grid>
<Line X1="0" X2="0" Y1="40" Stroke="Black" StrokeThickness="1"
Y2="{Binding ElementName=CanvasArea, Path=ActualHeight}"/>
<Line X1="0" Stroke="Black" StrokeThickness="1"
X2="{Binding ElementName=CanvasArea, Path=ActualWidth}"
Y2="{Binding ElementName=CanvasArea, Path=ActualHeight}"
Y1="{Binding ElementName=CanvasArea, Path=ActualHeight}"/>
</Canvas>
</Grid>
</Border>
</TabItem>
<TabItem Header="Сумма периметров контуров" x:Name="PerimCont">
<Border Margin="10" BorderThickness="2"
BorderBrush="DarkGray">
<Grid>
<Canvas x:Name="CanvasPerimeter" Margin="10" Loaded="CanvasPerimeter_Loaded">
<Polyline Name="PerimLine" Stroke="DarkBlue"
Points="{Binding Graphici}"/>
<Polyline Name="NoicePerimLine" Stroke="Orange"
Points="{Binding GraphiciNoice}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row ="0" Grid.Column="0">
Без шума
</TextBlock>
<TextBlock Grid.Row ="1" Grid.Column="0">
С шумом
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="0"
HorizontalAlignment="Right">
Max =
</TextBlock>
<TextBlock Grid.Row ="2" Grid.Column="1"
Text="{Binding MaxValue}"
HorizontalAlignment="Left"/>
<Line Grid.Row ="0" Grid.Column="1" Stroke="DarkBlue"
X1="5" X2="40" Y1="10" Y2="10" />
<Line Grid.Row ="1" Grid.Column="1" Stroke="Orange"
X1="5" X2="40" Y1="10" Y2="10"/>
</Grid>
<Line X1="0" X2="0" Y1="40" Stroke="Black" StrokeThickness="1"
Y2="{Binding ElementName=CanvasPerimeter, Path=ActualHeight}"/>
<Line X1="0" Stroke="Black" StrokeThickness="1"
X2="{Binding ElementName=CanvasPerimeter, Path=ActualWidth}"
Y2="{Binding ElementName=CanvasPerimeter, Path=ActualHeight}"
Y1="{Binding ElementName=CanvasPerimeter, Path=ActualHeight}"/>
</Canvas>
</Grid>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>
Обработчик событий окна вывода графиков
namespace НИР
{
/// <summary>
/// Логика взаимодействия для Analize.xaml
/// </summary>
public partial class Analize : Window
{
List<AnalizeResult> Graph;
List<AnalizeResult> NoiceGraph;
public Analize(List<AnalizeResult> graph, List<AnalizeResult> noiceGraph)
{
InitializeComponent();
Graph = new List<AnalizeResult>(graph);
NoiceGraph = new List<AnalizeResult>(noiceGraph);
DataContext = new ViewClass();
NumCont.Focus();
}
private void CanvasNum_Loaded(object sender, RoutedEventArgs e)
{
if (NumCont.IsSelected)
{
List<int> _value = new List<int>(Graph.Select(x => x.ContoursCount));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.ContoursCount));
GetPoints(_value, _noiceValue, CanvasNum.ActualHeight, CanvasNum.ActualWidth);
}
}
private void CanvasArea_Loaded(object sender, RoutedEventArgs e)
{
if (AreaCont.IsSelected)
{
List<int> _value = new List<int>(Graph.Select(x => x.SumAreas));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.SumAreas));
GetPoints(_value, _noiceValue, CanvasArea.ActualHeight, CanvasArea.ActualWidth);
}
}
private void CanvasPerimeter_Loaded(object sender, RoutedEventArgs e)
{
if (PerimCont.IsSelected)
{
List<int> _value = new List<int>(Graph.Select(x => x.SumPerimeters));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.SumPerimeters));
GetPoints(_value, _noiceValue, CanvasPerimeter.ActualHeight, CanvasPerimeter.ActualWidth);
}
}
private void GetPoints(List<int> _value, List<int> _noiceValue, double canH, double canW)
{
int maxG = _value.Max();
int maxNG = _noiceValue.Max();
double maxValue = maxG > maxNG ? maxG : maxNG;
((ViewClass)DataContext).MaxValue = (int)maxValue;
double maxHeight = canH - 40.0;
double maxWidth = canW;
var _Graphici = new PointCollection();
var _GraphiciNoice = new PointCollection();
for (int i = 0; i < Graph.Count; i++)
{
_Graphici.Add(new Point(maxWidth * i / _value.Count, maxHeight + 40 - maxHeight * _value[i] / maxValue));
_GraphiciNoice.Add(new Point(maxWidth * i / _noiceValue.Count, maxHeight + 40 - maxHeight * _noiceValue[i] / maxValue));
}
((ViewClass)DataContext).Graphici = _Graphici;
((ViewClass)DataContext).GraphiciNoice = _GraphiciNoice;
}
private void TabCa_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (NumCont.IsSelected)
{
if (CanvasNum.Parent != null)
{
var parent = (Panel)CanvasNum.Parent;
parent.Children.Remove(CanvasNum);
parent.Children.Add(CanvasNum);
}
}
else if (AreaCont.IsSelected)
{
if (CanvasArea.Parent != null)
{
var parent = (Panel)CanvasArea.Parent;
parent.Children.Remove(CanvasArea);
parent.Children.Add(CanvasArea);
}
}
else
{
if (CanvasPerimeter.Parent != null)
{
var parent = (Panel)CanvasPerimeter.Parent;
parent.Children.Remove(CanvasPerimeter);
parent.Children.Add(CanvasPerimeter);
}
}
}
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (NumCont.IsSelected)
{
List<int> _value = new List<int>(Graph.Select(x => x.ContoursCount));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.ContoursCount));
GetPoints(_value, _noiceValue, CanvasNum.ActualHeight, CanvasNum.ActualWidth);
}
else if (AreaCont.IsSelected)
{
List<int> _value = new List<int>(Graph.Select(x => x.SumAreas));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.SumAreas));
GetPoints(_value, _noiceValue, CanvasArea.ActualHeight, CanvasArea.ActualWidth);
}
else
{
List<int> _value = new List<int>(Graph.Select(x => x.SumPerimeters));
List<int> _noiceValue = new List<int>(NoiceGraph.Select(x => x.SumPerimeters));
GetPoints(_value, _noiceValue, CanvasPerimeter.ActualHeight, CanvasPerimeter.ActualWidth);
}
}
}
}
Класс свойств зависимостей
namespace НИР
{
public class ViewClass : DependencyObject
{
public string FileName
{
get { return (string)GetValue(FileNameProperty); }
set { SetValue(FileNameProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства FileName
public static readonly DependencyProperty FileNameProperty =
DependencyProperty.Register("FileName", typeof(string), typeof(ViewClass), new PropertyMetadata(null));
public int Max
{
get { return (int)GetValue(MaxProperty); }
set { SetValue(MaxProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства Max
public static readonly DependencyProperty MaxProperty =
DependencyProperty.Register("Max", typeof(int), typeof(ViewClass), new PropertyMetadata(1));
public int Val
{
get { return (int)GetValue(ValProperty); }
set { SetValue(ValProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства Val
public static readonly DependencyProperty ValProperty =
DependencyProperty.Register("Val", typeof(int), typeof(ViewClass), new PropertyMetadata(1));
public List<BlobParameters> BlobList
{
get { return (List<BlobParameters>)GetValue(BlobListProperty); }
set { SetValue(BlobListProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства BlobList
public static readonly DependencyProperty BlobListProperty =
DependencyProperty.Register("BlobList", typeof(List<BlobParameters>), typeof(ViewClass), new PropertyMetadata(null));
public BitmapImage BlobImage
{
get { return (BitmapImage)GetValue(BlobImageProperty); }
set { SetValue(BlobImageProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства BlobImage
public static readonly DependencyProperty BlobImageProperty =
DependencyProperty.Register("BlobImage", typeof(BitmapImage), typeof(ViewClass), new PropertyMetadata(null));
public PointCollection Graphici
{
get { return (PointCollection)GetValue(GraphiciProperty); }
set { SetValue(GraphiciProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства Graphici
public static readonly DependencyProperty GraphiciProperty =
DependencyProperty.Register("Graphici", typeof(PointCollection), typeof(ViewClass), new PropertyMetadata(null));
public PointCollection GraphiciNoice
{
get { return (PointCollection)GetValue(GraphiciNoiceProperty); }
set { SetValue(GraphiciNoiceProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства GraphiciNoice
public static readonly DependencyProperty GraphiciNoiceProperty =
DependencyProperty.Register("GraphiciNoice", typeof(PointCollection), typeof(ViewClass), new PropertyMetadata(null));
public int MaxValue
{
get { return (int)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
// Использование DependencyProperty в качестве резервного хранилища для свойства MaxValue
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(int), typeof(ViewClass), new PropertyMetadata(0));
}
}
Результаты эксперимента
Эксперимент заключается в анализе влияния шума на результат обработки для различных категорий изображений.
Рисунок 1 - Исходное изображение кишки без шума и с шумом
Рисунок 2 - Бинарное изображение кишки без шума и с шумом
Рисунок 3 - Контуры изображения кишки без шума и с шумом
Таблица 1 - Геометрические характеристики изображения без шума
Таблица 2 - Геометрические характеристики изображения с шумом
Рисунок 4 - Анализ контуров изображений кишки с шумом и без шума
Для других категорий изображений выведем результаты эксперимента только в виде графиков
Рисунок 5 - Анализ контуров изображений легких с шумом и без шума
Рисунок 6 - Анализ контуров изображений печени с шумом и без шума
Рисунок 7 - Анализ контуров изображений селезенки с шумом и без шума
Рисунок 8 - Анализ контуров изображений сердца с шумом и без шума
Анализ результатов эксперимента
При рассмотрении влияния адаптивного сглаживающего шума на различные категории томографических изображений можно отметить следующие закономерности:
- изображения получают более четкие очертания крупных объектов изображений, мелкие же детали изображений пропадают;
- количество контуров изображений с шумом, сумма их площадей и сумма периметров преимущественном меньше, чем у изображений без шума (наиболее сильно проявилось при анализе изображений легких.
Таким образом, можно сделать вывод о том, что задачи поставленные на научно-исследовательскую работу решены. Программное обеспечение работает корректно и без сбоев, выводит результаты исследований в удобном для анализа виде.
Размещено на Allbest.ru
Подобные документы
Общая информация о графическом формате. Описание формата Microsoft Windows Bitmap. Структура файла DDВ исходного формата ВМР. Преобразования графических файлов. Просмотр и редактирование растровых изображений. Создание многодокументного приложения.
дипломная работа [1,5 M], добавлен 06.06.2010Методы обработки растровых изображений (кластеризация, пороговая и интерактивная сегментация). Разработка программного модуля для системы мониторинга биосферы и дистанционного зондирования. Создание пользовательского интерфейса программного модуля.
курсовая работа [2,2 M], добавлен 29.04.2015Обзор существующего программного обеспечения для автоматизации выделения границ на изображении. Разработка математической модели обработки изображений и выделения контуров в оттенках серого и программного обеспечения для алгоритмов обработки изображений.
дипломная работа [1,7 M], добавлен 27.03.2013Описание математических методов представления и обработки графических изображений. Описание разработанного программного дополнения. Описание функций и их атрибутов. Представление и обработка графических изображений. Результаты тестирования программы.
курсовая работа [1,7 M], добавлен 27.01.2015Анализ проблем, возникающих при совмещении изображений в корреляционно-экстремальных навигационных системах. Использование двумерного дискретного преобразования Фурье. Нахождение корреляционной функции радиолокационного и моделируемого изображений.
дипломная работа [3,6 M], добавлен 07.07.2012Разработка программы для создания, просмотра и сохранения изображений. Реализация функции рисования различных фигур с заливкой и без заливки, функции очистки рабочего пространства и отмены последних действий. Обоснование выбранных методов и алгоритмов.
курсовая работа [3,2 M], добавлен 25.07.2013Задача пространственно-временной обработки изображений при наличии шумов и помех. Методы оптимизации при пространственно-временной обработке изображений. Структура специализированной программы, описание ее пользовательского интерфейса. Смета затрат.
дипломная работа [957,2 K], добавлен 10.06.2013Технологические возможности компьютерных программ для работы с графикой. Режимы и источники изображений, основной и фоновый цвет, контуры, фильтры и меню графического редактора Adobe Photoshop. Создание и трансформация объектов в программе Corel Draw.
курсовая работа [39,5 K], добавлен 08.11.2013Обработка изображений на современных вычислительных устройствах. Устройство и представление различных форматов изображений. Исследование алгоритмов обработки изображений на базе различных архитектур. Сжатие изображений на основе сверточных нейросетей.
дипломная работа [6,1 M], добавлен 03.06.2022Загрузка интерфейса изображением формата хранения растровых изображений BMP. Программа осуществления отражения изображения по вертикали и горизонтали. Применение к изображению черно-белого, сглаживающего, подчеркивания границ и медианного фильтров.
лабораторная работа [713,6 K], добавлен 26.04.2015