Для принятия решения используется программное решение на языке программирования C#. Процесс принятия решения состоит из двух этапов:
· поиска границы изображения, изображенного на рисунке 5.1. На рисунках 5.2, 5.3, 5.4, 5.5 представлена детализация блоков;
· определения вида гриба, изображенного на рисунка 5.6 и 5.7.
Рис. 5.1. Алгоритм поиска границы
Рис. 5.2. Алгоритм Собеля
Рис. 5.3. Алгоритм ЛБШ
Рис. 5.4. Вычисление Мат. Ожидания
Рис. 5.5. Вычисление Дисперсии
Рис. 5.6. Алгоритм определения вида гриба
Рис. 5.7. Алгоритм выделения границы
Пример использования программного средства представлен на рисунках 5.8 – 5.11.
Рис. 5.8. Общий вид программы
На рисунке 5.8. представлен общий вид программного средства. Для загрузки изображений (формат .bmp) необходимо нажать клавишу «Загрузить». Загрузка изображения показана на рисунке 5.9. После загрузки и обработки изображений у пользователя есть возможность просмотреть изображения и их параметры. Для перехода от одного изображения выборки к другому, необходимо воспользоваться клавишами перехода, изображенных на рисунке 5.10. После загрузки изображения, пользователь может вывести на экран акт и накладную для данной выборки, изображенных на рисунках 5.11 и 5.12 соответственно.
Рис. 5.9. Выбор изображения
Рис. 5.10. Просмотр изображения
Рис. 5.11. Закупочный акт
Рис. 5.12. Накладная
Заключение
В данном проекте была разработана автоматизированная интеллектуальная информационная система сортировки грибов.
В процессе работы был произведен анализ предметной области и определены цели и задачи АИИС.
Был разработан технологический процесс обработки данных, концептуальное и логическое проектирование реляционной БД.
Была разработана программа для сортировки грибов.
Внедрение АИИС позволит сортировать грибы с минимальным привлечением человеческих ресурсов, что позволит в перспективе уменьшить затраты на сортировку, так же увеличится качество и скорость сортировки.
Conclusion
In this project, an automated intellectual information system for sorting mushrooms has been developed.
In the process of work, the domain was analyzed and AIIS goals and objectives were defined.
The technological process of data processing was developed, the conceptual and logical design of a relational database.
A program for sorting mushrooms was developed.
The introduction of AIIS will make it possible to sort the mushrooms with minimal human resources, which will in the long run reduce the cost of sorting, as will the quality and speed of sorting.
Приложение 1. Словарь терминов
Таблица «Словарь терминов»
Код понятия | Наименование понятия | Определение, пояснение |
0001 | Артель | Добровольное объединение людей для совместной работы или иной коллективной деятельности, часто с участием в общих доходах и общей ответственностью на основе круговой поруки. |
0002 | Белый гриб | Гриб из рода Боровик. |
0003 | Вид | Совокупность близких по происхождению организмов, относительно схожих в морфофизиологическом отношении |
0004 | Выплата | Выплаченные деньги. Очередные выплаты. |
0005 | Граница | Реальная или воображаемая линия в пространстве или во времени, отделяющая один объект (тело, процесс или состояние) от другого. |
0006 | Грибы | Царство живой природы, объединяющее эукариотические организмы, сочетающие в себе некоторые признаки как растений, так и животных. |
0007 | Доставка | Подача, поставка, снабжение, обеспечение. |
0008 | Заготовитель | Лицо, организация, производящие государственные или кооперативные заготовки чего-нибудь |
0009 | Закупочный акт | Составляется в двух экземплярах в момент совершения закупки сельхозпродуктов у населения (продавца) представителем организации. Подписывается лицом, закупившим продукты, и продавцом. Утверждается руководителем организации. |
0010 | Изображение | Одна из разновидностей информационной модели, в которой используется картинный (наглядный) способ представления информации оператору. |
0011 | Маслята | Род трубчатых съедобных грибов семейства Болетовые (лат. Boletaceae). Своё название получил из-за маслянистой, скользкой на ощупь шляпки. |
0012 | Накладная | Документ, используемый при передаче товарно-материальных ценностей от одного лица другому. |
0013 | Параметр | Величина, значения которой служат для различения элементов некоторого множества между собой. |
0014 | Получить | Взять, приобрести вручаемое, предлагаемое, искомое |
0015 | Процесс | Совокупность взаимосвязанных действий, приводящих к смене состояний |
0016 | Регистрировать | Записывать, отмечать с целью учёта, придания законной силы, научного наблюдения и т. п. |
0017 | Сбор грибов | Деятельность человека, направленная на поиск грибов. Является разновидностью собирательства. |
0018 | Сортировка | Процесс перегруппировки заданного множества объектов в некотором определенном порядке.Сортировка предпринимается для того, чтобы облегчить последующий поиск элементов в отсортированноммножестве. |
0019 | Сортировщик | Работник, отвечающий за работу конвейера. |
0020 | Сумма | Общее количество чего-нибудь. |
0021 | Транспортёр | Конвейер для перемещения грузов. |
0022 | Формирование | Создание, составление. |
0023 | Холодильная камера | Теплоизолированный контейнер, поддерживающий низкую температуру для хранения скоропортящихся продуктов питания и других веществ. |
Приложение 2. Контрольный пример базы данных
Рис. 1. Таблица «Выборка входных данных»
Рис. 2. Таблица «Признаки изображения»
Рис. 3. Таблица «Правила принятия решения»
Рис. 4. Таблица «Товар»
Рис. 5. Таблица «Контейнер»
Рис. 6. Таблица «Контейнеры в накладной»
Рис. 7. Таблица «Накладная»
Рис. 8. Таблица «Акт»
Рис. 9. Таблица «Контейнеры в Актах»
Приложение 3. Листинг Программы
namespace KurceWork
{
public partial class Form1 : Form
{
private Bitmap imageBitmap;
private MyImage image;
private MyImage[] images;
private bool isLoad = false;
private byte position = 0;
//private List<Nakladnaya> listNa = new List<Nakladnaya>();
private Nakladnaya na, act;
private List<Int32> goodBox = new List<Int32>();
private List<Int32> badBox = new List<Int32>();
private double badMas = 0;
private double goodMas = 0;
private int idNa = -1;
private int idAct = -1;
public Form1()
{
InitializeComponent();
openFileDialog1.Filter = "Image Files(*.BMP)|*.BMP";
folderBrowserDialog1.SelectedPath = "D:\\Program\\C Sharp\\Kurse_Work_IIS\\KurceWork\\KurceWork\\bin\\Debug\\images";
}
//загрузка изображения (старое)
private void oldLoadImage()
{
if (openFileDialog1.ShowDialog() == DialogResult.Cancel)
return;
//читаем изображение в битмап
imageBitmap = new Bitmap(openFileDialog1.FileName);
pictureBox1.Image = imageBitmap;
string name = openFileDialog1.FileName;
int t = name.LastIndexOf("\\");
Text = name.Substring(t + 1);
//исходное изображение в объект типа MyImage
image = new MyImage((Bitmap)pictureBox1.Image);
//устанавливаем первое преобразование (собель)
image.setFirstTransform(Transform.sobelTransform(image.getSrc()));
//устанавливаем второе преобразование (робертс)
image.setSecondTransform(Transform.robertsTransform(image.getSrc()));
//pictureBox1.Image = Transform.calculate(image);
pictureBox1.Image = Transform.anotherWay(image);
//pictureBox1.Image = Transform.secondAnotherWay(image);
//pictureBox1.Image = Transform.carrot();
//d
label1.Text = string.Format("D = {0:0.####}", image.getD());
//v
label2.Text = string.Format("V = {0:0.####}", image.getV());
//mas
label3.Text = string.Format("Mas = {0:0.####}", image.getMas());
//disp
label4.Text = string.Format("Disp = {0:0000}", image.getDisp());
//rotten
bool rotten = image.getDisp() > 1380 ? true : false;
label5.Text = string.Format("Rotten = {0}", rotten.ToString());
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void groupBox2_Enter(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label5_Click(object sender, EventArgs e)
{
}
//загрузка папки с изображениями
private void button2_Click(object sender, EventArgs e)
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.Cancel)
return;
//путь к папке
string folder = folderBrowserDialog1.SelectedPath;
//пути всех изображений в папке
string[] images = Directory.GetFiles(@folder, "*.bmp");
MyImage[] imagesFromFolder = new MyImage[images.Length];
goodBox.Clear();
badBox.Clear();
TestDB tdb = new TestDB();
//читаем изображение в битмап и устанавливаем преобразования
for (int i = 0; i < images.Length; i++)
{
Text = string.Format("Загрузка {0} изображения из {1}", (i+1), images.Length);
//загрузка оригинального изображения
imagesFromFolder[i] = new MyImage(new Bitmap(images[i]));
//сохранение первого преобразования
imagesFromFolder[i].setFirstTransform(Transform.sobelTransform(new Bitmap(images[i])));
//сохранение второго преобразования
imagesFromFolder[i].setSecondTransform(Transform.robertsTransform(new Bitmap(images[i])));
//сохранение результата
imagesFromFolder[i].setResult(Transform.anotherWay(imagesFromFolder[i]));
//установка id
imagesFromFolder[i].setId(i);
if (imagesFromFolder[i].getDisp() > 1450)
{
badMas += imagesFromFolder[i].getMas();
}
else
{
goodMas += imagesFromFolder[i].getMas();
}
}
Text = "";
pictureBox1.Image = imagesFromFolder[0].getResult();
position = 0;
isLoad = true;
//d
label1.Text = string.Format("Диаметр: {0:0.####}", imagesFromFolder[0].getD());
//v
label2.Text = string.Format("Объем: {0:0.####}", imagesFromFolder[0].getV());
//mas
label3.Text = string.Format("Вес: {0:0.####}", imagesFromFolder[0].getMas());
//disp
label4.Text = string.Format("Дисперсия: {0:0000}", imagesFromFolder[0].getDisp());
//rotten
string rotten = imagesFromFolder[0].getDisp() > 1450 ? "Белый" : "Маслята";
label5.Text = string.Format(rotten.ToString());
///////////////////////////////////////////////////////
//ящики
badBox.Add(tdb.save_Box(2, badMas));
goodBox.Add(tdb.save_Box(1, goodMas));
//создание новой накладной
idNa = tdb.save_Na(1, goodBox.Count);
//создание нового акта
idAct = tdb.save_Act(2, badBox.Count);
//создание записей ЯщикиВнакладной
foreach (int idBox in goodBox)
{
tdb.save_Box_in_Na(idNa, idBox);
}
foreach (int idBox in badBox)
{
tdb.save_Box_in_Act(idAct, idBox);
}
//передача накладной в форму
na = new Nakladnaya(idNa, "Белый гриб", "шт.", goodBox.Count, 150, 150 * goodMas * goodBox.Count, goodMas);
//передача акта в форму
act = new Nakladnaya(idAct, "Маслята", "", badBox.Count, 40, 40 * badMas * badBox.Count, badMas);
this.images = imagesFromFolder;
}
//показать следующее изображение
private void next_Click(object sender, EventArgs e)
{
if (!isLoad)
return;
position++;
if (position >= images.Length)
position = 0;
pictureBox1.Image = images[position].getResult();
//d
label1.Text = string.Format("Диаметр: {0:0.####}", images[position].getD());
//v
label2.Text = string.Format("Объем: {0:0.####}", images[position].getV());
//mas
label3.Text = string.Format("Вес: {0:0.####}", images[position].getMas());
//disp
label4.Text = string.Format("Дисперсия: {0:0000}", images[position].getDisp());
//rotten
string rotten = images[position].getDisp() > 1450 ? "Белый" : "Маслята";
label5.Text = string.Format(rotten.ToString());
}
//показать предыдущее изображение
private void prev_Click(object sender, EventArgs e)
{
if (!isLoad)
return;
if (position - 1 >= 0)
position--;
else
position = (byte) (images.Length - 1);
pictureBox1.Image = images[position].getResult();
//d
label1.Text = string.Format("Диаметр: {0:0.####}", images[position].getD());
//v
label2.Text = string.Format("Объем: {0:0.####}", images[position].getV());
//mas
label3.Text = string.Format("Вес: {0:0.####}", images[position].getMas());
//disp
label4.Text = string.Format("Дисперсия: {0:0000}", images[position].getDisp());
//rotten
string rotten = images[position].getDisp() > 1450 ? "Белый" : "Маслята";
label5.Text = string.Format(rotten.ToString());
}
//печать накладной
private void button3_Click(object sender, EventArgs e)
{
if (!isLoad)
return;
Form2 form2 = new Form2(na);
form2.Show();
}
//печать акта
private void button1_Click(object sender, EventArgs e)
{
if (!isLoad)
return;
Form3 form3 = new Form3(act);
form3.Show();
}
private void button4_Click(object sender, EventArgs e)
{
TestDB dbt = new TestDB();
//dbt.go2();
}
private void label2_Click(object sender, EventArgs e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace KurceWork
{
class Transform
{
public static Bitmap sobelTransform(Bitmap src)
{
Bitmap bitmap = (Bitmap) src.Clone();
Color Pixel;
int R = 0;
int G = 0;
int B = 0;
//Создание массива массивов яркостей пикселей изображения по размеру высоты битовой матрицы
float[][] result = new float[bitmap.Height][];
//Сохранение яркости изображения в массиве
for (int y = 0; y < bitmap.Height; y++) //Для каждой строки
{
result[y] = new float[bitmap.Width];//Создание массивов по ширине битовой матрицы
for (int x = 0; x < bitmap.Width; x++) //Для каждого пикселя строки
{
Pixel = bitmap.GetPixel(x, y); //Определяем атрибут пикселя из битовой матрицы
result[y][x] = Pixel.GetBrightness();//Записываем яркость точки в массив
}
}
//Собель
int[,] gx = new int[,] {
{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }
};
int[,] gy = new int[,] {
{ 1, 2, 1 },
{ 0, 0, 0 },
{ -1, -2, -1 }
};
float new_x = 0, new_y = 0;
float rc;
for (int y = 1; y < bitmap.Height - 1; y++)
for (int x = 1; x < bitmap.Width - 1; x++)
{
new_x = 0;
new_y = 0;
rc = 0;
for (int wi = -1; wi < 2; wi++)
{
for (int hw = -1; hw < 2; hw++)
{
rc = result[y + wi][x + hw];
new_x += gx[hw + 1, wi + 1] * rc;
new_y += gy[hw + 1, wi + 1] * rc;
}
}
//1. Способ (он без порога, ограничение (255) только из-за того,
//что Color принимает на вход параметры от 0 до 255)
new_x *= 25;
new_y *= 25;
if (new_x * new_x + new_y * new_y > 255)
{
R = 255;
G = 255;
B = 255;
}
else
{
R = (int)((float)new_x * new_x + new_y * new_y);
G = (int)((float)new_x * new_x + new_y * new_y);
B = (int)((float)new_x * new_x + new_y * new_y);
}
Pixel = Color.FromArgb(0, R, G, B);
bitmap.SetPixel(x, y, Pixel);
}
//bitmap.Save("sobel.bmp"); //Сохраняем изображение в файле
return bitmap;
}
public static Bitmap robertsTransform(Bitmap src)
{
Bitmap bitmap = (Bitmap)src.Clone();
Color Pixel;
int R = 0;
int G = 0;
int B = 0;
//Создание массива массивов яркостей пикселей изображения по размеру высоты битовой матрицы
float[][] result = new float[bitmap.Height][];
//Сохранение яркости изображения в массиве
for (int y = 0; y < bitmap.Height; y++) //Для каждой строки
{
result[y] = new float[bitmap.Width];//Создание массивов по ширине битовой матрицы
for (int x = 0; x < bitmap.Width; x++) //Для каждого пикселя строки
{
Pixel = bitmap.GetPixel(x, y); //Определяем атрибут пикселя из битовой матрицы
result[y][x] = Pixel.GetBrightness();//Записываем яркость точки в массив
}
}
//ЛБШ
float roberts = 0;
float a = 0, b = 0;
for (int y = 1; y < bitmap.Height - 1; y++)
for (int x = 1; x < bitmap.Width - 1; x++)
{
a = 255 * (result[y][x] - result[y + 1][x + 1]);
b = 255 * (result[y][x + 1] - result[y + 1][x]);
roberts = (float)Math.Sqrt(a * a + b * b);
if (roberts > 255)
{
R = 255;
G = 255;
B = 255;
}
else
{
R = (int)(roberts);
G = (int)(roberts);
B = (int)(roberts);
}
Pixel = Color.FromArgb(0, R, G, B);
bitmap.SetPixel(x, y, Pixel);
}
//Сохраняем преобразованное изображение в файле
//bitmap.Save("roberts.bmp"); //Сохраняем изображение в файле
return bitmap;
}
public static int[,] getDispers(Bitmap src)
{
Bitmap bitmap = (Bitmap)src.Clone();
float[][] result = new float[bitmap.Height][];//Создание массива массивов result
Color Pixel;
for (int y = 0; y < bitmap.Height; y++) //Для каждой строки
{
result[y] = new float[bitmap.Width];//Создание массивов по ширине битовой матрицы
//Сохранение яркости точки в массиве
for (int x = 0; x < bitmap.Width; x++) //Для каждого пикселя строки
{
Pixel = bitmap.GetPixel(x, y); //Определяем атрибут пикселя из битовой матрицы
result[y][x] = Pixel.GetBrightness();//Записываем яркость точки в массив
}
}
int s = 5 / 2; //Ширина и высота полуокна
int left = 0; //Левая граница окна
int floor = 0; //Нижняя граница окна
int right = 0; //Правая граница окна
int ceil = 0; //Верхняя граница окна
int k = 0;
int[,] M = new int[bitmap.Height - 10, bitmap.Width - 10];
int[,] D = new int[bitmap.Height - 10, bitmap.Width - 10];
for (int y = 5; y < bitmap.Height-10; y++)
for (int x = 5; x < bitmap.Width-10; x++)
{
k = 0;
//Вычисление границ окна особой точки
left = x - s; if (left < 5) left = 5;
right = x + s; if (right >= bitmap.Width-5) right = bitmap.Width - 5;
ceil = y - s; if (ceil < 5) ceil = 5;
floor = y + s; if (floor >= bitmap.Height-5) floor = bitmap.Height - 5;
//вычисление Мат. Ожидания
for (int yy = ceil; yy <= floor; yy++)
for (int xx = left; xx <= right; xx++)
{
//Console.WriteLine("M = {0}; res = {1};", M[i], result[y][x]);
M[y,x] = M[y,x] + (int)((float)255 * result[yy][xx]);
k++;
}
M[y,x] = (int)((float)M[y,x] / (float)k);
//Вычисление Дисперсии
for (int yy = ceil; yy <= floor; yy++)
for (int xx = left; xx <= right; xx++)
{
D[y,x] = D[y,x] + ((int)((float)255 * result[yy][xx]) * (int)((float)255 * result[yy][xx])) - (M[y,x] * M[y,x]);
}
D[y,x] = (int)((float)D[y,x] / (float)(k - 1));
}
return D;
}
public static int[,] getMat(Bitmap src)
{
Bitmap bitmap = (Bitmap)src.Clone();
float[][] result = new float[bitmap.Height][];//Создание массива массивов result
Color Pixel;
for (int y = 0; y < bitmap.Height; y++) //Для каждой строки
{
result[y] = new float[bitmap.Width];//Создание массивов по ширине битовой матрицы
//Сохранение яркости точки в массиве
for (int x = 0; x < bitmap.Width; x++) //Для каждого пикселя строки
{
Pixel = bitmap.GetPixel(x, y); //Определяем атрибут пикселя из битовой матрицы
result[y][x] = Pixel.GetBrightness();//Записываем яркость точки в массив
}
}
int s = 5 / 2; //Ширина и высота полуокна
int left = 0; //Левая граница окна
int floor = 0; //Нижняя граница окна
int right = 0; //Правая граница окна
int ceil = 0; //Верхняя граница окна
int k = 0;
int[,] M = new int[bitmap.Height - 10, bitmap.Width-10];
for (int y = 5; y < bitmap.Height - 10; y++)
for (int x = 5; x < bitmap.Width - 10; x++)
{
//Вычисление границ окна особой точки
left = x - s; if (left < 5) left = 5;
right = x + s; if (right >= bitmap.Width - 5) right = bitmap.Width - 6;
ceil = y - s; if (ceil < 5) ceil = 5;
floor = y + s; if (floor >= bitmap.Height - 5) floor = bitmap.Height - 6;
k = 0;
//вычисление Мат. Ожидания
for (int yy = ceil; yy <= floor; yy++)
for (int xx = left; xx <= right; xx++)
{
//Console.WriteLine("x = {0}; y = {1}; xx = {2}; yy = {3}", x, y, xx, yy);
M[y,x] = M[y,x] + (int)((float)255 * result[yy][xx]);
k++;
}
M[y,x] = (int)((float)M[y,x] / (float)k);
}
return M;
}
public static int[,] getModa(Bitmap src)
{
Bitmap bitmap = (Bitmap)src.Clone();
float[][] result = new float[bitmap.Height][];//Создание массива массивов result
Color Pixel;
for (int y = 0; y < bitmap.Height; y++) //Для каждой строки
{
result[y] = new float[bitmap.Width];//Создание массивов по ширине битовой матрицы
//Сохранение яркости точки в массиве
for (int x = 0; x < bitmap.Width; x++) //Для каждого пикселя строки
{
Pixel = bitmap.GetPixel(x, y); //Определяем атрибут пикселя из битовой матрицы
result[y][x] = Pixel.GetBrightness();//Записываем яркость точки в массив
}
}
int s = 5 / 2; //Ширина и высота полуокна
int left = 0; //Левая граница окна
int floor = 0; //Нижняя граница окна
int right = 0; //Правая граница окна
int ceil = 0; //Верхняя граница окна
//int k = 0;
//int[,] M = new int[bitmap.Height - 10, bitmap.Width - 10];
int[,] Moda = new int[bitmap.Height - 10, bitmap.Width - 10];
for (int y = 5; y < bitmap.Height - 10; y++)
for (int x = 5; x < bitmap.Width - 10; x++)
{
//Вычисление границ окна особой точки
left = x - s; if (left < 5) left = 5;
right = x + s; if (right >= bitmap.Width - 5) right = bitmap.Width - 5;
ceil = y - s; if (ceil < 5) ceil = 5;
floor = y + s; if (floor >= bitmap.Height - 5) floor = bitmap.Height - 5;
//мода
int kk = 0;
Dictionary<float, int> mapModa = new Dictionary<float, int>();
for (int yy = ceil; yy <= floor; yy++)
for (int xx = left; xx <= right; xx++)
{
//мода
int freq = 0;
if (mapModa.ContainsKey((float)255 * result[yy][xx]))
{
freq = mapModa[(float)255 * result[yy][xx]];
mapModa[(float)255 * result[yy][xx]] = freq + 1;
}
else
{
mapModa.Add((float)255 * result[yy][xx], 1);
}
kk++;
}
//Мода
int mo = 0;
foreach (KeyValuePair<float, int> moda in mapModa)
{
if (moda.Value > mo)
{
Moda[y,x] = (int)moda.Key;
mo = moda.Value;
}
}
}
return Moda;
}
public static Bitmap calculate(MyImage image)
{
//загрузка изображений
Bitmap src = image.getSrc();
Bitmap firstT = image.getFirstTransform();
Bitmap secondT = image.getSecondTransform();
//загружка нужных преобразований
float[,] x1 = normalization( getMat(firstT) );
float[,] x2 = normalization(getDispers(firstT));
float[,] x3 = normalization(getModa(firstT));
float[,] polynom = new float[src.Height, src.Width];
float a00 = -0.01f;
float a01 = 1.7f;
float a02 = -0.3f;
float a03 = 0.25f;
/*
float a00 = -0.01f;
float a01 = 1.7f;
float a02 = -0.3f;
float a03 = 0.25f;
*/
for (int y = 5; y < src.Height-10; y++)
for (int x = 5; x < src.Width-10; x++)
{
polynom[y,x] = a00 + a01 * x1[y,x] + a02 * x2[y,x] + a03 * x3[y,x];
polynom[y,x] = polynom[y,x] > 0.2f? 1f:0f;
}
Color pixel;
Bitmap res = (Bitmap) src.Clone();
for (int y = 0; y < src.Height; y++)
for (int x = 0; x < src.Width; x++)
{
if (polynom[y, x] == 1f)
{
pixel = Color.Black;
}
else
pixel = src.GetPixel(x, y);
res.SetPixel(x, y, pixel);
}
res.Save("counter.bmp");
return res;
}
public static Bitmap anotherWay(MyImage image)
{
//загрузка изображений
Bitmap src = image.getSrc();
Bitmap firstT = image.getFirstTransform();
Bitmap secondT = image.getSecondTransform();
//загружка нужных преобразований
float[,] x1 = normalization(getMat(firstT));
float[,] x2 = normalization(getDispers(firstT));
float[,] x3 = normalization(getModa(firstT));
//db
TestDB tdb = new TestDB();
//запись в бд Признаков_Изображения
/*for(int y = 0; y < src.Height-10; y++)
for (int x = 0; x < src.Width-10; x++)
{
tdb.save_PriznakiIzobr(image.getId(), x, y, 0, x1[y,x]);
}*/
//загрузить коэфы полинома из бд
List<float> poly = tdb.get_Poly();
float[,] polynom = new float[src.Height, src.Width];
float a00 = poly[0];
float a01 = poly[1];
float a02 = poly[2];
float a03 = poly[3];
float a04 = poly[4];
float a05 = poly[5];
float a06 = poly[6];
float a07 = poly[7];
float a08 = poly[8];
float a09 = poly[9];
for (int y = 5; y < src.Height - 10; y++)
for (int x = 5; x < src.Width - 10; x++)
{
//polynom[y, x] = a00 + a01 * x1[y, x] + a02 * x2[y, x] + a03 * x3[y, x];
polynom[y, x] = a00 + a01 * x1[y, x] + a02 * x2[y, x] + a03 * x3[y, x] + a04 * x1[y, x] * x1[y, x] + a05 * x1[y, x] * x2[y, x] + a06 * x1[y, x] * x3[y, x] + a07 * x2[y, x] * x2[y, x] + a08 * x2[y, x] * x3[y, x] + a09 * x3[y, x] * x3[y, x];
polynom[y, x] = polynom[y, x] > 0.5f ? 1f : 0f;
//db
tdb.save_VybVhD(image.getId(), x, y, polynom[y,x]);
//tdb.save_PrResh(0, 1, 2, polynom[y, x]);
}
//left + rigth side
Color pixel;
Bitmap res = (Bitmap)src.Clone();
Bitmap dest = (Bitmap)src.Clone();
int lx = 500, rx = 0;
#region mark_border
for (int y = 0; y < src.Height; y++)
{
//left
for (int x = 0; x < src.Width; x++)
{
if (polynom[y, x] == 1f)
{
pixel = Color.Black;
res.SetPixel(x, y, pixel);
if (x < lx) lx = x;
break;
}
else
{
pixel = Color.Blue;
dest.SetPixel(x, y, pixel);
}
}
//right
for (int x = src.Width-1; x > 0 ; x--)
{
if (polynom[y, x] == 1f)
{
pixel = Color.Black;
res.SetPixel(x, y, pixel);
if (x > rx) rx = x;
break;
}
else
{
pixel = Color.Blue;
dest.SetPixel(x, y, pixel);
}
}
}
int vy = 500, ny = 0;
for (int x = 0; x < src.Width; x++)
{
//top
for (int y = 0; y < src.Height; y++)
{
if (polynom[y, x] == 1f)
{
pixel = Color.Black;
res.SetPixel(x, y, pixel);
if (y < vy) vy = y;
break;
}
else
{
pixel = Color.Blue;
dest.SetPixel(x, y, pixel);
}
}
//bottom
for (int y = src.Height-1; y > 0; y--)
{
if (polynom[y, x] == 1f)
{
pixel = Color.Black;
res.SetPixel(x, y, pixel);
if (y > ny) ny = y;
break;
}
else
{
pixel = Color.Blue;
dest.SetPixel(x, y, pixel);
}
}
}
#endregion
MyPoint point = new MyPoint(lx, rx, 40+vy, ny);
getParameters(point, dest, image);
//res.Save("counter.bmp");
return res;
}
public static float[,] normalization(int[,] b)
{
//(x-min)/(max-min)
int min = minM(b);
int max = maxM(b);
float[,] a = getFloatMas(b);
for (int y = 0; y < a.GetLength(0); y++)
for (int x = 0; x < a.GetLength(1); x++)
{
a[y, x] = (float)(a[y, x] - min) / (max - min);
}
return a;
}
public static int maxM(int[,] a)
{
int max = -10000;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
if (a[i,j] > max)
{
max = a[i,j];
}
}
return max;
}
public static int minM(int[,] a)
{
int min = 10000;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
if (a[i, j] < min)
{
min = a[i, j];
}
}
return min;
}
public static float[,] getFloatMas(int[,] a)
{
float[,] b = new float[a.GetLength(0), a.GetLength(1)];
for (int y = 0; y < a.GetLength(0); y++)
for (int x = 0; x < a.GetLength(1); x++)
b[y, x] = (float)a[y, x];
return b;
}
private static void getParameters(MyPoint point, Bitmap dest, MyImage image)
{
//Dispersia
//1. Mat
double Mat = 0;
int k = 0;
int t = 0;
for (int y = point.getMinY(); y < point.getMaxY(); y++)
for (int x = point.getMinX(); x < point.getMaxX(); x++)
{
Color currentPix = dest.GetPixel(x, y);
if (currentPix != Color.Blue && currentPix != Color.Black)
{
float ff = currentPix.GetBrightness() * 255f;
if (ff < 100f) t++;
Mat = Mat + currentPix.GetBrightness()*255f;
k++;
}
}
Mat = Mat / k;
//2. Disp
double Disp = 0;
for (int y = point.getMinY(); y < point.getMaxY(); y++)
for (int x = point.getMinX(); x < point.getMaxX(); x++)
{
Color currentPix = dest.GetPixel(x, y);
if (currentPix != Color.Blue && currentPix != Color.Black)
{
Disp = Disp + (currentPix.GetBrightness() * 255f) * (currentPix.GetBrightness() * 255f) - Mat * Mat;
}
}
Disp = Disp / (k - 1);
image.setDisp(Disp);
//diametr = max_x - min_x
double d = (point.getMaxX() - point.getMinX()) / 2000.0; //20 пикс = 1см -> /100 перевод в метры
d = d > 0.20 ? d - 0.06 : d;
d = d > 0.15 ? d - 0.02 : d;
image.setD(d);
//V = (pi*D^3)/6
double v = (Math.PI * Math.Pow(d, 3)) / 6.0;
image.setV(v);
//m = V * ro
double mas = 0;
if (Disp < 1450)
{
mas = v * 420.0;
}
else
{
mas = v * 320.0;
}
image.setMas(mas);
//dest.Save("blue.bmp");
}
}
}
Дата: 2018-12-28, просмотров: 451.