Главная Случайная страница


Категории:

ДомЗдоровьеЗоологияИнформатикаИскусствоИскусствоКомпьютерыКулинарияМаркетингМатематикаМедицинаМенеджментОбразованиеПедагогикаПитомцыПрограммированиеПроизводствоПромышленностьПсихологияРазноеРелигияСоциологияСпортСтатистикаТранспортФизикаФилософияФинансыХимияХоббиЭкологияЭкономикаЭлектроника






Лабораторная работа «Работа с растровыми изображениями»

 

Цель лабораторной работы: изучить возможности Visual Studio по открытию и сохранению файлов. Написать и отладить программу для создания или обработки изображений.

Отображение графических файлов

Обычно для отображения точечных рисунков, рисунков из метафайлов, значков, рисунков из файлов в формате BMP, JPEG, GIF или PNG используется объект PictureBox, т.е. элемент управления PictureBox действует как контейнер для картинок. Можно выбрать изображение для вывода, присвоив значение свойству Image. Свойство Image может быть установлено в окне Свойства или в коде программы, указывая на рисунок, который следует отображать.

Элемент управления PictureBox содержит и другие полезные свойства, в том числе: AutoSize определяющее, будет ли изображение растянуто в элементе PictureBox, и SizeMode, которое может использоваться для растягивания, центрирования или увеличения изображения в элементе управления PictureBox.

Перед добавлением рисунка к элементу управления PictureBox в проект обычно добавляется файл рисунка в качестве ресурса[3]. После добавления ресурса к проекту можно повторно использовать его. Например, может потребоваться отображение одного и того же изображения в нескольких местах.

Необходимо отметить, что поле Image само является классом для работы с изображениями, у которого есть свои методы. Например, метод FromFile используется для загрузки изображения из файла. Кроме класса Image существует класс Bitmap, который расширяет возможности класса Image за счет дополнительных методов для загрузки, сохранения и использования растровых изображений. Так метод Save класса Bitmap позволяет сохранять изображения в разных форматах, а методы GetPixel и SetPixel позволяют получить доступ к отдельным пикселям рисунка.

Компоненты OpenFileDialog и SaveFileDialog

Компонент OpenFileDialog является стандартным диалоговым окном. Он аналогичен диалоговому окну «Открыть файл» операционной системы Windows. Компонент OpenFileDialog позволяет пользователям просматривать папки личного компьютера или любого компьютера в сети, а также выбирать файлы, которые требуется открыть. Для вызова диалогового окна для выбора файла можно использовать метод ShowDialog() который возвращет true при корректном выборе.

Диалоговое окно возвращает путь и имя файла, который был выбран пользователем в специальном свойстве FileName.

 

Простой графический редактор

Создайте приложение, реализующее простой графический редактор. Функциями этого редактора должны быть: открытие рисунка, рисование поверх него простой кистью, сохранение рисунка в другой файл. Для этого создайте форму и разместите на ней элементы управления button и picturebox (рис 7.1).

Рис. 8.1. Форма для графического редактора

В этом случае на понадобится из панели элементов размещать на форме компоненты диалоговых окон OpenFileDialog и SaveFileDialog. Эти элементы будут порождены динамически в ходе выполнения программы с помощью конструтора. Например так:

 

OpenFileDialog dialog = new OpenFileDialog();

 

Далее они будут вызыватся с помощью метода ShowDialog().

Для кнопок «Открыть» и «Сохранить» создайте свои обработчики события. Также создайте обработчик события Load для формы. Для элемента управления picturebox1 создайте обработчики события MouseDown, MouseMove. Код приложения будет выглядеть следующим образом:

 

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

public partial class Form1 : Form

{ //Объявляем переменные доступные в каждом обработчике события

private Point PreviousPoint, point; //Точка до перемещения курсора мыши

//и текущая точка

private Bitmap bmp;

private Pen blackPen;

private Graphics g;

 

public Form1()

{

InitializeComponent();

}

 

private void Form1_Load(object sender, EventArgs e)

{

blackPen = new Pen(Color.Black, 4); //подготавливаем перо

}

 

private void button1_Click(object sender, EventArgs e)

{ //открытие файла

OpenFileDialog dialog = new OpenFileDialog();

//задаем расширения файлов

dialog.Filter = "Image files (*.BMP, *.JPG, *.GIF, *.TIF, *.PNG, *.ICO, *.EMF, *.WMF)|*.bmp;*.jpg;*.gif; *.tif; *.png; *.ico; *.emf; *.wmf";

if (dialog.ShowDialog() == DialogResult.OK)//вызываем диалоговое окно

{

Image image = Image.FromFile(dialog.FileName); //Загружаем в image

//изображение из выбранного файла

int width = image.Width;

int height = image.Height;

pictureBox1.Width = width;

pictureBox1.Height = height;

 

bmp = new Bitmap(image, width, height); //создаем и загружаем из

//image изображение в формате bmp

 

pictureBox1.Image = bmp; //записываем изображение в формате bmp

//в pictureBox1

g = Graphics.FromImage(pictureBox1.Image); //подготавливаем объект

//Graphics для рисования в pictureBox1

}

}

 

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

{ // обработчик события нажатия кнопки на мыши

// записываем в предыдущую точку (PreviousPoint) текущие координаты

PreviousPoint.X = e.X;

PreviousPoint.Y = e.Y;

}

 

 

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)

{//Обработчик события перемещения мыши по pictuteBox1

if (e.Button == MouseButtons.Left) //Проверяем нажатие левой кнопка

{ //запоминаем в point текущее положение курсора мыши

point.X = e.X;

point.Y = e.Y;

 

//соединяем линией предыдущую точку с текущей

g.DrawLine(blackPen, PreviousPoint, point);

 

//текущее положение курсора мыши сохраняем в PreviousPoint

PreviousPoint.X = point.X;

PreviousPoint.Y = point.Y;

pictureBox1.Invalidate();//Принудительно вызываем перерисовку

}

}

 

private void button2_Click(object sender, EventArgs e)

{ //сохранение файла

SaveFileDialog savedialog = new SaveFileDialog();

//задаем свойства для savedialog

savedialog.Title = "Сохранить картинку как ...";

savedialog.OverwritePrompt = true;

savedialog.CheckPathExists = true;

savedialog.Filter =

"Bitmap File(*.bmp)|*.bmp|" +

"GIF File(*.gif)|*.gif|" +

"JPEG File(*.jpg)|*.jpg|" +

"TIF File(*.tif)|*.tif|" +

"PNG File(*.png)|*.png";

savedialog.ShowHelp = true;

if (savedialog.ShowDialog() == DialogResult.OK)

{

// в fileName записываем полный путь к файлу

string fileName = savedialog.FileName;

// Убираем из имени три последних символа (расширение файла)

string strFilExtn =

fileName.Remove(0, fileName.Length - 3);

// Сохраняем файл в нужном формате и с нужным расширением

switch (strFilExtn)

{

case "bmp":

bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Bmp);

break;

case "jpg":

bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);

break;

case "gif":

bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Gif);

break;

case "tif":

bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Tiff);

break;

case "png":

bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);

break;

default:

break;

}

}

}

 

 

}

}

 

Далее добавим в проект кнопку для перевода изображения в градации серого цвета:

 

private void button3_Click(object sender, EventArgs e)

{ //циклы для перебора всех пикселей на изображении

for (int i = 0; i < bmp.Width; i++)

for (int j = 0; j < bmp.Height; j++)

{

int R = bmp.GetPixel(i, j).R; //извлекаем долю красного цвета

int G = bmp.GetPixel(i, j).G; //извлекаем долю зеленого цвета

int B = bmp.GetPixel(i, j).B; //извлекаем долю синего цвета

int Gray = (R = G + B)/3; // высчитываем среднее

Color p = Color.FromArgb(255, Gray, Gray, Gray); //переводим int в значение цвета. 255 - показывает степень прозрачности. остальные значения одинаковы для трех каналов R,G,B

bmp.SetPixel(i, j, p); //записываем полученный цвет в точку

}

Refresh(); //вызываем функцию перерисовки окна

}

 

Данный код демонстрирует возможность обращения к отдельным пикселям. Цвет каждого пикселя хранится в модели RGB и состоит из трех составляющих: красного, зеленого и синего цвета, называемых каналами. Значение каждого канала может варьироваться в диапазоне от 0 до 255.

Задание по лабораторной работе

Добавьте в приведенный графический редактор свои функции в соответствии с вариантом.

 

1) Расширьте приложение путем добавления возможности регулировки яркости и контрастности как в целом сразу по трём каналам, так и по каждому каналу отдельно.

2) Расширьте приложение путем добавления различных фильтров размытия с различным размером ядра.

3) Расширьте приложение путем добавления различных фильтров повышения контрастности с различным размером ядра.

4) Расширьте приложение путем добавления различных фильтров нахождения границ.

5) Расширьте приложение путем добавления медианного фильтра.

6) Создайте функцию, переводящую изображение в черно-белый формат (реализуйте пороговую фильтрацию). Пороговое значение задавать с помощью элемента управления TrackBar.

7) Разработайте функцию построения гистограммы по трем каналам (R,G,B) вместе и по каждому каналу в отдельности.

8) Реализуйте функцию поворота выделенного участка изображения.

9) Реализуйте функцию вертикального и горизонтальногоотражениявыделенного участка изображения.

10) Разработайте функцию, оставляющую на изображении только один из каналов (R,G,B). Канал выбирается пользователем.

11) Расширьте приложение путем добавления возможности выбора пользователем цвета и величины кисти.

12) Создайте функцию, выводящую на изображение окружность. Центр окружности совпадает с центром изображения. Все точки вне окружности переводятся в градации серого цвета. Все точки внутри окружности остаются неизменными. Радиус окружности задается пользователем.

13) Создайте функцию, выводящую на изображение треугольник. Для всех точек вне треугольника оставьте только канал B. Все точки внутри треугольника переводятся в градации серого цвета.

14) Создайте функцию, выводящую на изображение ромб. Все точки вне ромба переводятся в градации серого цвета. Для всех точек внутри ромба оставьте только канал G.

15) Разработайте функцию, которая каждую четную строку изображения переводит в градации серого цвета.

16) Разработайте функцию, которая переводит каждый нечетный столбец пикселей (вертикальные линии) в градации серого цвета.

17) Создайте функцию, разбивающую изображение на четыре равные части. В каждой оставьте значение только одного канала R, G и B, а в четвертой выведите градации серого цвета.

18) Разработайте функцию, заменяющую все точки синего цвета на точки красного цвета.

19) Создайте функцию, инвертирующую изображение в градациях серого цвета в негатив.

20) Создайте функцию, переводящую изображение в черно-белый формат в соответствии с пороговым значением, которое ввел пользователь. Для анализа используйте только один из каналов (R,G,B).

21) Разработайте функцию для создания эффекта мозаики. При этом изображения разбивается на прямоугольные фрагменты, в каждом из которых выбирается цвет средней точки и этим же цветом закрашивается весь фрагмент.

22) Разработайте функцию, разбивающую изображение на фрагменты, в каждом из которых остается только один из каналов (R, G, B).

9. Лабораторная работа «Преобразования на плоскости»

 

Цель лабораторной работы: изучить, как производятся двухмерные преобразования с помощью однородных координат и матрицы преобразования 3x3. Написать и отладить программу для 2D преобразований.

Простейшие преобразования на плоскости

Рассмотрим преобразования на плоскости.

Для начала заметим, что точки на плоскости задаются с помощью двух ее координат. Таким образом, геометрически каждая точка задается значениями координат вектора относительно выбранной системы координат. Координаты точек можно рассматривать как элементы матрицы [x, y], т.е. в виде вектор-строки или вектор-столбца. Положением этих точек управляют путем преобразования матрицы.

Точки на плоскости x y можно перенести в новые позиции путем добавления к координатам этих точек констант переноса:

 

 

Рассмотрим результаты матричного умножения матрицы [x, y], определяющей точку Р и матрицы преобразований 2х2 общего вида:

Проведем анализ полученных результатов, рассматривая x* и y* как преобразованные координаты. Для этого исследуем несколько частных случаев.

Рассмотрим случай, когда a = d = 1 и c = b = 0. Матрица преобразований приводит к матрице, идентичной исходной,

При этом изменений координат точки Р не происходит.

Если теперь d = 1, b = c = 0, a = const, то:

Как видно, это приводит к изменению масштаба в направлении х, так как х*=ах. Следовательно, данное матричное преобразование эквивалентно перемещению исходной точки в направлении х.

Теперь положим b = c = 0, т.е.:

В результате получаем изменение масштабов в направлениях x и y. Если a¹ d, то перемещения вдоль осей неодинаковы. Если a = d >1, то имеет место увеличение масштаба координат точки Р. Если 0 < a=d <1, то будет иметь место уменьшение масштаба координат точки Р.

Если a или (и) d отрицательны, то происходит отображение координат точек. Рассмотрим это, положив b = c = 0, d = 1 и а = -1, тогда:

 

Произошло отображение точки относительно оси у. В случае b = c = 0,
a = 1, d = -1, отображение происходит относительно оси х. Если b = c = 0,
a = d <0, то отображение будет происходить относительно начала координат.

Заметим, что отображение и изменение масштаба вызывают только диагональные элементы матрицы преобразования.

Преобразование общего вида, примененное к началу координат не приведет к изменению координат точки (0, 0). Следовательно, начало координат инвариантно при общем преобразовании. Это ограничение преодолевается за счет использования однородных координат.

Преобразование поворота и отражения

Общую матрицу 2х2, которая осуществляет вращение фигуры относительно начала координат, можно получить из рассмотрения вращения единичного квадрата вокруг начала координат.

 

Как следует из рисунка, точка В с координатами (1, 0) преобразуется в точку В*, для которой х*= (1) cosq и y=(1) sinq, а точка D, имеющая координаты (0, 1) переходит в точку D* с координатами x*=(-1) sinq и y*=(1) cosq.

Матрица преобразования общего вида записывается так:

.

Для частных случаев. Поворот на 900 можно осуществить с помощью матрицы преобразования

.

Если использовать матрицу координат вершин, то получим, например:

.

Поворот на 1800 получается с помощью матрицы .

В то время как чистое двумерное вращение в плоскости xy осуществляется вокруг оси, перпендикулярной к этой плоскости, отображение определяется поворотом на 1800 вокруг оси, лежащей в плоскости ху.

Такое вращение вокруг линии у=х происходит при использовании матрицы .

Преобразованные новые выражения определяются соотношением:

.

Вращение вокруг у = 0 получается при использовании матрицы

.

Однородные координаты

Преобразования переноса, масштабирования и поворота записываются в матричной форме в виде

,

,

.

Очевидно, что перенос, в отличие от масштабирования и поворота, реализуется с помощью сложения. Это обусловлено тем, что вводить константы переноса внутрь структуры общей матрицы размера 2х2 не представляется возможным. Желательным является представление преобразований в единой форме – с помощью умножения матриц. Эту проблему можно решить за счет введения третьей компоненты в векторы точек и , т.е. представляя их в виде и . Матрица преобразования после этого становится матрицей размера 3х3, например:

.

Используя эту матрицу, получаем преобразованный вектор [х* у* 1]. Добавление третьего элемента к вектору положения и третьего столбца к матрице преобразования позволяет выполнить смещение вектора положения. Третий элемент здесь можно рассматривать как дополнительную координату вектора положения. Итак, вектор положения [х у 1] при воздействии на него матрицы 3х3 становится вектором положения в общем случае вида [X Y Н]. Представленное преобразование было выполнено так, что [X Y Н]= [х* у* 1].

Преобразование, имеющее место в трехмерном пространстве, в нашем случае ограничено плоскостью, поскольку H = 1. Если, однако, третий столбец матрицы преобразования Т размера 3х3 отличен от 0, то в результате матричного преобразования получим [х у 1] ×Т = [Х Y Н], где Н ¹ 1.

Плоскость, в которой теперь лежит преобразованный вектор положения, находится в трехмерном пространстве.

Преобразованные обычные координаты получаются за счет нормализации однородных координат, т. е.

и .

Геометрически все преобразования х и у происходят в плоскости Н=1 после нормализации преобразованных однородных координат.

Преимущество введения однородных координат проявляется при использовании матрицы преобразований общего вида порядка 3х3

,

с помощью которой можно выполнять и другие преобразования, такие как смещение, операции изменения масштаба и сдвига, обусловленные матричными элементами а, b, с и d. Указанные операции рассмотрены ранее.

Основная матрица преобразования размера 3х3 для двумерных однородных координат может быть подразделена на четыре части:

.

Как мы видим, а, b, с и d осуществляют изменение масштаба, сдвиг и вращение; т и п выполняют смещение, а р и q – получение проекций. Оставшаяся часть матрицы, элемент s, производит полное изменение масштаба. Чтобы показать это, рассмотрим преобразование

Здесь Х = х, Y = у, а Н = s. Это дает х* = x/s и y* == y/s. В результате преобразования [х у 1 ] —> [x/s y/s 1] имеет место однородное изменение масштаба вектора положения. При s< 1 происходит увеличение, а при s> 1 уменьшение масштаба.

Комбинированные преобразования

Рассмотрим комбинированные преобразования на примере поворота вокруг произвольной точки.

Выше было рассмотрено вращение изображения около начала координат. Однородные координаты обеспечивают поворот изображения вокруг точек, отличных от начала координат. В общем случае вращение около произвольной точки может быть выполнено путем переноса центра вращения в начало координат, поворотом относительно начала координат, а затем переносом точки вращения в исходное положение. Таким образом, поворот вектора положения [х у 1 ] около точки (т, п) на произвольный угол может быть выполнен с помощью преобразования

.

Выполнив две операции умножения матриц, можно записать

.

 

Программная реализация

На первом этапе спроектируйте оконный интерфейс. Разместите на форме кнопки для переноса, масштабирования и поворота. При необходимости разместите элементы для ввода значений: например для ввода значений углов поворота. Пример окна приведен на рис. 9.1.

Опишите и задайте начальные значения для матрицы, где будут храниться координаты двухмерной фигуры. Назовем эту матрицу матрицей тела и опишем как двухмерный массив Sqтипа double. Опишите и задайте как единичную матрицу преобразования 3x3 (двухмерный массив Tтипа double). Поскольку массивы Sq и T будут использоваться повсеместно, то целесообразно задать их в качестве полей класса доступных во всех методах и не тратить время на передачу в качестве параметров.

Рис. 9.1. Интерфейс для преобразований на плоскости

 

При нажатии на кнопку должен запускаться процесс, приведённый на рис. 9.2.

Рис. 9.2. Основной процесс визуализации

Этап задания коэффициентов матрицы преобразования сводится к заданию элементов двухмерного массива.

Как видим из рис. 9.2. на втором этапе выбрана стратегия сохранения изменений при преобразованиях в матрице тела, а не накапливание изменений в матрице преобразований. Исходя из этого тело метода, реализующего данный этап, может выглядеть следующим образом:

 

b = new double[3];//массив для хранения промежуточных данных

for (int j=0; j<4; j++)//Цикл по вершинам фигуры (4 вершины для квадрата)

{

for (int i = 0; i < 3; i++)

{

b[i] = 0;

for (int k = 0; k < 3; k++)

b[i] = b[i] + Sq[j, k]*T[k, i];

}

for (int k=0; k<3; k++)

Sq[j, k]= b[k];

}

 

Третий этап нормализации приводит к единице последнюю координату путем деления:

 

for (int j = 0; j < 4; j++)

{

Sq[j, 0] = Sq[j, 0] / Sq[j, 2];

Sq[j, 1] = Sq[j, 1] / Sq[j, 2];

Sq[j, 2] = 1;

}

 

Перерисовка должна находиться в обработчике события Paint:

 

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics gfx = e.Graphics;

Pen skyBluePen = new Pen(Brushes.DeepSkyBlue);

int cx = ClientSize.Width/2;

int cy = ClientSize.Height/2;

gfx.DrawLine(skyBluePen, cx, 0, cx, ClientSize.Height);

gfx.DrawLine(skyBluePen, 0, cy, ClientSize.Width, cy);

 

Pen SqPen = new Pen(Brushes.BlueViolet);

 

gfx.DrawLine(SqPen, (int) (cx + Sq[0, 0]), (int) (cy - Sq[0, 1]),

(int) (cx + Sq[1, 0]), (int) (cy - Sq[1, 1]));

gfx.DrawLine(SqPen, (int) (cx + Sq[1, 0]), (int) (cy - Sq[1, 1]),

(int) (cx + Sq[2, 0]), (int) (cy - Sq[2, 1]));

gfx.DrawLine(SqPen, (int) (cx + Sq[2, 0]), (int) (cy - Sq[2, 1]),

(int) (cx + Sq[3, 0]), (int) (cy - Sq[3, 1]));

gfx.DrawLine(SqPen, (int) (cx + Sq[3, 0]), (int) (cy - Sq[3, 1]),

(int) (cx + Sq[0, 0]), (int) (cy - Sq[0, 1]));

}

 

Переменные cx и сy это координаты центра окна, используются для прорисовки осей и самой фигуры. Приведение к целому типу, а следовательно округление, производится непосредственно перед прорисовкой и не сохраняется в матрице Sq. Поэтому не будет происходить накопление ошибок округления. Запустите и отладьте программу. По результатам подготовьте отчет.

Задание по лабораторной работе

Реализуйте с заданной совокупностью фигур все виды аффинных преобразований: перенос по оси OX и оси OY, отражение относительно координатных осей и прямой Y=X, масштабирование, поворот на заданные углы относительно центра координат и относительно произвольной точки, указываемой в ходе выполнения программы. Предусмотреть восстановление исходной позиции фигур. Управление организовать как через интерфейсные элементы (меню, кнопки, строки редактирования и пр.), так и через «горячие» клавиши.

Варианты заданий

Задание №1     Задание №2 Задание №3 Задание №4 Задание №5
Задание №6 Задание №7 Задание №8 Задание №9 Задание №10
Задание №11 Задание №12 Задание №13 Задание №14 Задание №15
Задание №16 Задание №17     Задание №18   Задание №19 Задание №20
    Задание №21 Задание №22 Задание №23 Задание №24 Задание №25

 

10. Лабораторная работа «3D преобразования и получение проекций»

 

Цель лабораторной работы: изучить, как производятся преобразования в пространстве. Изучить способ получения проекций с помощью матрицы 4x4. Написать и отладить программу для 3D преобразований.

Последнее изменение этой страницы: 2016-06-10

lectmania.ru. Все права принадлежат авторам данных материалов. В случае нарушения авторского права напишите нам сюда...