![Фотография](https://vse.kz/public/style_images/osnovnoi34/profile/default_large.png)
Программирование на квадрокоптере AR.Drone
#62
Отправлено 08.04.2013, 11:05:14
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Для того чтобы получить заряд батареи в процентах создаем объект и вызываем функцию opennav()
var DroneNav1 = DroneNav1.new;
DroneNav1.opennav();
#include <urbi/uobject.hh> #include <stdio.h> #include <string.h> #include <winsock2.h> #include <windows.h> #define NAVDATA_PORT 5554 #define AT_PORT 5556 #define NAVDATA_BUFFER_SIZE 2048 #define WIFI_MYKONOS_IP "192.168.1.1" #define NAVDATA_STATE 4 #define NAVDATA_BATTERY 24 #define NAVDATA_PITCH 28 #define NAVDATA_ROLL 32 #define NAVDATA_YAW 36 #define NAVDATA_ALTITUDE 40 #define NAVDATA_VX 44 #define NAVDATA_VY 48 #define NAVDATA_VZ 52 class DroneNav1: public urbi::UObject { public: // The class must have a single constructor taking a string. DroneNav1(const std::string& str); int init(); // Our variable. urbi::UVar v; int opennav() ; }; // the constructor defines what is available from Urbi DroneNav1::DroneNav1(const std::string& s) : urbi::UObject(s) // required { // Bind the variable. UBindVar (DroneLed, v); // Bind the function. UBindFunction (DroneNav1, opennav); UBindFunction(DroneNav1, init); }; int DroneNav1::init() { return 0; }; int DroneNav1::opennav() { int seq=0; char msg[NAVDATA_BUFFER_SIZE]; int at_socket = -1, //sendto navdata_socket = -1; //recvfrom struct sockaddr_in pc_addr, //INADDR_ANY drone_at, //send at addr drone_nav, //send nav addr from; int l,size; char trig[] = { 0x01, 0x00, 0x00, 0x00 }; char command[256]; //Инициализируем библиотеку WinSock с промощью вызова функции WSAStartup char buff[10 * 1014]; //printf("UDP DEMO Client\nType quit to quit\n"); // Шаг 1 - иницилизация библиотеки Winsocks if (WSAStartup(0x202, (WSADATA *)&buff[0])) { printf("WSAStartup error: %d\n", WSAGetLastError()); return -1; } if((at_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0){ printf ("at_socket error: %s\n", strerror(errno)); goto fail; }; if((navdata_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0){ printf ("navdata_socket: %s\n", strerror(errno)); goto fail; }; //for recvfrom pc_addr.sin_family = AF_INET; pc_addr.sin_addr.s_addr = htonl(INADDR_ANY); pc_addr.sin_port = htons(NAVDATA_PORT); //for sendto AT drone_at.sin_family = AF_INET; drone_at.sin_addr.s_addr = inet_addr(WIFI_MYKONOS_IP); drone_at.sin_port = htons(AT_PORT); //for sendto navadata init drone_nav.sin_family = AF_INET; drone_nav.sin_addr.s_addr = inet_addr(WIFI_MYKONOS_IP); drone_nav.sin_port = htons(NAVDATA_PORT); if(bind( navdata_socket, (struct sockaddr *)&pc_addr, sizeof(pc_addr)) < 0){ printf ("bind: %s\n", strerror(errno)); goto fail; }; //set unicast mode on sendto(navdata_socket, trig, 4, 0, (struct sockaddr *)&drone_nav, sizeof(drone_nav)); int v_bat; for(l=0;l<10;l++) { if(seq<2) sprintf(command,"AT*CONFIG=%d,\"general:navdata_demo\",\"TRUE\"\r",seq); else sprintf(command,"AT*COMWDG=%d\r",seq); sendto(at_socket, command, strlen(command), 0, (struct sockaddr*)&drone_at, sizeof(drone_at) ); seq++; size=0; int l = sizeof(pc_addr); size = recvfrom ( navdata_socket, &msg[0], NAVDATA_BUFFER_SIZE, 0, (struct sockaddr *)&from, &l); if (size==500){ v_bat = msg[24]; } } closesocket(at_socket); closesocket(navdata_socket); WSACleanup(); return v_bat; fail: // Шаг последний - выход closesocket(at_socket); closesocket(navdata_socket); WSACleanup(); return 1000; } UStart(DroneNav1);
#63
Отправлено 10.04.2013, 13:35:43
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
A |= B
http://citforum.ru/p...h/cpp_026.shtml
Например, пусть заданы два двухбайтных числа.
У первого числа ( B ) младший байт во всех разрядах содержит нули, а старший байт имеет произвольные значения в своих битах. Можно представить это так - XXXX XXXX 0000 0000
У второго числа (A) наоборот старший байт имеет во всех разрядах нули , а младший байт - произвольное число от нуля до 255. Можно представить это так - 0000 0000 YYYY YYYY
Тогда в результате операции
A |= B;
получим :
XXXX XXXX YYYY YYYY
#64
Отправлено 11.04.2013, 09:50:07
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
#include <urbi/uobject.hh> #include <stdio.h> #include <string.h> #include <winsock2.h> #include <windows.h> #define NAVDATA_PORT 5554 #define AT_PORT 5556 #define NAVDATA_BUFFER_SIZE 2048 #define WIFI_MYKONOS_IP "192.168.1.1" #define NAVDATA_STATE 4 #define NAVDATA_BATTERY 24 #define NAVDATA_PITCH 28 #define NAVDATA_ROLL 32 #define NAVDATA_YAW 36 #define NAVDATA_ALTITUDE 40 #define NAVDATA_VX 44 #define NAVDATA_VY 48 #define NAVDATA_VZ 52 int32_t get_int(int offset); char msg[NAVDATA_BUFFER_SIZE]; class DroneNav1: public urbi::UObject { public: // The class must have a single constructor taking a string. DroneNav1(const std::string& str); int init(); // Our variable. urbi::UVar drone_battery; urbi::UVar drone_altitude; urbi::UVar drone_pitch; urbi::UVar drone_roll; urbi::UVar drone_yaw; int opennav() ; }; // the constructor defines what is available from Urbi DroneNav1::DroneNav1(const std::string& s) : urbi::UObject(s) // required { // Bind the variable. UBindVar (DroneNav1, drone_battery); UBindVar (DroneNav1, drone_altitude); UBindVar (DroneNav1, drone_pitch); UBindVar (DroneNav1, drone_roll); UBindVar (DroneNav1, drone_yaw); // Bind the function. UBindFunction (DroneNav1, opennav); UBindFunction(DroneNav1, init); }; int DroneNav1::init() { return 0; }; int DroneNav1::opennav() { int seq=0; int32_t dr_battery, dr_altitude, dr_pitch, dr_yaw, dr_roll, dr_vx, dr_vy, dr_vz ; int at_socket = -1, //sendto navdata_socket = -1; //recvfrom struct sockaddr_in pc_addr, //INADDR_ANY drone_at, //send at addr drone_nav, //send nav addr from; int l,size; char trig[] = { 0x01, 0x00, 0x00, 0x00 }; char command[256]; //Инициализируем библиотеку WinSock с промощью вызова функции WSAStartup char buff[10 * 1014]; //printf("UDP DEMO Client\nType quit to quit\n"); // Шаг 1 - иницилизация библиотеки Winsocks if (WSAStartup(0x202, (WSADATA *)&buff[0])) { printf("WSAStartup error: %d\n", WSAGetLastError()); return -1; } if((at_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0){ printf ("at_socket error: %s\n", strerror(errno)); goto fail; }; if((navdata_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0){ printf ("navdata_socket: %s\n", strerror(errno)); goto fail; }; //for recvfrom pc_addr.sin_family = AF_INET; pc_addr.sin_addr.s_addr = htonl(INADDR_ANY); pc_addr.sin_port = htons(NAVDATA_PORT); //for sendto AT drone_at.sin_family = AF_INET; drone_at.sin_addr.s_addr = inet_addr(WIFI_MYKONOS_IP); drone_at.sin_port = htons(AT_PORT); //for sendto navadata init drone_nav.sin_family = AF_INET; drone_nav.sin_addr.s_addr = inet_addr(WIFI_MYKONOS_IP); drone_nav.sin_port = htons(NAVDATA_PORT); if(bind( navdata_socket, (struct sockaddr *)&pc_addr, sizeof(pc_addr)) < 0){ printf ("bind: %s\n", strerror(errno)); goto fail; }; //set unicast mode on sendto(navdata_socket, trig, 4, 0, (struct sockaddr *)&drone_nav, sizeof(drone_nav)); int v_bat; while(1) { if(seq<2) sprintf(command,"AT*CONFIG=%d,\"general:navdata_demo\",\"TRUE\"\r",seq); else sprintf(command,"AT*COMWDG=%d\r",seq); sendto(at_socket, command, strlen(command), 0, (struct sockaddr*)&drone_at, sizeof(drone_at) ); seq++; size=0; int l = sizeof(pc_addr); size = recvfrom ( navdata_socket, &msg[0], NAVDATA_BUFFER_SIZE, 0, (struct sockaddr *)&from, &l); if (size==500){ //v_bat = msg[24]; drone_battery = get_int(NAVDATA_BATTERY); dr_altitude = get_int(NAVDATA_ALTITUDE); drone_altitude = *(float *)&dr_altitude/1000; dr_pitch = get_int(NAVDATA_PITCH); drone_pitch = *(float *)&dr_pitch/1000; dr_roll = get_int(NAVDATA_ROLL); drone_roll = *(float *)&dr_roll/1000; dr_yaw = get_int(NAVDATA_YAW); drone_yaw = *(float *)&dr_yaw/1000; //printf("dr_battery %i \n",drone_battery); //printf("dr_altitude %i \n",drone_altitude); //printf("dr_pitch %f \n",drone_pitch); //printf("dr_roll %f \n",drone_roll); //printf("dr_yaw %f \n",drone_yaw); break; } } closesocket(at_socket); closesocket(navdata_socket); WSACleanup(); return 0; fail: // Шаг последний - выход closesocket(at_socket); closesocket(navdata_socket); WSACleanup(); return 1000; } int32_t get_int(int offset) { int32_t tmp = 0, n = 0; for (int i=3; i>=0; i--) { n <<= 8; tmp = msg[offset + i] & 0xFF; n |= tmp; } return n; } UStart(DroneNav1);
#65
Отправлено 12.04.2013, 10:47:18
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Решил вернуться к идее метода Хафа и обсудить ее
Вот математический образ, который на мой взгляд помогает понять суть этого метода
Пусть имеется n элементов, каждый из них обладает m свойствами. Каждое свойство характеризует принадлежность элемента определенному множеству. То есть каждый элемент входит в m разных множеств.
В ситуации когда для каждого n элемента существует только одно общее с остальными элементами множество, можно сказать, что число элементов в этом множестве будет равно n, а число элементов в остальных множествах будет равно единице.
Если существует возможность пользуясь свойствами элементов определить в какие множества они входят, то мы получим список множеств
A(1), B(1), C(1), .... K(n), L(1), ...
и так далее. В скобках указанно количество элементов в множестве.
Все множества кроме K будут содержать по одному элементу, множество K будет содержать n элементов.
Суть метода Хафа состоит в данном случае в определении всех множеств в которые входят элементы и подсчете количества элементов из которых они состоят.
И далее находим множество у которого число элементов равно n (в общем случае - множество имеющее максимальное число элементов)
Массив таких множеств называется аккумуляторной матрицей. Размерность массива зависит от количества величин описывающих свойство вхождения элемента n в то или иное множество.
В случае если мы ищем прямые линии на рисунке то свойство вхождения в множество описывается двумя целыми значениями. То есть массив можно представить как двухмерную матрицу, элементами которой являются множества, а значение элемента этой двухмерной матрицы равно количеству элементов n в этом множестве
Эту матрицу можно представить в виде рисунка размером a*b, где а - ширина рисунка в пикселах (число столбцов в аккумуляторной матрице), b - высота рисунка в пикселах (число строк в матрице)
Для того чтобы отобразить матрицу в рисунок с "градациями серого цвета" надо посмотреть как кодируется информация в графическом файле. Содержимым файла является интенсивность свечения пикселов, которая задается целым числом от 0 до 255.
0 - это черный цвет пиксела
255 - белый цвет пиксела
В общем случае значение элемента аккумуляторной матрицы может быть больше чем 255. Можно нормировать значения элементов матрицы для того чтобы значение максимального элемента не превышало число 255
Находим отношение M_max/255= prop
M_max - элемент матрицы имеющий наибольшее значение
И делим значения всех элементов матрицы на число prop. Дробная часть у частного отбрасывается
После того как значения элементов матрицы таким образом откалиброваны надо подумать о том как будет отображаться информация о значениях на рисунке.
Интересует ситуация когда элемент с наибольшим значением имеет более черный цвет - "максимальная видимость этого элемента на рисунке"
Поэтому выполняем инверсию значений элементов матрицы
M = 255 - M
М - элемент матрицы
Сообщение отредактировал erbol: 12.04.2013, 12:58:58
#66
Отправлено 12.04.2013, 16:46:16
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
http://robocraft.ru/...vision/265.html
http://robocraft.ru/...vision/700.html
[size=4]
[/size] #include <opencv2/opencv.hpp> #ifdef _MSC_VER # if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION ==4 && CV_SUBMINOR_VERSION == 5 // OpenCV 2.4.5 # if defined(_DEBUG) # pragma comment(lib, "opencv_core245d.lib") # pragma comment(lib, "opencv_highgui245d.lib") # pragma comment(lib, "opencv_imgproc245d.lib") # pragma comment(lib, "opencv_video245d.lib") # pragma comment(lib, "opencv_ml245d.lib") # pragma comment(lib, "opencv_calib3d245d.lib") # pragma comment(lib, "opencv_objdetect245d.lib") # pragma comment(lib, "opencv_features2d245d.lib") # pragma comment(lib, "opencv_contrib245d.lib") # pragma comment(lib, "opencv_ts245d.lib") # pragma comment(lib, "opencv_legacy245d.lib") # pragma comment(lib, "opencv_flann245d.lib") # pragma comment(lib, "opencv_gpu245d.lib") # else # pragma comment(lib, "opencv_core245.lib") # pragma comment(lib, "opencv_highgui245.lib") # pragma comment(lib, "opencv_imgproc245.lib") # pragma comment(lib, "opencv_video245.lib") # pragma comment(lib, "opencv_ml245.lib") # pragma comment(lib, "opencv_calib3d245.lib") # pragma comment(lib, "opencv_objdetect245.lib") # pragma comment(lib, "opencv_features2d245.lib") # pragma comment(lib, "opencv_contrib245.lib") # pragma comment(lib, "opencv_ts245.lib") # pragma comment(lib, "opencv_legacy245.lib") # pragma comment(lib, "opencv_flann245.lib") # pragma comment(lib, "opencv_gpu245.lib") # endif //# if defined(_DEBUG) # endif //# if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION == 4 #endif //#ifdef _MSC_VER
Сообщение отредактировал erbol: 12.04.2013, 18:08:57
#67
Отправлено 13.04.2013, 10:25:39
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
https://github.com/puku0x/cvdrone
Обсуждение
https://projects.ard...57#message-5051
Установка
https://github.com/p...ki/How-to-build
#68
Отправлено 13.04.2013, 16:03:30
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
#69
Отправлено 14.04.2013, 13:05:43
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
В решении этой задачи сильно помог проект на который я уже ссылался
https://github.com/puku0x/cvdrone
Автор проекта puku0x
Определился состав ПО. Это библиотеки
ffmpeg - работа с видео
opencv - обработка изображений
pthread - работа с потоками
Так же из проекта puku0x, можно узнать функции этих библиотек которые используются для решения задачи
#70
Отправлено 14.04.2013, 16:30:07
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Чтобы пользоваться потоками в программировании надо уметь создавать потоки, блокировки памяти (общего адресного пространства потоков), выполнять необходимые операции в созданных потоках, после выполнения необходимых действий уничтожать потоки. Каждое действие с потоками характеризуется функцией из библиотеки pthread
Все функции этой библиотеки имеют приставку «pthread_»
- Функции управления потоками:
- pthread_create(): создание потока.
- pthread_cancel(): отмена потока.
- pthread_join(): подключиться к другому потоку и ожидать его завершения; поток, к которому необходимо подключиться, должен быть создан с возможностью подключения (PTHREAD_CREATE_JOINABLE).
- Функции синхронизации потоков:
- pthread_mutex_init(), pthread_mutex_destroy(), pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock(): с помощью мьютексов.
http://rk6.bmstu.ru/...ultithread.html
int pthread_create (pthread_t *tid_p, const pthread_attr_t *attr_p,
void *(*func_p)(void *), void *arg_p)
Создает новый поток для функции, заданной параметром func_p. Эта функция имеет аргументом указатель (void *) и возвращает значение того же типа. Реально же в функцию передается аргумент arg_p. Идентификатор нового потока возвращается через tid_p.
Аргумент attr_p указывает на структуру, задающую атрибуты вновь создаваемого потока. Если attr_p=NULL, то используются атрибуты "по умолчанию" (но это плохая практика, т.к. в разных ОС эти значения могут быть различными, хотя декларируется обратное). Одна структура, указываемая attr_p, может использоваться для управления несколькими потоками.
--------
Смысл использования функции pthread_testcancel() описан в http://citforum.ru/p...g/unix/threads/
с помощью функции pthread_testcancel(), создаем точку отмены (cancellation point) потока. Если досрочное завершение потока было затребовано, в этот момент поток должен завершиться.
Зачем нужны особые точки отмены? Дело в том, что даже если досрочное завершение разрешено, поток, получивший запрос на досрочное завершение, может завершить работу не сразу. Если поток находится в режиме отложенного досрочного завершения (именно этот режим установлен по умолчанию), он выполнит запрос на досрочное завершение, только достигнув одной из точек отмены. В соответствии со стандартом POSIX, точками отмены являются вызовы многих «обычных» функций, например open(), pause() и write(). Про функцию printf() в документации сказано, что она может быть точкой отмены, но в Linux при попытке остановиться на printf() происходит нечто странное – поток завершается, но pthread_join() не возвращает управления. Поэтому мы создаем явную точку отмены с помощью вызова pthread_testcancel().
---------
int pthread_mutex_lock (pthread_mutex_t *mp)
int pthread_mutex_unlock (pthread_mutex_t *mp)
С помощью pthread_mutex_lock() поток пытается захватить блокировку. Если же блокировка уже принадлежит другому потоку, то вызывающий поток ставится в очередь (с учетом приоритетов потоков) к блокировке. После возврата из функции pthread_mutex_lock() блокировка будет принадлежать вызывающему потоку.
Функция pthread_mutex_unlock() освобождает захваченную ранее блокировку. Освободить блокировку может только ее владелец.
----------
В нашем случае поток будет получать tcp-пакеты , декодировать их и помещать готовые кадры видео в память, откуда можно будет их брать и выполнять с ними нужные операции
#71
Отправлено 16.04.2013, 11:11:05
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Вот , парень показывает drone красный шарик и перемещает его в разные стороны . Drone следит за шариком и движется вслед за ним.
Потом на экране видим текст программы на urbiscript
Попробуем выполнить то же самое , пока без URBI
Первое , надо научится находить шарик на экране. У меня это будет теннисный шарик. Спасибо, тенниис !
#72
Отправлено 16.04.2013, 14:53:55
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Чем точнее определяем критерии поиска , тем меньше посторонних объектов обнаруживаем в результате поиска
Функция cvHoughCircles, которую используем для поиска шарика
CVAPI(CvSeq*) cvHoughCircles( CvArr* image, void* circle_storage,
int method, double dp, double min_dist,
double param1 CV_DEFAULT(100),
double param2 CV_DEFAULT(100),
int min_radius CV_DEFAULT(0),
int max_radius CV_DEFAULT(0));
имеет девять параметров
dp — разрешение сумматора, используемое для детектирования центров кругов.
Этот параметр задает точность определения радиуса окружности.
Допустим задан центр окружности, точка x0, y0. Задан радиус окружности , пусть он равен величине a.
Если dp равен например 5, то все контрастные точки, находящиеся от точки x0, y0 на расстоянии a, плюс/минус 2,5 пиксела, подходят для определения этой окружности.
Для поиска круга нужно составить представление о смысле параметров param1, param2
Значения интенсивности пиксела в картинке с градациями серого цвета хранится в виде числа. Максимальное значение интенсивности - 255. На границе предметов интенсивность имеет разрыв, то есть резко отличается для двух соседних пикселов. Чем больше разрыв значений , тем отчетливее видна граница предмета на рисунке
Чтобы различать малозаметные контуры предметов, например светло-зеленое на темно-зеленом фоне надо учитывать, что в данном случае разрыв значений интенсивности у соседних пикселов в области границы предмета будет маленьким
Отсюда надо исходить устанавливая значение для величин param1, param2
Сообщение отредактировал erbol: 16.04.2013, 15:25:37
#73
Отправлено 16.04.2013, 21:44:47
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Подбором параметров можно добиться того что все нужные круги будут найдены, а ложных круги не появится на рисунке
// // Несколько модифицированный пример example 6-1 Hough circles // нахождение кругов на изображении, // с использованием трансформации Хафа cvHoughCircles() // // из книги: // Learning OpenCV: Computer Vision with the OpenCV Library // by Gary Bradski and Adrian Kaehler // Published by O'Reilly Media, October 3, 2008 // // // http://robocraft.ru // #include <cv.h> #include <highgui.h> #include <math.h> #include <opencv2/opencv.hpp> #ifdef _MSC_VER # if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION ==4 && CV_SUBMINOR_VERSION == 5 // OpenCV 2.4.5 # if defined(_DEBUG) # pragma comment(lib, "opencv_core245d.lib") # pragma comment(lib, "opencv_highgui245d.lib") # pragma comment(lib, "opencv_imgproc245d.lib") # pragma comment(lib, "opencv_video245d.lib") # pragma comment(lib, "opencv_ml245d.lib") # pragma comment(lib, "opencv_calib3d245d.lib") # pragma comment(lib, "opencv_objdetect245d.lib") # pragma comment(lib, "opencv_features2d245d.lib") # pragma comment(lib, "opencv_contrib245d.lib") # pragma comment(lib, "opencv_ts245d.lib") # pragma comment(lib, "opencv_legacy245d.lib") # pragma comment(lib, "opencv_flann245d.lib") # pragma comment(lib, "opencv_gpu245d.lib") # else # pragma comment(lib, "opencv_core245.lib") # pragma comment(lib, "opencv_highgui245.lib") # pragma comment(lib, "opencv_imgproc245.lib") # pragma comment(lib, "opencv_video245.lib") # pragma comment(lib, "opencv_ml245.lib") # pragma comment(lib, "opencv_calib3d245.lib") # pragma comment(lib, "opencv_objdetect245.lib") # pragma comment(lib, "opencv_features2d245.lib") # pragma comment(lib, "opencv_contrib245.lib") # pragma comment(lib, "opencv_ts245.lib") # pragma comment(lib, "opencv_legacy245.lib") # pragma comment(lib, "opencv_flann245.lib") # pragma comment(lib, "opencv_gpu245.lib") # endif //# if defined(_DEBUG) # endif //# if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION == 4 #endif //#ifdef _MSC_VER int main(int argc, char* argv[]) { IplImage* image = 0; // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "image_1.jpg"; // получаем картинку (в градациях серого) image = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE); printf("[i] image: %s\n", filename); assert( image != 0 ); // загрузим оригинальное изображении IplImage* src = cvLoadImage(filename ); // хранилище памяти для кругов CvMemStorage* storage = cvCreateMemStorage(0); // сглаживаем изображение cvSmooth(image, image, CV_GAUSSIAN, 5, 5 ); // поиск кругов CvSeq* results = cvHoughCircles( image, storage, CV_HOUGH_GRADIENT, 1, image->width/5, 40, 5, 10, 60 ); // пробегаемся по кругам и рисуем их на оригинальном изображении for( int i = 0; i < results->total; i++ ) { float* p = (float*) cvGetSeqElem( results, i ); CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) ); cvCircle( src, pt, cvRound( p[2] ), CV_RGB(0xff,0,0) ); } // показываем cvNamedWindow( "cvHoughCircles", 1 ); cvShowImage( "cvHoughCircles", src); // сохраняем кадр в файл cvSaveImage ("out1.jpg", src); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseMemStorage(&storage); cvReleaseImage(& image); cvReleaseImage(&src); cvDestroyAllWindows(); return 0; }
Исходная картинка
![Изображение](http://www.banker.kz/uploads/1354002131/gallery_13947_52_335.jpg)
Обработанная картинка с параметрами
CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
1,
image->width/5,
40, 5, 10, 60
);
![Изображение](http://www.banker.kz/uploads/1354002131/gallery_13947_52_6524.jpg)
Обработанная картинка с параметрами
CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
1,
image->width/5,
40, 10, 10, 60
);
![Изображение](http://www.banker.kz/uploads/1354002131/gallery_13947_52_4271.jpg)
#74
Отправлено 18.04.2013, 12:58:17
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Соревнования нацелены на стимулирование научно-исследовательских способностей школьников к прикладным исследованиям в области науки о Земле и Космосе, космических технологий, моделирования и астрофизики.
Соревнования проходят на базе Международной космической школы им. академика В.Н. Челомея по 9 секциям: «Ракетная техника и инфраструктура», «Космические аппараты», «Космические информационные технологии и моделирование», «Электроника, автоматика и телеметрия, приборостроение», «Космическая биология и медицина», «Экология и космическая деятельность», «Астрофизика и эволюция Вселенной», «Солнечная система», «Энергетика и химия топлив»
Согласно правилам проведения Международных научных соревнований по космическим исследованиям «Открываем мир науки» победители и призеры награжденные дипломами МОН РК I, II, III степени имеют преимущественное право на получение образовательных грантов для обучения в высших учебных заведениях Республики Казахстан.
http://rus.classtime.kz/node/2744
В Атырау школьница изобрела новый вид ракетного топлива
Ученицы атырауской технической гимназии с углубленным изучением английского языка Гаухар ЗАЙДЕНОВА и Аяжан ЖОЛДАСКАЛИ стали призерами IX Международных научных соревнований по космическим исследованиям.
Обе девочки получили право без сдачи ЕНТ поступить в любой вуз страны.
http://www.zakon.kz/...novyjj-vid.html
http://daryn.kz/blogs/view/4/1230
Сообщение отредактировал erbol: 18.04.2013, 14:46:12
#75
Отправлено 21.04.2013, 18:13:19
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Задача: Обнаружить шарик на видеокартинке, найти координаты центра и его радиус. Обвести шарик по окружности зеленой линией и результат показать в окне с видео
Решение: Ищем шарик по цвету и по форме контура. Для поиска по цвету видеокартинка разбивается на три матрицы H, S, V.
Для каждой из них подбираем фильтр из двух значений - верхнего и нижнего. Далее путем суммирования логического получаем величину HSV
Для поиска по форме используем функцию cvHoughCircles
Получился такой код
#include "ardrone/ardrone.h" #define KEY_DOWN(key) (GetAsyncKeyState(key) & 0x8000) #define KEY_PUSH(key) (GetAsyncKeyState(key) & 0x0001) // -------------------------------------------------------------------------- // main(Number of arguments, Argument values) // Description : This is the entry point of the program. // Return value : SUCCESS:0 ERROR:-1 // -------------------------------------------------------------------------- // для хранения каналов HSV IplImage* hsv = 0; IplImage* h_plane = 0; IplImage* s_plane = 0; IplImage* v_plane = 0; // для хранения каналов HSV после преобразования IplImage* h_range = 0; IplImage* s_range = 0; IplImage* v_range = 0; // для хранения суммарной картинки IplImage* hsv_and = 0; int Hmin = 0; int Hmax = 256; int Smin = 0; int Smax = 256; int Vmin = 0; int Vmax = 256; int HSVmax = 256; // // функции-обработчики ползунков // void myTrackbarHmin(int pos) { Hmin = pos; cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range); } void myTrackbarHmax(int pos) { Hmax = pos; cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range); } void myTrackbarSmin(int pos) { Smin = pos; cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range); } void myTrackbarSmax(int pos) { Smax = pos; cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range); } void myTrackbarVmin(int pos) { Vmin = pos; cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range); } void myTrackbarVmax(int pos) { Vmax = pos; cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range); } int main(int argc, char **argv) { // AR.Drone class ARDrone ardrone; // Initialize if (!ardrone.open()) { printf("Failed to initialize.\n"); return -1; } // Get a image IplImage* image = ardrone.getImage(); // создаём картинки hsv = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 ); h_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); s_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); v_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); h_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); s_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); v_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); hsv_and = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); // окна для отображения картинки cvNamedWindow("H range",CV_WINDOW_AUTOSIZE); cvNamedWindow("S range",CV_WINDOW_AUTOSIZE); cvNamedWindow("V range",CV_WINDOW_AUTOSIZE); cvNamedWindow("hsv and",CV_WINDOW_AUTOSIZE); // Создаем ползунки cvCreateTrackbar("Hmin", "H range", &Hmin, HSVmax, myTrackbarHmin); cvCreateTrackbar("Hmax", "H range", &Hmax, HSVmax, myTrackbarHmax); cvCreateTrackbar("Smin", "S range", &Smin, HSVmax, myTrackbarSmin); cvCreateTrackbar("Smax", "S range", &Smax, HSVmax, myTrackbarSmax); cvCreateTrackbar("Vmin", "V range", &Vmin, HSVmax, myTrackbarVmin); cvCreateTrackbar("Vmax", "V range", &Vmax, HSVmax, myTrackbarVmax); // Images IplImage *gray = cvCreateImage(cvGetSize(image), image->depth, 1); IplImage *smooth = cvCreateImage(cvGetSize(image), image->depth, 1); IplImage *canny = cvCreateImage(cvGetSize(image), image->depth, 1); // Canny thresholds int th1 = 50, th2 = 100; cvNamedWindow("canny"); cvCreateTrackbar("th1", "canny", &th1, 255); cvCreateTrackbar("th2", "canny", &th2, 255); // Main loop while (!GetAsyncKeyState(VK_ESCAPE)) { // Update if (!ardrone.update()) break; // Get an image image = ardrone.getImage(); // Выделение шарика по цвету // конвертируем в HSV cvCvtColor( image, hsv, CV_BGR2HSV ); // разбиваем на отдельные каналы cvSplit( hsv, h_plane, s_plane, v_plane, 0 ); cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range); cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range); cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range); cvShowImage( "H range", h_range ); cvShowImage( "S range", s_range ); cvShowImage( "V range", v_range ); // складываем cvAnd(h_range, s_range, hsv_and); cvAnd(hsv_and, v_range, hsv_and); cvShowImage( "hsv and", hsv_and ); // Detect edges cvCanny(hsv_and, canny, th1, th2, 3); // Detect circles CvMemStorage *storage = cvCreateMemStorage(0); CvSeq *circles = cvHoughCircles( canny, storage, CV_HOUGH_GRADIENT, 5, image->width, 125, 50, 10, 30 ); // Draw circles for (int i = 0; i < circles->total; i++) { float *p = (float*) cvGetSeqElem(circles, i); cvCircle(image, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(0,255,0), 3, 8, 0); } // Release memory cvReleaseMemStorage(&storage); // Display the image cvShowImage("camera", image); cvShowImage("canny", canny); cvWaitKey(1); } // Release memories cvReleaseImage(&gray); cvReleaseImage(&image); cvReleaseImage(&canny); cvReleaseImage(&smooth); cvReleaseImage(&hsv); cvReleaseImage(&h_plane); cvReleaseImage(&s_plane); cvReleaseImage(&v_plane); cvReleaseImage(&h_range); cvReleaseImage(&s_range); cvReleaseImage(&v_range); cvReleaseImage(&hsv_and); // удаляем окна cvDestroyAllWindows(); // See you ardrone.close(); return 0; }
В проекте https://github.com/puku0x/cvdrone заменяем содержимое файла main.cpp на наш код
Для красного шарика у меня получились такие значения для фильтров
H - 150, 185
V - 150, 256
S - 70, 160
#76
Отправлено 28.04.2013, 10:55:57
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Проект Puku состоит из нескольких классов. Есть классы ardrone, tcp и udp. К проекту подключается несколько пакетов, которые обеспечивают работу с потоками (pthread), декодирование видео (ffmpeg) и обработку видео (opencv)
Можно конечно создать на основе проекта еще несколько классов. Но чтобы сохранить возможность импорта новых версий проекта я не стал этого делать.
Чтобы работать с классами в драйвере URBI надо создавать класс который наследует нескольким классам, в том числе UObject
Как это делается можно посмотреть в интересной статье noonv
http://robocraft.ru/...orithm/495.html
http://robocraft.ru/...oCraft/394.html
#77
Отправлено 02.05.2013, 08:36:36
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
http://ru.wikipedia....Препроцессор_Си
http://web.znu.edu.u...ter 4/index.htm
Сообщение отредактировал erbol: 02.05.2013, 08:41:22
#78
Отправлено 02.05.2013, 15:12:09
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Этот метод может иметь переменное число аргументов. В объявлении и определении переменное число аргументов задается многоточием в конце списка формальных параметров.
http://www.tdoc.ru/c...ide-page52.html
Для работы с ними (аргументам) используются функции va_start(arg, str) и va_end(arg)
http://www.tdoc.ru/c...ide-page52.html
Макрос va_start предназначен для установки аргумента arg на начало списка необязательных параметров и имеет вид функции с двумя параметрами:
void va_start(arg,str);
Для создания буфера используется функция vsprintf_s
http://msdn.microsof...y/xa1a1a6z.aspx
Для отправки данных используется функция sendto
http://cs.mipt.ru/do.../man/sendto.htm
#79
Отправлено 03.05.2013, 23:33:52
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
#80
Отправлено 08.05.2013, 15:24:22
![](https://vse.kz/public/style_images/osnovnoi34/post_offline.png)
Как работает mutex
http://www.cyberforu...read663602.html
Немного изменил код. Получилось так
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <pthread.h> #include <windows.h> pthread_mutex_t m; int count=0; void* inc_count (void* arg) { Sleep(1000); pthread_mutex_lock(&m); count = count + 1; printf("[%d]",count); pthread_mutex_unlock(&m); return 0; } void* inc_count1 (void* arg) { Sleep(3000); pthread_mutex_lock(&m); count = count + 1; printf("[%d]",count); pthread_mutex_unlock(&m); return 0; } void* inc_count2 (void* arg) { Sleep(5000); pthread_mutex_lock(&m); count = count + 1; printf("[%d]",count); pthread_mutex_unlock(&m); return 0; } int main() { pthread_mutex_init(&m,NULL); pthread_t t1; inc_count(NULL); pthread_create(&t1,NULL,inc_count,NULL); pthread_create(&t1,NULL,inc_count1,NULL); pthread_create(&t1,NULL,inc_count2,NULL); pthread_join(t1,NULL); return 0; }
Настройки проекта
Дополнительные зависимости -> pthreadVC2.lib
Дополнительные каталоги библиотек -> D:\3rdparty\pthread\lib
Дополнительные каталоги включения -> D:\3rdparty\pthread\include
--------------------
Функция pthread_mutex_lock - блокирует мьютекс (если мьютекс уже заблокирован, то поток блокируется, пока его не разблокирует)
pthread_mutex_unlock -разблокирует мюьеткс.
Сообщение отредактировал erbol: 08.05.2013, 17:47:27
Количество пользователей, читающих эту тему: 2
пользователей: 0, неизвестных прохожих: 2, скрытых пользователей: 0