Перейти к содержимому

Фотография

Программирование на квадрокоптере AR.Drone


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 187

#61
erbol

erbol
  • Читатель
  • 361 сообщений
Ладно

#62
erbol

erbol
  • Читатель
  • 361 сообщений
Код драйвера для URBI. Получаем навигационные данные от drone.

Для того чтобы получить заряд батареи в процентах создаем объект и вызываем функцию 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
erbol

erbol
  • Читатель
  • 361 сообщений
"|=" Операция присвоения результата поразрядной дизъюнкции битовых представлений значений целочисленных операндов.

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
erbol

erbol
  • Читатель
  • 361 сообщений
Новый драйвер для измерения навигационных данных. Добавил прием данных углов Эйлера и высоты drone над поверхностью


#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
erbol

erbol
  • Читатель
  • 361 сообщений
Сейчас перечитывал свои старые сообщения в связи с тем, что рисунки не отображаются. Причина в том, что ресурс на котором они размещены перестал существовать.

Решил вернуться к идее метода Хафа и обсудить ее

Вот математический образ, который на мой взгляд помогает понять суть этого метода

Пусть имеется 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
erbol

erbol
  • Читатель
  • 361 сообщений
Установка OpenCV под Windows

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
erbol

erbol
  • Читатель
  • 361 сообщений
Работающее приложение на VC для AR.Drone с OpenCV


https://github.com/puku0x/cvdrone

Обсуждение

https://projects.ard...57#message-5051

Установка

https://github.com/p...ki/How-to-build

#68
erbol

erbol
  • Читатель
  • 361 сообщений

Тут много тем обсуждается о использовании пакета OpenCV


http://www.compvisio...filter=all&st=0


#69
erbol

erbol
  • Читатель
  • 361 сообщений
Для того чтобы URBI мог анализировать информацию с видеокамеры drone, надо научиться получать видеопоток, декодировать его и обрабатывать кадры потока

В решении этой задачи сильно помог проект на который я уже ссылался

https://github.com/puku0x/cvdrone

Автор проекта puku0x

Определился состав ПО. Это библиотеки

ffmpeg - работа с видео
opencv - обработка изображений
pthread - работа с потоками

Так же из проекта puku0x, можно узнать функции этих библиотек которые используются для решения задачи

#70
erbol

erbol
  • Читатель
  • 361 сообщений
http://ru.wikipedia....i/POSIX_Threads

Чтобы пользоваться потоками в программировании надо уметь создавать потоки, блокировки памяти (общего адресного пространства потоков), выполнять необходимые операции в созданных потоках, после выполнения необходимых действий уничтожать потоки. Каждое действие с потоками характеризуется функцией из библиотеки 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
erbol

erbol
  • Читатель
  • 361 сообщений


Вот , парень показывает drone красный шарик и перемещает его в разные стороны . Drone следит за шариком и движется вслед за ним.

Потом на экране видим текст программы на urbiscript

Попробуем выполнить то же самое , пока без URBI

Первое , надо научится находить шарик на экране. У меня это будет теннисный шарик. Спасибо, тенниис !

#72
erbol

erbol
  • Читатель
  • 361 сообщений
Обнаружение шарика на картинке с помощью пакета Opencv

Чем точнее определяем критерии поиска , тем меньше посторонних объектов обнаруживаем в результате поиска

Функция 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
erbol

erbol
  • Читатель
  • 361 сообщений
Программа для поиска центров окружностей на рисунке.

Подбором параметров можно добиться того что все нужные круги будут найдены, а ложных круги не появится на рисунке



//
// Несколько модифицированный пример 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;
}


Исходная картинка

Изображение

Обработанная картинка с параметрами

CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
1,
image->width/5,
40, 5, 10, 60
);

Изображение


Обработанная картинка с параметрами

CvSeq* results = cvHoughCircles(
image,
storage,
CV_HOUGH_GRADIENT,
1,
image->width/5,
40, 10, 10, 60
);

Изображение

#74
erbol

erbol
  • Читатель
  • 361 сообщений
Министерство образования и науки РК в г. Байконур провело IX Международные научные соревнования по космическим исследованиям «Открываем мир науки».

Соревнования нацелены на стимулирование научно-исследовательских способностей школьников к прикладным исследованиям в области науки о Земле и Космосе, космических технологий, моделирования и астрофизики.

Соревнования проходят на базе Международной космической школы им. академика В.Н. Челомея по 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
erbol

erbol
  • Читатель
  • 361 сообщений
Получаем видео с drone, на нем виден красный теннисный шар.

Задача: Обнаружить шарик на видеокартинке, найти координаты центра и его радиус. Обвести шарик по окружности зеленой линией и результат показать в окне с видео

Решение: Ищем шарик по цвету и по форме контура. Для поиска по цвету видеокартинка разбивается на три матрицы 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
erbol

erbol
  • Читатель
  • 361 сообщений
Сборка драйвера для URBI на основе проекта Puku

Проект Puku состоит из нескольких классов. Есть классы ardrone, tcp и udp. К проекту подключается несколько пакетов, которые обеспечивают работу с потоками (pthread), декодирование видео (ffmpeg) и обработку видео (opencv)

Можно конечно создать на основе проекта еще несколько классов. Но чтобы сохранить возможность импорта новых версий проекта я не стал этого делать.

Чтобы работать с классами в драйвере URBI надо создавать класс который наследует нескольким классам, в том числе UObject

Как это делается можно посмотреть в интересной статье noonv

http://robocraft.ru/...orithm/495.html

http://robocraft.ru/...oCraft/394.html

#77
erbol

erbol
  • Читатель
  • 361 сообщений
Директивы препроцессора

http://ru.wikipedia....Препроцессор_Си

http://web.znu.edu.u...ter 4/index.htm

Сообщение отредактировал erbol: 02.05.2013, 08:41:22


#78
erbol

erbol
  • Читатель
  • 361 сообщений
Класс UDPSocket (проекта Puku) имеет метод sendf(char *str, ...)

Этот метод может иметь переменное число аргументов. В объявлении и определении переменное число аргументов задается многоточием в конце списка формальных параметров.

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
erbol

erbol
  • Читатель
  • 361 сообщений
Микрочип DARPA: навигация без GPS

http://rnd.cnews.ru/...13/04/17/526174

#80
erbol

erbol
  • Читатель
  • 361 сообщений
Потоки и мьютексы

Как работает 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

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.