
- •Дослідження основних проблем предметної області
- •Роль інформаційних технологій у предметній області
- •Загальний опис проблем предметної області.
- •Актуальність даної теми.
- •Аналіз існуючих аналогів
- •Метод Віоли-Джонса
- •Метод surf
- •Метод sift
- •Метод orc
- •Порівняльна характеристика
- •Мета кваліфікаційної роботи
- •Постановка задачі
- •Об’єкт та методи дослідження
- •Програмна підтимка дослідження
- •Інформаційна модель системи
- •Детальний опис реалізації основних процедур та функцій додатку з прикладами.
- •Рекомендації по впровадженню та використанню
- •Порівняльний аналіз методів
- •Оцінка складності алгоритму контурного аналізу
- •Аналіз продуктивності методів
- •Рекомендаціі до використання методів
- •Охорона праці
- •Економічна частина диплому
- •Цивільний захист
- •Наукова новизна та практичне значення одержаних результатів
- •Перелік використаних джерел
- •Додаток a
- •Додаток b
Детальний опис реалізації основних процедур та функцій додатку з прикладами.
class Contours implements Runnable {
В цьому потоці реалізовано алгоритм детектування об’єктів за іх контурів.
Тут об’являються два фрейми в першому буде відображатися зображення з знайденим об’єктом, в другому будуть відображатися контури зображення. Це необхідно для того щоб можна було стежити за поведінкою зображення під час підбирання оптимальних настройок.
CanvasFrame frame;
CanvasFrame frame2;
Змінна stoped необхідна для синхронного завершення потоку.
static boolean stoped;
public void run() {
В методі run() реалізоване тіло програми. Для початку створюються екземпляри об’єктів CanvasFram, і встановлюється дія при натисканні кнопки в правому верхньому куті вікна.
frame = new CanvasFrame("Main Frame");
frame2 = new CanvasFrame("Gray Frame");
stoped = false;
frame.setDefaultCloseOperation(CanvasFrame.EXIT_ON_CLOSE);
frame2.setDefaultCloseOperation(CanvasFrame.EXIT_ON_CLOSE);
try {
Створюється обєкт OpenCVFrameGrabber, за вдяки якому можна отримати зображення з відеокамери або відео файлу. В якості параметра передається номер пристрою тобто відеокамери. Якщо на комп’ютері декілька камер, то можна вибирати будь яку з них перша камера має нульовий номер, друга одиницю, і так далі. Якщо потрібно отримати відео з файлу, то вказується в якості параметра шлях до файлу. Так як можуть виникнути проблеми з відеокамерою, або з відео файлом, цей блок коду поміщається у в оператор try {}
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start(); //запуск грабера
while (!stoped) {
Поки потік працює, виймається зображення з відео потоку і перевіряється чи не є воно null.
IplImage Grab = grabber.grab();
if (Grab == null)
return;
Якщо зображення коректно було отримано з пристрою або з файлу, воно передається функції Detect(Grab) в якості параметру, для подальшої обробки, а після обробки буде повернуто в якості результату функції.
Grab = Detect(Grab);
Метод showImage(Grab) прорисовує зображення на фрейм.
frame.showImage(Grab);
}
} catch (Exception e) {
Якщо виникла якась помилка підчас зчитування даних виконується блок catch, і печатається детальний опис помилки.
e.printStackTrace();
} finally {
Цей блок виконується в будь якому випадку. Він знищує створені фрейми, після чого робота потоку завершеється.
frame.dispose();
frame2.dispose();
}
}
Метод stop() використовується для синхронного завершення роботи.
public void stop() {
stoped = true;
}
public IplImage Detect(IplImage Grab) {
В цій функції реалізовано саме серце методу виявлення об’єктів за їх контурами.
Створюється місце в пам’яті де будуть зберігатися знайдені контури під час їх обробки.
CvMemStorage storage = CvMemStorage.create(0);
Створюється екземпляр об’єкту CvSeq який описує послідовність точок контуру.
CvSeq contour = new CvSeq(null);
Створюється екземпляр об’єкту, завдяки якому можна отримати моменти контуру, для подальшої їх обробки.
CvMoments moments = new CvMoments();
Створюються два екземпляри об’єкту CvHuMoments, один для описання шаблону, а інший для знайдених контурів.
CvHuMoments hu_moments = new CvHuMoments();
CvHuMoments hu_templ = new CvHuMoments();
try {
Зчитуються з файлу сім чисел, для ініціалізації об’єкта CvHuMoments. Так як існує вірогідність виникнення помилок при зчитування з файлу, цей блок поміщується у блок try.
Scanner fileScan = new Scanner(new BufferedReader(new FileReader(
"C:\\moments.txt")));
if (fileScan.hasNext())
hu_templ.hu1(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu2(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu3(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu4(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu5(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu6(fileScan.nextDouble());
if (fileScan.hasNext())
hu_templ.hu7(fileScan.nextDouble());
} catch (Exception e) {
}
//створюється екземпляр IplImage у якому буде зберігатися зображення у відтінках сірого. Одразу передаються розміри зображення, вказується що воно 8-ми бітне, а кількість каналів дорівнює 1.
IplImage gray = IplImage.create(Grab.width(), Grab.height(),
IPL_DEPTH_8U, 1);
if (Grab == null) {
System.err.println("Невозможно загрузить изображение.");
} else {
Функція cvCvtColor конвертує вхідне зображення в відтінки сірого. Вказується в якості параметрів вхідне зображення, вихідне, та метод конвертації у даному випадку з RGB в відтінки сірого.
cvCvtColor(Grab, gray, CV_BGR2GRAY);
Функція cvSmooth виконує розмиття зображення, в даному випадку розмиття по Гаусу. В якості параметрів отримує вхідне зображення, вихідне зображення тут воно теж саме, і ступінь розмиття, наступні три параметри в даному випадку не використовуються.
cvSmooth(gray, gray, CV_GAUSSIAN, 9, 0, 0, 0);
Наступними діями є підкреслення границь за допомогою оператора Кенні. Для цього виконується функція cvCanny, в якості параметрів якій передаються: вхідне зображення, вихідне тобто теж саме, значення нижнього та верхнього порогу.
cvCanny(gray, gray, 56, 100, 3);
Підкреслені контури виводяться на екран у фрейм за допомогою методу showImage()
frame.showImage(gray);
Для пошуку підкреслених контурів на зображенні використовується функція cvFindContours(), в якості параметрів їй передаються: вхідне зображення, місце для зберігання контурів, об’єм який потрібно виділити у пам’яті, метод пошуку, метод апроксимації, і початкова точка пошуку.
cvFindContours(gray, storage, contour,
Loader.sizeof(CvContour.class), CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
int NC = 0;
//Перебираються всі контури
while (contour != null && !contour.isNull()) {
if (contour.elem_size() > 0) {
//апроксимуються
CvSeq points = cvApproxPoly(contour,
Loader.sizeof(CvContour.class), storage,
CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.002, 0);
//обчислюються моменти для кожного контуру
cvMoments(contour, moments, 1);
//обчислюються Hu моменти для кожного контуру
cvGetHuMoments(moments, hu_moments);
//порівнюються Hu моменти поточного контуру з шаблоним, і якщо ступінь схожості менше 150 виконати наступне
if (MatchShapes(hu_templ, hu_moments) < 150) {
//промалювати контур на вихідному зображенні
cvDrawContours(Grab, contour, CvScalar.RED,
CvScalar.RED, -1, 4, CV_AA);
//промалювати рамку навколо контуру
CvRect r = cvBoundingRect(contour, 1); int x = r.x(),
y = r.y(), w = r.width(), h = r.height();
cvRectangle(Grab, cvPoint(x, y), cvPoint(x + w, y +
h), CvScalar.MAGENTA, 4, CV_AA, 0);
}
System.out.print("NC = " + NC + "\n");
System.out.print("hu1 = " + hu_moments.hu1() + "\n");
System.out.print("hu2 = " + hu_moments.hu2() + "\n");
System.out.print("hu3 = " + hu_moments.hu3() + "\n");
System.out.print("hu4 = " + hu_moments.hu4() + "\n");
System.out.print("hu5 = " + hu_moments.hu5() + "\n");
System.out.print("hu6 = " + hu_moments.hu6() + "\n");
System.out.print("hu7 = " + hu_moments.hu7() + "\n");
NC++;
}
contour = contour.h_next();
}
//виводиться на екран вихідне зображення
frame2.showImage(gray);
}
return Grab;
}
//функції MatchShapes, порівнює Hu моменти двох контурів
private double MatchShapes(CvHuMoments hu_m_templ, CvHuMoments hu_m) {
double mt = 0;
double[] ma = new double[7];
double[] mb = new double[7];
ma[0] = hu_m_templ.hu1();
ma[1] = hu_m_templ.hu2();
ma[2] = hu_m_templ.hu3();
ma[3] = hu_m_templ.hu4();
ma[4] = hu_m_templ.hu5();
ma[5] = hu_m_templ.hu6();
ma[6] = hu_m_templ.hu7();
mb[0] = hu_m.hu1();
mb[1] = hu_m.hu2();
mb[2] = hu_m.hu3();
mb[3] = hu_m.hu4();
mb[4] = hu_m.hu5();
mb[5] = hu_m.hu6();
mb[6] = hu_m.hu7();
for (int i = 0; i < 7; i++) {
mt += Math
.abs((Math.signum(ma[i]) * Math.log(Math.abs(ma[i])) - Math
.signum(mb[i]) * Math.log(Math.abs(mb[i])))
/ Math.signum(ma[i]) * Math.log(Math.abs(ma[i])));
}
System.out.print("\nMatchResult = " + mt + "\n");
return mt;
}
}
class Haar implements Runnable {
//розмір відступу
private static final int SCALE = 2;
//шлях до файлу каскаду
private static final String CASCADE_FILE = "C:\\out_ok_25.02.2012.xml";
static boolean stoped;
public void run() {
stoped = false;
System.out.println("Starting OpenCV...");
Loader.load(opencv_objdetect.class);
CanvasFrame frame = new CanvasFrame("Main Frame");
frame.setDefaultCloseOperation(CanvasFrame.EXIT_ON_CLOSE);
try {
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber("C:\\ggg.avi");
grabber.start();
while (!stoped) {
IplImage origImg = grabber.grab();
if (origImg == null)
return;
// конвертування в відтінки сірого
IplImage grayImg = IplImage.create(origImg.width(),
origImg.height(), IPL_DEPTH_8U, 1);
cvCvtColor(origImg, grayImg, CV_BGR2GRAY);
// створення зменшеної копії для підвищення швидкості виявлення IplImage smallImg = IplImage.create(grayImg.width() / SCALE,
grayImg.height() / SCALE, IPL_DEPTH_8U, 1);
cvResize(grayImg, smallImg, CV_INTER_LINEAR);
// еквалізація гістограми зменшеного зображення
IplImage equImg = IplImage.create(smallImg.width(),
smallImg.height(), IPL_DEPTH_8U, 1);
cvEqualizeHist(smallImg, equImg);
// створення тимчасового місця, що використовуються під час виявлення об'єкта
CvMemStorage storage = CvMemStorage.create();
//створення екземпляру каскадного класифікатору для розпізнавання об’єктів
CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(
cvLoad(CASCADE_FILE));
System.out.println("Detecting faces...");
CvSeq faces = cvHaarDetectObjects(equImg, cascade, storage,
1.1, 3, CV_HAAR_DO_CANNY_PRUNING);
cvClearMemStorage(storage);
//Перебираються знайдені об’єкти і рисується жовтий прямокутник навколо них
int total = faces.total();
System.out.println("Found " + total + " obj");
for (int i = 0; i < total; i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
cvRectangle(
origImg,
// задається відступ
cvPoint(r.x() * SCALE, r.y() * SCALE),
cvPoint((r.x() + r.width()) * SCALE,
(r.y() + r.height()) * SCALE),
CvScalar.YELLOW, 6, CV_AA, 0);
}
//виведення зображення на екран
frame.showImage(origImg);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
frame.dispose();
}
}
public void stop() {
stoped = true;
}
}