Сделай Сам Свою Работу на 5

Схема программного обеспечения





 

Для реализации данного курсового проекта был выбран язык С# .NET Framework 4.5, IDE – Microsoft Visual Studio 2012. Использовались только стандартные библиотеки, не имеющие отношения к распознаванию.

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

Рисунок 4.1.1 – Схема приложения.
4.2 Диаграммы классов, функций и методов

 

Рис. 4.2.1 Диаграммы классов и методов

Рисунок 4.2.2 – Диаграмма используемых классов и методов

Основные классы для работы с изображением.

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

Класс EditPictureForm класс формы для редактирования изображения

Класс Hand содержит в себе всю информацию о ладони человека.

Класс finger – содержит информацию о пальце

Класс FingerName – имя каждого пальца в соответствии с его номером.

Перечисление HandOrientation – для определения положения руки (правая или левая).

Класс fingerDifference – класс для вычисления разницы между пальцами.

Перечисление TypeOfImage для определения типа изображения (серое, бинарное, цветное или неопределено)

ImageClass – класс в котором находятся основные поля для работы с персептроном.



Perseptron – класс для обучения и распознавания изображения.

ImageObject – класс изображения для персептрона.

 


 

Основные методы для работы с изображением

 

AddClass() – метод добавления класса в персептрон.

Recognize() – метод распознавания класса персептроном.

FindAverageBrightness() – находит средние значения яркостей изображения.

SearchPixels() – находит крайние чёрные пиксели изображения(по ширине и высоте).

ShowBorder() – отображает контур ладони.

BinaryByLip() – бинаризация по порогу.

RotateImage – поворот изображения.

GetHandsListInfo() – собирает всю информация о признаках и выводит в таблицу.

FindTopOfFingers() – находит кончики пальцев.

FindMaxWidthOfHand() – находит максимальную ширину руки.

CutCarpus – обрезает запястье.

SetToClass() – метод обучения изображения.

FindEthalons() – находит эталоны для всех объектов.

CreateImageOnBorder() – метод построения нового изображения, растянутого пропорционально на основании границ ладони.

MakeOperationWithImage() – сохраняет операцию в историю.

OpenAndLoadImage() – загрузка изображения.



AddImageToList() – добавляет картинку в список картинок.

Тестирование и руководство пользователя

 

После запуска приложения осуществляется обучение программы. Для этого необходимо нажать «Load images to learning» на вкладке «Recognizing image», выбранные картинки отобразятся внизу программы, потом выбираем из этого списка картинки, выбираем соответствующий класс для обучения и нажимаем кнопку «Add to class». После обучения в истории обучения отобразится информация о обучении программы. Результат на рисунке 4.3.1.

Рисунок 4.3.1 – Обучение программы

 

После этого на вкладке «Processing Image» необходимо нажать «Open» (для загрузки изображения хранящегося на жестком диске). Результат выполнения представлен на рисунке 4.3.2

Рисунок 4.3.2 – Загруженное изображение

 

Далее можно запустить первый этап обработки в автоматическом режиме нажав кнопку «Automatic», после выполнения всех операций в историю запишутся основные изменения и отобразятся справа от картинки, а картинка будет обработана результат на рисунке 4.3.3.

Рисунок 4.3.3 – Изображение после обработки

Следующим этапом является нахождение расстояния между пальцами и обрезание запястья руки. Для этого выбираем «Sign processing». Результат выполнения показан на рисунке 4.3.4.

Рисунок 4.3.4 – Нахождение кончиков пальцев

После этого выбираем последнего этапа обработки без цветных полос и нажимаем кнопку «Continue processing». Картинка передаётся на следующий этап обработки.

Рисунок 4.3.5– Передача картинки на распознавание

Для распознавания ладони необходимо нажать кнопку Reognize, после чего произойдёт автоматический переход на вкладку «Recognize info», где будет отображён результат распознавания 4.3.6.



Рисунок 4.3.6 – Результат распознавания


ЗАКЛЮЧЕНИЕ

 

В ходе работы было разработано приложение, реализующее алгоритм распознавания ладоней человека. Проанализировав полученные результаты, можно сделать вывод о том, что данный метод эталонов, в который подаются признаки гораздо эффективнее персептрона, потому что при подаче изображения на вход персептрона его приходится искажать, что не всегда даёт хороший результат. В общем данную программу можно использовать для распознавания ладоней людей и определять с высокой точностью чья это ладонь, хотя программа и не гарантирует 100% результат, так как не всегда подаются корректные данные.

 


ЛИТЕРАТУРА

 

1. Ковалева И.Л., «Алгоритмы обработки изображений», БНТУ, 2007

2. Фисенко В.Т., Фисенко Т. Ю., «Компьютерная обработка и распознавание образов», Санкт-Петербург, 2008

3. Гонсалес Р., Вудс Р., «Цифровая обработка изображений», Москва 2005

4. Контурный анализ http://habrahabr.ru/post/118486/

5. Применение нейросети в распознавании изображений http://habrahabr.ru/post/74326/

6. Распознавание цифр с помощью однослойного персептрона (с примером) http://habrahabr.ru/post/74865/

7. Нейронные сети http://nncourse.chat.ru/

 

ПРИЛОЖЕНИЕ

 

Листинг основных методов:

public class GraphicProcessor

{

 

public int xx = 999;

public int yy = 999;

public int xx1 = 0;

public int yy1 = 0;

public Bitmap mainBitmap;

public Bitmap grayBitmap;

public Bitmap binaryBitmap;

public int[,] binaryArray;

public int[,] grayArray;

private int[,] borderArray;

 

 

public int[,] BorderArray

{

get

{

return borderArray;

}

}

 

public GraphicProcessor(Bitmap bitmap)

{

InitProcessor(bitmap);

}

 

public Bitmap ResizeImage(Image original, int width, int height)

{

double zoomCoefficient = (double)original.Width / width > (double)original.Height / height

? (double)original.Width / width

: (double)original.Height / height;

 

return new Bitmap(original, (int)(original.Width / zoomCoefficient), (int)(original.Height / zoomCoefficient));

}

 

private void InitProcessor(Bitmap bitmap)

{

int grayInt;

 

InitializeBitmapsAndArrays(bitmap);

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

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

{

grayInt = (mainBitmap.GetPixel(i, j).R + mainBitmap.GetPixel(i, j).G +

mainBitmap.GetPixel(i, j).B) / 3;

SetGrayVariables(i, j, grayInt);

SetBinaryVariables(i, j, grayInt, 90);

}

 

}

 

private void SetGrayArray(Bitmap bitmap)

{

int grayInt;

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

{

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

{

grayInt = (mainBitmap.GetPixel(i, j).R + mainBitmap.GetPixel(i, j).G + mainBitmap.GetPixel(i, j).B) / 3;

SetGrayVariables(i, j, grayInt);

}

}

}

 

private bool InitializeBitmapsAndArrays(Bitmap image)

{

if (image != null)

{

 

mainBitmap = ResizeImage(image, 400, 400);

binaryBitmap = new Bitmap(mainBitmap.Width, mainBitmap.Height);

grayBitmap = new Bitmap(mainBitmap.Width, mainBitmap.Height);

binaryArray = new int[mainBitmap.Width, mainBitmap.Height];

grayArray = new int[mainBitmap.Width, mainBitmap.Height];

return true;

}

return false;

}

 

public void SetBinaryVariables(int x, int y, int grayInput, int lip)

{

int binaryColorInt;

binaryColorInt = (grayInput > lip ? 1 : 0) == 0 ? 255 : 0;

binaryBitmap.SetPixel(x, y, Color.FromArgb(binaryColorInt, binaryColorInt, binaryColorInt));

binaryArray[x, y] = binaryColorInt;

}

 

public void SetGrayVariables(int x, int y, int grayInput)

{

grayArray[x, y] = grayInput;

grayBitmap.SetPixel(x, y, Color.FromArgb(grayInput, grayInput, grayInput));

}

 

/// <summary>

/// Высчитывает угол между первой и последней точками

/// </summary>

/// <param name="x1"></param>

/// <param name="y1"></param>

/// <param name="x2"></param>

/// <param name="y2"></param>

/// <returns>возвращает угол</returns>

public double CalculateAngle(int x1, int y1, int x2, int y2)

{

double angle = 0;

double tango;

int yyy;

int xxx;

yyy = y2 - y1;

 

xxx = x2 - x1;

 

tango = (double)yyy / xxx;

angle = Math.Atan(tango) * (180 / Math.PI); // 180/пи сука

 

return angle;

}

 

/// <summary>

/// Отображает массив байтов изображения

/// </summary>

/// <param name="inputBitmap">входная картинка</param>

/// <param name="binaryArray">бинарный массив картинки</param>

/// <returns></returns>

public String ShowBitmapBytes(Bitmap inputBitmap, int[,] binaryArray)

{

StringBuilder builder = new StringBuilder();

 

int column = 0;

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

{

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

{

if (column % 30 == 0)

{

builder.Append(String.Format("\r\n{0,8}", binaryArray[i, j]));

}

else

{

builder.Append(String.Format("{0,8}", binaryArray[i, j]));

}

 

column++;

 

}

}

 

return builder.ToString();

}

 

/// <summary>

/// Строит сеть на картинке

/// </summary>

/// <param name="inputBitmap"> входная картинка</param>

/// <param name="binaryArray"> бинарный массив </param>

/// <param name="squaresInWidth">колличество квадратов в ширине картинки</param>

/// <returns>Возвращает картинку с сетью</returns>

public Bitmap BuildNetwork(Bitmap inputBitmap, int[,] binaryArray, int squaresInWidth)

{

int colorOfPixel;

int squareSize = inputBitmap.Width / squaresInWidth;

 

Bitmap tempBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);

 

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

{

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

{

// colorOfPixel = binaryArray[i, j] == 0 ? 255 : 0;

 

colorOfPixel = inputBitmap.GetPixel(i, j).R == 0 ? 0 : 255;

 

if ((j != 0 && j % squareSize == 0) | (i != 0 && i % squareSize == 0))

{

tempBitmap.SetPixel(i, j, Color.FromArgb(200, 40, 60));

}

else

{

tempBitmap.SetPixel(i, j, Color.FromArgb(colorOfPixel, colorOfPixel, colorOfPixel));

}

}

}

 

return tempBitmap;

}

 

/// <summary>

/// Повернуть изображение

/// </summary>

/// <param name="input"> входная картинка</param>

/// <param name="angle"> угол поворота</param>

/// <returns> Возвращает повёрнутую картинку</returns>

public Bitmap RotateImage(Bitmap input, float angle)

{

Bitmap result = new Bitmap(input.Width, input.Height);

Graphics g = Graphics.FromImage(result);

g.TranslateTransform((float)input.Width / 2, (float)input.Height / 2);

g.RotateTransform(angle);

g.TranslateTransform(-(float)input.Width / 2, -(float)input.Height / 2);

g.DrawImage(input, new Point(0, 0));

return result;

}

 

/// <summary>

/// Бинаризация по порогу

/// </summary>

/// <param name="lip"> порог бинаризации</param>

/// <param name="invert"> инвертировать цвет или нет</param>

/// <param name="inputBitmap">входная картинка</param>

/// <param name="grayArray"> массив полутоновых серых пикселей изображения</param>

/// <param name="binaryArray">бинарный массив изображения</param>

/// <returns>Возвращает новую картинку с бинаризацией по заданному порогу</returns>

public Bitmap BinaryByLip(int lip, bool invert, Bitmap inputBitmap, ref int[,] binaryArray)

{

bool IsWhite;

int binaryColorInt;

int grayInt;

 

binaryArray = new int[inputBitmap.Width, inputBitmap.Height];

 

Bitmap tempBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);

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

{

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

{

 

grayInt = (inputBitmap.GetPixel(i, j).R + inputBitmap.GetPixel(i, j).G + inputBitmap.GetPixel(i, j).B) / 3;

IsWhite = grayInt > lip;

 

binaryColorInt = IsWhite ? 255 : 0;

tempBitmap.SetPixel(i, j, Color.FromArgb(binaryColorInt, binaryColorInt, binaryColorInt));

binaryArray[i, j] = binaryColorInt;

}

}

return tempBitmap;

}

 

 

public Bitmap BinaryGray(Bitmap inputBitmap)

{

bool IsWhite;

int binaryColorInt;

int grayInt;

 

Bitmap tempBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);

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

{

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

{

grayInt = (inputBitmap.GetPixel(i, j).R + inputBitmap.GetPixel(i, j).G + inputBitmap.GetPixel(i, j).B) / 3;

if (grayInt > 200)

{

tempBitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));

}

else

{

tempBitmap.SetPixel(i, j, Color.FromArgb(0, 0, 0));

}

 

}

}

return tempBitmap;

}

 

 

/// <summary>

/// Показать границу изображения

/// </summary>

/// <param name="isWhite"> белую или чёрную границу показывать?</param>

/// <param name="binaryBitmap"> бинаризованная картинка</param>

/// <param name="binaryArray"> бинарный массив</param>

/// <returns>Возвращает картинку с очерченым контуром</returns>

public Bitmap ShowBorder(Bitmap binaryBitmap, int[,] binaryArray)

{

Bitmap tempBitmap = new Bitmap(binaryBitmap.Width, binaryBitmap.Height);

borderArray = new int[binaryBitmap.Width, binaryBitmap.Height];

 

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

{

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

{

if (i != 0 && i < binaryBitmap.Width - 1 && j != 0 && j < binaryBitmap.Height - 1)

{

if (

(binaryArray[i - 1, j] == binaryArray[i, j] && binaryArray[i + 1, j] == binaryArray[i, j])

&& (binaryArray[i, j - 1] == binaryArray[i, j] && binaryArray[i, j + 1] == binaryArray[i, j])

&& (binaryArray[i - 1, j - 1] == binaryArray[i, j] && binaryArray[i + 1, j + 1] == binaryArray[i, j])

&& (binaryArray[i + 1, j - 1] == binaryArray[i, j] && binaryArray[i - 1, j + 1] == binaryArray[i, j])

)

{

tempBitmap.SetPixel(i, j, Color.FromArgb(0, 0, 0));

borderArray[i, j] = 1;

}

 

else

{

tempBitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));

borderArray[i, j] = 0;

}

}

}

}

 

return tempBitmap;

}

 

public Bitmap InvertBorder(Bitmap bitmapWithBorder, int[,] binaryArray)

{

if (bitmapWithBorder == null)

return null;

 

Bitmap tempbitmap = new Bitmap(bitmapWithBorder.Width, bitmapWithBorder.Height);

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

{

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

{

tempbitmap.SetPixel(i, j, binaryArray[i, j] != 1 ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255));

 

if (i == 0 | i == bitmapWithBorder.Width - 1)

{

tempbitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));

}

if (j == 0 | j == bitmapWithBorder.Height - 1)

{

tempbitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));

}

}

}

return tempbitmap;

}

 

public void SearchPixels(Bitmap inputBitmap)

{

xx = 999;

yy = 999;

xx1 = 0;

yy1 = 0;

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

{

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

{

if ((inputBitmap.GetPixel(i, j).R < 255 && yy > j))

{

yy = j;

}

 

if ((inputBitmap.GetPixel(i, j).R < 255 && yy1 < j))

{

 

yy1 = j;

}

 

if ((inputBitmap.GetPixel(i, j).R < 255 && xx > i))

{

xx = i;

}

 

if ((inputBitmap.GetPixel(i, j).R < 255 && xx1 < i))

{

xx1 = i;

}

}

}

}

 

private int FindAverageBrightness()

{

int Sum = 0;

int countOfPixels = 0;

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

{

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

{

Sum += grayArray[i, j];

countOfPixels++;

}

}

return Sum / countOfPixels;

}

 

public Bitmap AutoBinarisation(bool invert, Bitmap inputBitmap, int[,] grayArray, ref int[,] binaryArray)

{

return BinaryByLip(FindAverageBrightness(), invert, inputBitmap, ref binaryArray);

}

}

 

public static class BmpConverter

{

public static void Convert(String file, String pathToSave)

{

Bitmap myBitmap;

myBitmap = new Bitmap(file);

myBitmap.Save(pathToSave, ImageFormat.Jpeg);

}

}

 

#region Perseptron

static class Const

{

public static int Aj = 180;

public static int Porog = 1;

public static int Xi = 400 * 400;

}

 

class ImageObject

{

public ImageObject(Image image)

{

int count = 0;

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

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

{

X[count++] = ((Bitmap)image).GetPixel(i, j).R == 0 ? 1 : 0;

}

}

 

public int[] X = new int[Const.Xi];

public decimal[] SUM = new decimal[Const.Aj];

public int[] Y = new int[Const.Aj];

}

 

class ImageClass

{

Random rnd = new Random();

public ImageClass(string name)

{

Name = name;

I.Add(new double[Const.Aj]);

for (int i = 0; i < Const.Aj; i++)

{

I[0][i] = rnd.Next(-3, 3) > 0 ? 1 : -1;

}

 

}

 

public string Name;

public List<ImageObject> ImageList = new List<ImageObject>();

public List<double[]> I = new List<double[]>();

public double[] YI = new double[Const.Aj];

public double SUMREC;

}

 

class Perseptron

{

public List<ImageClass> ImageClassList = new List<ImageClass>();

public double[,] A = new double[Const.Xi, Const.Aj];

public ImageObject RecImage;

Random rnd = new Random();

public int PictureCount = 1;

 

public Perseptron()

{

ImageClassList.Add(new ImageClass("Sergei"));

ImageClassList.Add(new ImageClass("Petya"));

ImageClassList.Add(new ImageClass("Mother"));

ImageClassList.Add(new ImageClass("Lekha"));

ImageClassList.Add(new ImageClass("Gena"));

 

for (int i = 0; i < Const.Xi; i++)

{

A[i, rnd.Next(0, Const.Aj)] = rnd.Next(-1, 1) == 0 ? -1 : 1;

}

}

 

public ImageObject AddClass(int ClassNumber, Image image)

{

ImageObject io = new ImageObject(image);

ImageClassList[ClassNumber].ImageList.Add(io);

PictureCount++;

 

foreach (ImageClass imageClass in ImageClassList)

{

imageClass.I.Add(new double[Const.Aj]);

for (int i = 0; i < Const.Aj; i++)

imageClass.I[imageClass.I.Count - 1][i] = imageClass.I[imageClass.I.Count - 2][i];

}

 

for (int i = 0; i < Const.Aj; i++)

{

decimal sum = 0;

for (int j = 0; j < Const.Xi; j++)

{

sum += (decimal)(io.X[j] * A[j, i]);

}

io.SUM[i] = sum;

if (io.SUM[i] - Const.Porog >= 0)

{

io.Y[i] = 1;

for (int j = 0; j < ImageClassList.Count; j++)

{

ImageClassList[j].I[ImageClassList[j].I.Count - 1][i] = ImageClassList[j].I[ImageClassList[j].I.Count - 2][i] + (j == ClassNumber ? 1 : -1);

}

}

}

return io;

}

 

 

public string Recognize(Image image)

{

string ClassRec;

RecImage = new ImageObject(image);

 

foreach (ImageClass imageClass in ImageClassList)

imageClass.SUMREC = 0;

 

for (int i = 0; i < Const.Aj; i++)

{

decimal sum = 0;

 

for (int j = 0; j < Const.Xi; j++)

{

sum += (decimal)(RecImage.X[j] * A[j, i]);

}

RecImage.SUM[i] = sum;

if (RecImage.SUM[i] - Const.Porog >= 0)

{

RecImage.Y[i] = 1;

for (int j = 0; j < ImageClassList.Count; j++)

{

ImageClassList[j].YI[i] = ImageClassList[j].I[ImageClassList[j].I.Count - 1][i] * RecImage.Y[i];

ImageClassList[j].SUMREC += ImageClassList[j].YI[i];

}

}

}

 

double SUMA = ImageClassList[0].SUMREC;

ClassRec = ImageClassList[0].Name;

 

foreach (ImageClass imageClass in ImageClassList)

{

if (SUMA < imageClass.SUMREC)

{

SUMA = imageClass.SUMREC;

ClassRec = imageClass.Name;

}

}

return ClassRec;

}

}

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.