Разработка приложения с использованием метода Лукаса-Канаде
Особенности и методы построения приложений с технологией оптического потока. Простые функции для преобразования изображений. Примитивные типы данных в OpenCV. Выбор языка программирования. Разработка приложения с использованием алгоритма Лукаса-Канаде.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 07.08.2018 |
Размер файла | 1,1 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Для повышения производительности работы Java-программ были разработаны "JustinTime" (JIT) компиляторы, но универсального решения этой проблемы не существует.
На первый взгляд, полуинтерпретируемая природа Java-программ обеспечивает выполнение принципа "скомпилированный однажды код выполняется везде". Однажды скомпилированная в байт-код Java-программа может выполняться на любой платформе, для которой доступна JVM. На практике же, это не всегда так из-за отличий в реализациях разных JVM и из-за необходимости иногда наряду с Java-программами использовать родной, не-Java код, обычно написанный на C или C++.
Но разве использование платформенно-независимого байт-кода является верным подходом в создании кросс-платформенных приложений? С хорошим кросс-платформенным инструментарием, наподобие Qt, и хорошими компиляторами для различных платформ программисты могут достичь почти той же цели компиляцией своего исходного кода один раз для каждой из платформ: "написанный однажды код компилируется везде". Можно возразить, что для этого разработчикам потребуется доступ ко всем поддерживаемым платформам, в то время, как с Java, теоретически, разработчикам необходим доступ только к одной из платформ, имеющей средства разработки для Java и JVM. На практике же ни один из ответственных производителей программного обеспечения не будет сертифицировать свои программные продукты для платформ без предварительного их тестирования, поэтому в любом случае производителям будет необходим доступ ко всем поддерживаемым платформам.
Возникает вопрос, зачем использовать программную реализацию виртуальной машины Java, если такую же функциональность можно получить с помощью аппаратной реализации? Именно так рассуждали разработчики при создании языка Java; они предполагали, что вопрос низкой производительности будет решен, когда станет доступной аппаратная реализация JVM в виде Java-процессоров. Однако даже по прошествии пяти лет Java-процессоры не получили широкого распространения. Существуют проектные экземпляры и даже работающие прототипы Java-процессоров, однако понадобится еще немало времени, чтобы стало возможным их приобрести.
Java и C++ используют различные подходы в управлении памятью.ВC++ управление памятью полностью осуществляется программистом, т.е. по мере необходимости распределение и освобождение памяти должно выполняться программистом. Если программист забывает освободить ранее полученную память, возникает "утечка памяти". Если во время работы приложения произойдет лишь одна такая утечка, проблем не возникнет, так как после завершения работы приложения операционная система освободит всю ранее использованную им память. Но если утечки памяти будут происходить постоянно (например, если пользователь будет периодически выполнять определенные действия), использование памяти приложением будет расти вплоть до полного ее расхода с последующим возможным отказом системы.
Java обеспечивает автоматическое освобождение неиспользуемой памяти. Наряду с распределением памяти программистом JVM ведет учет всех используемых блоков памяти и указателей на них. Если блок памяти больше не используется, он может быть освобожден. Это обеспечивает процесс, который называется "сборкой мусора". Он периодически вызывается JVM, проверяет все используемые блоки памяти и освобождает те из них, на которые отсутствуют указатели.
Сборка мусора очень удобна, но за ее использование приходится расплачиваться большим потреблением памяти и низкой произодительностью. Программисты C++ могут (и должны) освобождать блоки памяти сразу после того, как они перестали быть нужны. С Java блоки не освобождаются до очередного вызова сборщика мусора, периодичность работы которого зависит от использумой реализации JVM. Вдобавок к большому расходу памяти процесс сборки мусора требует дополнительной процессорной мощности, которая в результате становится недоступной приложению, и это приводит к замедлению его работы. Поэтому периодическая работа сборщика мусора может приводить к "замораживанию" Java-программы на несколько секунд. Лучшие реализации JVM минимизируют такие замораживания, но не устраняют их полностью.
При работе с внешними программами и устройствами, например, во время ввода/вывода или при взаимодействии с базой данных, желательно закрыть файл или соединение с базой данных сразу же после того, как они перестали быть нужны. Благодаря деструкторам C++ это происходит сразу после вызова delete. В Java закрытие произойдет лишь во время следующего цикла работы сборщика мусора. В лучшем случае это может привести к излишней блокировке ресурсов, в худшем - к нарушению целостности открытых ресурсов.
Тот факт, что Java-программы используют блоки памяти большие, чем необходимо, является особенно критичным для встраиваемых устройств, объемы памяти которых невелики. Неслучайно, что до сих пор (на время написания этой статьи) не существует полной реализации Java-платформы для встраиваемых устройств, а лишь ее частичные реализации.
Главная причина, по которой сборка мусора является более дорогостоящей, чем непосредственное управление памятью программистом, - это утрата информации. В C++ программе программист знает и местонахождение своих блоков памяти (сохраняя указатели на них), и когда они перестанут быть ему нужными. В Java-программе последняя информация недоступна для JVM (даже если она известна программисту), поэтому JVM должна перебирать все блоки на предмет отсутствующих указателей. Для того, чтобы вызвать сборку мусора вручную, Java-программист может удалить все указатели на больше ненужные ему блоки памяти. Но со стороны программиста это потребует больше усилий, чем непосредственное управление памятью в C++; и тем не менее, во время сборки мусора JVM все равно придется проверить все блоки памяти, чтобы освободить неиспользуемые.
С технической точки зрения, нет ничего такого, что бы мешало реализовать сборку мусора в C++ программах. Существуют обеспечивающие это коммерческие программы и библиотеки. Но из-за перечисленных выше недостатков немногие C++ программисты используют их. Инструментарий Qt использует более эффективный подход для упрощения задачи управления памятью: при удалении объекта все зависящие от него объекты также автоматически удаляются. Подход Qt не мешает программистам по желанию самостоятельно удалять объекты.
Так как управление памятью в C и C++ обременительно для программиста, созданное с помощью этих языков программное обеспечение обвиняется в нестабильной работе и подверженности ошибкам. Хотя некорректная работа с памятью в C и C++ может привести к более критичным ошибкам (обычно приводящим к аварийному завершению программы), хорошие знания, инструментарий и опыт могут значительно уменьшить связанный с этим риск. Изучению управления памятью должно уделяться достаточно внимания. Также существует большое число коммерческих и свободных инструментов, позволяющих программистам обеспечить отсутствие в программах ошибок при работе с памятью; например, ParasoftInsure++, RationalPurify и ElectricFence. Гибкая система управления памятью в C++ делает возможным создавать адаптированные для любого типа приложений профилировщики памяти.
В результате этого обсуждения мы убедились в том, что при сравнимой продуктивности программирования C++ обеспечивает приложениям гораздо лучшие, чем Java, производительность работы и эффективность использования памяти.
Java-платформа предлагает внушительное число пакетов, насчитывающих сотни классов для любых задач, включая пользовательский графический интерфейс, безопасность, поддержку сети и прочие.Это несомненное преимущество Java-платформы. Любому Java-пакету соответствует, как минимум, одна C++ библиотека, хотя иногда бывает очень трудно собрать в одном C++ проекте множество библиотек и заставить их вместе правильно работать.
Однако это преимущество Java является также ее недостатком. Разобраться в огромномAPI программисту становится все сложнее. Можете быть наверняка уверены, что для любой задачи всегда найдется уже готовое решение или, по крайней мере, решение, облегчающее выполнение этой задачи. Но найти пригодный для этого пакет и класс становится все труднее. Также с увеличением числа пакетов стремительно растет размер Java-платформы. В результате стали возникать ее "урезанные" версии, утратившие преимущества готовых решений. Таким образом, размер Java-платформы делает практически невозможным создание Java-систем небольшими производителями независимо от создателя JavaSunMicrosystems, что ослабляет конкуренцию.
Если преимущества Java заключаются в доступных библиотеках, то явные преимущества C++ - в имеющихся средствах разработки. За все время существования семейства языков C и C++ было создано огромное количество самых разнообразных средств разработки, включая инструменты для дизайна, отладки и профилирования. Имеющиеся средства разработки для Java часто уступают по возможностям своим C++ -аналогам. Это справедливо даже для инструментов от одного производителя; например, сравните Java и C/C++ -версии профилировщика RationalQuantify.
Самым важным инструментом для любого разработчика, использующего компилируемые языки, является компилятор. Основным достоинством компиляторов C++ является скорость работы. Для обеспечения кросс-платформенности своих компиляторов (и других средств разработки) производители Java-инструментов часто сами используют Java, со всеми вытекающими отсюда проблемами производительности и эффективности использования памяти. Иногда встречаются Java-компиляторы, написанные на C/C++ (например, IBMJikes), но это редкость.
Проведя анализ языков, выбор остановился на языке C++.
4.2 Реализация алгоритма с использованием библиотеки OpenCV
Результатом исследования стала реализация алгоритма Лукаса-Канаде, с использованием библиотеки OpenCV. На данный момент программа обладает следующим функционалом:
· Определение объекта
· Реализация захвата видео с камеры и обработка кадров с целью выделения руки в кадре.
Рассмотрим подробнее реализацию данного программного продукта на примере отрывка кода.
int main(intargc, char** argv)
{
VideoCapturecap("Pryamougolnik2.avi"); //capture the video from web cam
if (!cap.isOpened()) // if not success, exit program
{
cout<< "Cannot open the web cam" <<endl;
return -1;
}
double fps = cap.get(CV_CAP_PROP_FPS);
double period = 1. / fps;
cout<< fps <<endl;
namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
intiLowH = 0;
intiHighH = 179;
intiLowS = 0;
intiHighS = 255;
intiLowV = 0;
intiHighV = 0;
//Create trackbars in "Control" window
cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
cvCreateTrackbar("HighH", "Control", &iHighH, 179);
cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("HighS", "Control", &iHighS, 255);
cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
cvCreateTrackbar("HighV", "Control", &iHighV, 255);
intprevX = 0, prevY = 0;
int frame = 0;
doublesummVelocity = 0;
intmarginTextTop = 10;
Mat imageText(600, 800, CV_8UC3, Scalar::all(0));
string text;
boolisFindContour = false;
constintTimeFrame = fps;
Ptr<BackgroundSubtractor>pMOG; //MOG Background subtractor
Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
Ptr<BackgroundSubtractorGMG>pGMG; //MOG2 Background subtractor
pMOG = new BackgroundSubtractorMOG();
Mat resizeF;
Mat fgMaskMOG; //fg mask generated by MOG method
doublecurrentDist = 0;
while (true)
{
Mat imgOriginal;
boolbSuccess = cap.read(imgOriginal); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout<< "Cannot read a frame from video stream" <<endl;
break;
}
resize(imgOriginal, resizeF, Size(imgOriginal.size().width / 4, imgOriginal.size().height / 4));
pMOG->operator()(resizeF, fgMaskMOG);
Mat imgHSV;
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(fgMaskMOG,
contours,
hierarchy,
CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE,
cv::Point(0, 0));
std::vector<std::vector<cv::Point>>contours_poly(contours.size());
std::vector<cv::Rect>boundRect(contours.size());
for (inti = 0; i<contours.size(); i++)
{
cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = cv::boundingRect(cv::Mat(contours_poly[i]));
}
if (boundRect.size())
{
cv::Rectrect = *boundRect.begin();
if (isFindContour)
{
doubledistX = rect.br().x - prevX, distY = rect.br().y - prevY;
doubledist = std::sqrt(distX*distX + distY*distY);
currentDist += dist;
cout<<distX<< " " <<distY<<endl;
}
prevX = rect.br().x, prevY = rect.br().y;
isFindContour = true;
}
else
{
isFindContour = false;
}
// then put the text itself
putText(imgOriginal, text, textOrg, fontFace, fontScale,
Scalar::all(255), thickness, 8);
imshow("Original", imgOriginal); //show the original image
if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout<< "esc key is pressed by user" <<endl;
break;
}
frame++;
}
return 0;
} int radius = 1;
int radius_max=10;
//
// функция-обработчик ползунка -
// радиусядра
void myTrackbarRadius(int pos) {
radius = pos;
}
int iterations = 1;
int iterations_max = 10;
if (frame % TimeFrame == 0)
{
std::ostringstreamstrs;
strs<<currentDist;
text = strs.str() + " pixels per second";
currentDist = 0;
cout<< text <<endl;
}
intfontFace = FONT_HERSHEY_DUPLEX;
doublefontScale = 1;
int thickness = 1;
int baseline = 0;
Size textSize = getTextSize(text, fontFace,
fontScale, thickness, &baseline);
baseline += thickness;
// center the text
Point textOrg(10, textSize.height + marginTextTop);
// then put the text itself
putText(imgOriginal, text, textOrg, fontFace, fontScale,
Scalar::all(255), thickness, 8);
imshow("Original", imgOriginal); //show the original image
if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout<< "esc key is pressed by user" <<endl;
break;
}
frame++;
}
return 0;
}
Рассмотрим подробнее определение конструктора.
VideoCapturecap(""); Данной командой мы указываем источник видеопоследовательности, на данный момент это видеофайл, который мы в итоге получаем из видеопоследовательности онлайн-камеры.
Далее мы с помощью команды doublefps происходит расчет частоты кадров, путем считывания количества кадров в переменную за интервал времени. Данная процедура необходима для получения интервала времени, в будущем необходимого для расчета скорости объекта.
namedWindow("Control", CV_WINDOW_AUTOSIZE)необходима для создания рабочего окна, в которое будет происходить вывод видеопоследовательности и результатов измерений Рабочее окно будет автоматически подстраиваться под возможности экрана пользователя.
Необходимо обрабатывать каждый полученный кадр, используя функцию cvCreateTrackbar, которая позволяет преобразовывать кадры и хранить их в переменной imgOriginal. Благодаря этому процессу мы сможем сравнивать последующие кадры друг с другом, для нахождения объекта.
Функция pMOG = newBackgroundSubtractorMOG() позволяет преобразовывать многоканальное изображение в одноканальное, для упрощения поиска объекта. Учитывая, что преобразованное изображение требуется только для вывода на исходном изображении расчетов, вся дальнейшая работа с кадром будет происходить в переменной fgMaskMOG.
После того как кадр был обработан, оригинал изображения транслируется на экран, а программа при помощи boolbSuccess = cap.read(imgOriginal); начинает работу со следующим кадром. Вся работа над видеопоследовательностью происходит в режиме реального времени.
Команда MatimgHSV позволит использовать функцию вычитания фона. Принцип работы: из исходного изображения, содержащее фон и объект, вычитается изображение, содержащее только фон, затем получившееся изображение обрабатывается для удаления шумов. Требуется два кадра: изображение с объектом и изображение без объекта. В результате получаем маску, которая очень точно повторяет объект на исходном изображении. Действительно точных результатов можно добиться лишь при совпадающем фоне, но так как у нас сплошной фон черного цвета, то проблем с вычитанием с использованием функции не наблюдается.
Функция td::vector<std::vector<cv::Point>>contours_poly(contours.size()); позволяет искать замкнутый контур в маске. Если такого контура не нашлось, то программа перестает обработку кадра и переходит к следующему. Ниже приведен код для поиска контура и объекта :
import numpy as np
import cv2
cap = cv2.VideoCapture('slow.flv')
# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Parameters for lucas kanade optical flow
lk_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# Create some random colors
color = np.random.randint(0,255,(100,3))
# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)
while(1):
ret,frame = cap.read()
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# calculate optical flow
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
# Select good points
good_new = p1[st==1]
good_old = p0[st==1]
# draw the tracks
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
c,d = old.ravel()
mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
cv2.imshow('frame',img)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
# Now update the previous frame and previous points
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()
Ниже приведен и описан результат работы программы.
Для дальнейшей работы с изображением используется принцип бинаризации - неизменный фон становится черным, а меняющийся объект, в данном случае рука - становится белым (рис 3.1).
Рис. 3.1 - Бинаризация изображения
После процесса бинаризации, достаточно легко определить объект на изображениии в дальнейшем его не терять, если не будет резких смен кадров.(рис. 3.2).
Рис. 3.2 - Определение объекта и его вершин
Заключение
В результате проделанной работы было разработано приложение с использованием алгоритма Лукаса-Канаде, реализованного на основе библиотеки OpenCV.
Для достижения поставленной цели были решены следующие задачи:
• Рассмотрено понятие оптический поток;
• Подготовлена среда разработки языка С++;
• Разработано приложение;
• Проведен анализ разработанного приложения
Использование в разработке программы библиотеки OpenCV позволило использовать некоторые готовые решения для работы с видеопоследовательностью, а так же для определения объекта на ней. Учитывая, что работа была выполнена на несложных объектах, требуется дальнейшее исследование алгоритма, а так же реализация его в последующей версии программы.
Список использованных источников
1. Шилдт Г. C++. Базовый курс [Текст]/ Шилдт Г. М.: «Вильямс», 2008. - 624 с.
2. Щупак Ю. C/C++. Структурное и объектно-ориентированное программирование: практикум [Текст]/ Щупак Ю., Павловская Т. - СПб.: «Питер», 2010. - 436 с.
3. Bradski G. Learning OpenCV: Computer Vision with the OpenCV Library [Текст]/ Bradski G., Kaehler A. - «O'Reilly Media», 2008. - 123 с.
4. Рао С. Освой самостоятельно C++ за 21 день[Текст]/ М.: «Вильямс», 2015. - 699 с.
5. Подбельский В.В. Язык C++. Учебное пособие [Текст] / В.В. Подбельский - Москва: Финансы и статистика, 1994 - 560с.
6. Седжвик Р. Алгоритмы на C++ [Текст]/ Седжвик Р. М.: «Вильямс», 2011. - 1056 с.
7. Литвиненко Н. А. - Технология программирования на С++ [Текст]/ Гуревич С -М.: БХВ-Петербург, 2010. - 281 с.
8. Ирэ Пол. Объектно-ориентированное программирование с использованием C++ / Пол. Ирэ; пер. с англ. - Киев: НИИПФ ДиаСофт Лтд, 1996 - 480с.
9. Форсайт Д. Компьютерное зрение. Современный подход / Форсайт Д., Понс Ж. // М: Издательский дом" Вильямс. - 2004. 314с.
10. Грузман И.С. Цифровая обработка изображений в информационных системах: Учебное пособие / И.С. Грузман, В.С. Киричук, В.П. Косых и др. - Новосибирск: Изд-во НГТУ, 2002. - 352 c.
11. OpenCV documentation [Electronic resource]//OpenCV documentation. 2014. URL: ttp://docs.opencv.org/ (access date 24.02.2015)
Приложение А
Программный код
import cv2
import numpy as np
cap = cv2.VideoCapture("vtest.avi")
ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[...,1] = 255
while(1):
ret, frame2 = cap.read()
next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)
flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = ang*180/np.pi/2
hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX)
bgr = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
cv2.imshow('frame2',bgr)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
elif k == ord('s'):
cv2.imwrite('opticalfb.png',frame2)
cv2.imwrite('opticalhsv.png',bgr)
prvs = next
cap.release()
cv2.destroyAllWindows()
importnumpyasnp
Продолжение приложения А
import cv2
cap = cv2.VideoCapture('slow.flv')
# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Parameters for lucas kanade optical flow
lk_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# Create some random colors
color = np.random.randint(0,255,(100,3))
# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)
while(1):
ret,frame = cap.read()
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# calculate optical flow
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
# Select good points
good_new = p1[st==1]
Продолжение приложения А
good_old = p0[st==1]
# draw the tracks
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
c,d = old.ravel()
mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
cv2.imshow('frame',img)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
# Now update the previous frame and previous points
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()
import numpy as np
import cv2
cap = cv2.VideoCapture('slow.flv')
# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Parameters for lucas kanade optical flow
lk_params = dict(winSize = (15,15),
Продолжение приложения А
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# Create some random colors
color = np.random.randint(0,255,(100,3))
# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)
while(1):
ret,frame = cap.read()
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# calculate optical flow
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
# Select good points
good_new = p1[st==1]
good_old = p0[st==1]
# draw the tracks
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
c,d = old.ravel()
mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
cv2.imshow('frame',img)
Продолжение приложения А
k = cv2.waitKey(30) & 0xff
if k == 27:
break
# Now update the previous frame and previous points
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()
Приложение Б
Презентационный материал
Размещено на Allbest.ur
...Подобные документы
Технология создания многопоточных приложений в современных системах программирования с использованием языка C# в Visual Studio.NET. Разработка алгоритма и структуры программы. Описание и особенности тестирования приложения с разным количеством потоков.
курсовая работа [773,0 K], добавлен 14.03.2013Разработка приложения для работы с базой данных с использованием объектно-ориентированного и визуального программирования. Обзор языка элементов языка программирования Delphi. Проектирование базы данных автозаправки. Клиентская система приложения.
курсовая работа [2,3 M], добавлен 31.01.2016Анализ возможных подходов к созданию web-приложения с использованием программирования Java и CGI. Разработка структуры базы данных и реализация полученной модели в рамках СУБД. Обеспечение диалога CGI-программы с пользователем, используя браузер.
курсовая работа [310,9 K], добавлен 07.08.2011Разработка приложения на базе скриптового языка программирования JavaScript, с использованием каскадных таблиц стилей CSS в среде программирования Bluefish Editor. Обоснование выбора инструментов. Применение клавиш управления памятью калькулятора.
курсовая работа [3,8 M], добавлен 22.06.2015Исследование возможностей и областей использования языка программирования JavaScript. Сравнительный анализ языков программирования JavaScript и PHP. Разработка интерактивного Web-приложения на примере теста по теме "Программирование на языке Delphi".
практическая работа [26,0 K], добавлен 04.02.2015Характеристика объекта автоматизации. Создание многоуровневой архитектуры приложения, отладка метода безошибочной идентификации пользователей системы. Разработка нестандартного метода преобразования объектов базы данных в объекты классов приложения.
курсовая работа [395,4 K], добавлен 28.04.2015Сравнительная характеристика, возможности и функции языков программирования JavaScript и PHP. Основные области их использования. Разработка интерактивного Web-приложения с применением JavaScript на примере теста по теме "Программирование на языке Delphi".
курсовая работа [19,3 K], добавлен 01.07.2014Математическое описание операций преобразования плоских фигур. Выбор и обоснование языка программирования и среды разработки. Задание базовой фигуры. Разработка алгоритма работы программы. Проверка корректности работы программы в различных режимах.
курсовая работа [567,6 K], добавлен 13.10.2014Выбор и обоснование аппаратного обеспечения. Типы архитектуры веб-приложений. Шаблоны проектирования архитектуры приложения. Разработка инфологической модели базы данных. Подготовка к разработке приложения. Рассмотрение причин возникновения паттернов.
дипломная работа [3,0 M], добавлен 27.11.2022Общая характеристика и функциональное назначение проектируемого программного обеспечения, требования к нему. Разработка и описание интерфейса клиентской и серверной части. Описание алгоритма и программной реализации приложения. Схема базы данных.
курсовая работа [35,4 K], добавлен 12.05.2013Разработка программы для рисования различных правильных многоугольников с помощью объектно-ориентированного языка программирования. Использование для разработки среды C++ Builder 6 и библиотеки VCL. Разработка интерфейса приложения и алгоритма его работы.
курсовая работа [616,4 K], добавлен 18.10.2010Этапы развития, особенности и возможности языка программирования Java; происхождение названия. Приложения Sun Microsystems: идеи, примитивные типы. Python - высокоуровневый язык программирования общего назначения: структуры данных, синтаксис и семантика.
реферат [79,0 K], добавлен 23.06.2012Разработка клиент-серверного приложения, позволяющего взаимодействовать друг с другом с использованием доступа к базам данных. Проектирование связи сервера с базой данных с помощью технологии ODBC. Разработка интерфейса программы, ее тестирование.
курсовая работа [352,0 K], добавлен 24.08.2016Создание программы "MP3 Player", воспроизводящей аудио файлы формата MP3 для работы в операционной системе Windows с использованием языка программирования Delphi. Разработка интерфейса, алгоритма и документации к разработанному программному продукту.
курсовая работа [625,0 K], добавлен 18.07.2012Разработка программного приложения WindowsForms для работы с базой данных на языке высокого уровня C# в автономном режиме с использованием ADO.NET. Проектирование реляционной модели базы данных, интерфейса приложения, основных функций и возможностей.
курсовая работа [4,3 M], добавлен 30.06.2015Разработка трехмерной модели приложения "Гоночный автомобиль" на языке С++ с использованием библиотеки OpenGL и MFC, создание программы в среде Visual Studio 6.0. Информационное обеспечение, логическая структура и функциональная декомпозиция проекта.
курсовая работа [3,9 M], добавлен 29.06.2011Программирование приложения с использованием библиотеки OpenGL и функции для рисования геометрических объектов. Разработка процедуры визуализации трехмерной сцены и интерфейса пользователя. Логическая структура и функциональная декомпозиция проекта.
курсовая работа [1,1 M], добавлен 23.06.2011История создания и развитие языка программирования Pascal, его версии. Особенности и порядок построения графика функции на языке Turbo Pascal с использованием декартовой системы координат. Блок схема алгоритма процедур, листинг и тестирование программы.
курсовая работа [102,7 K], добавлен 23.12.2011Программирование с использованием технологий Microsoft .NET. Разработка приложения "Станция технического обслуживания автомобилей": инфологическое, даталогическое проектирование базы данных. Информационное и программное обеспечение, логическая структура.
курсовая работа [1,6 M], добавлен 03.07.2011Основы программирования с использованием библиотеки OpenGL. Приложение для построения динамического изображения модели объекта "Батискаф": разработка процедуры визуализации трехмерной схемы, интерфейса пользователя и подсистемы управления событиями.
курсовая работа [1,4 M], добавлен 26.06.2011