Не так давно я уже похвастался, что мою(и Zoltberg-а) статью про Arduino — «Веб-камера на сервоприводах» опубликовали в журнале Хакер. Статья уже выложена на их сайте и её можно прочитать здесь.
Вкратце расскажу про создание такой камеры.
Как видно на фотографии, я собрал поворотную основу для камеры из самых простых и дешёвых маленьких серв — SG-90.
Камера крепится прямо к качалке верхней сервы, которая привинчивается к Г-образной загогулине, вылепленной из ПКЛ (поликапролактон — замечательный пластик для моделирования и прототипирования!). Эта же загогулина другим концом крепится к качалке второй сервы.
Основу я недолго думая вырезал из пластиковой бутылки 🙂 Хотя можно было бы вылепить из того же пластика ПКЛ 😉
Вот и вся механика. Очень просто и быстро. Использовать ПКЛ для таких поделок сплошное удовольствие. Но если у вас нет под рукой паяльной станции с феном, то нужно держать наготове чайник с кипятком 😉
Так же обратите внимание, что массивные детали из пластика будут размегчаться дольше, чем мелкие. Это можно наблюдать по цвету. Нагреваясь пластик становится прозрачным, а в глубине у него может оставаться белый стержень более холодного и твёрдого пластика.
Далее обе сервомашинки напрямую подключаются к 7 и 8 портам контроллера Arduino/CraftDuino :
В данном случае Arduino/CraftDuino играет роль шлюза, т.е. углы поворота сервомашинок передаются контроллеру по последовательному порту от управляющей программы на ПК, а Arduino просто получает значение угла поворота и поворачивает нужную серву на заданный угол.
Для работы с сервомашинками воспользуемся библиотекой Servo, а для общения с контроллером через последовательный порт используем библиотеку Firmata, которая так же как и библиотека Servo уже входит в стандартный набор библиотек Arduino IDE.
Вот какая программа для Arduino у нас получится (фактически — это немного модифицированный пример, поставляемый с библиотекой Firmata)
#include <Firmata.h> #include <Servo.h> Servo servo7; Servo servo8; void analogWriteCallback(byte pin, int value) { if(pin == 7) servo7.write(value); if(pin == 8) servo8.write(value); } void setup() { Firmata.setFirmwareVersion(0, 2); Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); servo7.attach(7); servo8.attach(8); Firmata.begin(9600); } void loop() { while(Firmata.available()) Firmata.processInput(); }
Вот и всё — механика и электроника готовы и остаётся только написать программу для управления этим мини-роботом!
Так как дальнейшие планы научить этого мини-web-cam-бота самостоятельно обнаруживать объекты и следить за ними, то для работы с камерой я воспользуюсь библиотекой OpenCV.
Управляющая программа довольно простая.
Подключаемся к web-камере и показывам её картинку. Так же выведем в окошко с картинкой пару ползунков, с помощью которых будем управлять положением сервомашинок.
Так как в моей конструкции робота web-камеру пришлось закрепить на боку, то в программе приходится это исправлять (поворачивать картинку на 90 градусов против часовой стрелки).
Эта процедура реализуется функцией rotate(), которая является обёрткой вокруг функции OpenCV: cvWarpAffine(), которая и выполняет поворот изображения (Аффинное преобразование).
// // программа для управления // сервомашинками мини-web-cam-бота // // robocraft.ru #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> #include "serial.h" Serial sg; // для работы с COM-портом // положение 1-й сервы int A = 0; int Amax = 180; // положение 2-й сервы int F = 0; int Fmax = 180; IplImage* dest = 0; // // функции-обработчики ползунков // void myTrackbarA(int pos) { A = pos; // Firmata char buf[3]; buf[0] = 0xE0 | 7; buf[1] = A & 0x7F; buf[2] = (A >> 7) & 0x7F; sg.Send(buf, 3); Sleep(100); } void myTrackbarF(int pos) { F = pos; // Firmata char buf[3]; buf[0] = 0xE0 | 8; buf[1] = F & 0x7F; buf[2] = (F >> 7) & 0x7F; sg.Send(buf, 3); Sleep(100); } // функция поворота изображения на заданный угол void rotate(IplImage* _image, double _angle=90) { // матрицы трансформации CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1); // вращение относительно центра изображения CvPoint2D32f center = cvPoint2D32f(_image->width/2, _image->height/2); double angle = _angle; double scale = 1; cv2DRotationMatrix(center,angle,scale,rot_mat); IplImage* Temp = 0; Temp = cvCreateImage(cvSize(_image->width, _image->height) , _image->depth, _image->nChannels); // выполняем вращение cvWarpAffine(_image,Temp,rot_mat); // сохраняем результат cvCopy(Temp, _image); cvReleaseImage(&Temp); cvReleaseMat(&rot_mat); } int main(int argc, char* argv[]) { // получаем любую подключённую камеру CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY); assert( capture ); // устанавливаем ширину и высоту кадра cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);//1280); cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);//960); IplImage* frame=0; // окно для вывода изображения cvNamedWindow("capture", CV_WINDOW_AUTOSIZE); // инициализация COM-порта int port=19; // номер виртуального COM-порта Arduino printf("[i] try to open COM-port %d\n", port); bool b = sg.Open(port, 9600); if(!b) { printf("[!] Error open COM-port!\n"); return 1; } printf("[i] ok\n"); // добавляем ползунки для управления положением сервомашинок cvCreateTrackbar("A", "capture", &A, Amax, myTrackbarA); cvCreateTrackbar("F", "capture", &F, Fmax, myTrackbarF); // цикл обработки кадров с камеры while(true){ // получаем кадр frame = cvQueryFrame( capture ); // копируем изображение dest = cvCloneImage(frame); // поворачиваем картинку на 90 градусов rotate(dest); // показываем cvShowImage("capture", dest); // освобождаем изображение cvReleaseImage(&dest); char c = cvWaitKey(33); if (c == 27) { // нажата ESC break; } } // освобождаем ресурсы sg.Close(); cvReleaseCapture( &capture ); cvDestroyWindow("capture"); return 0; }
Вот и всё!
Главное — желание и хорошая идея! 😉
исходники к статье можно скачать по адресу:
/files/opencv/servobot/servobot.zip
24 комментария на «“Управляемая веб-камера или же web-cam-бот”»
Подскажите пожалуйста, чем компилируется второй код программы (программа для управления сервомашинками мини-web-cam-бота)?
а с serial.h случайм serial.lib и serial.dll нет???, а то чёто ругается на неразрешенные внешние элементы… и она тока для Arduino или можно с чем угодно юзать?
исходники классаSerial есть в архиве . Ничего дополнительного ему не требуется. Как я уже указал — для передачи углов поворота используется протокол Firmata , но от него можно отказаться и использовать что-то другое — для этого нужно просто изменить содержимое функций
спс
В общем остаточно оригинально и технически интересно, но имхо можно было бы и по красивей. Например самая нижняя серва отвечает не за горизантальный а за вертикальный угол, к ней в притык серва за горизонталь, камера весит на трубке. Тогда весь механизм и электронику можно спрятать в коробку с прорезью, и снаружи только камера. Так красивей смотреться будет.
Я конечно извиняюсь, но конструкция у вас выглядит как-то не очень 🙂
Я тож управляемую камеру делал (это наверное первая мысля у всех ардуиновцев, купивших первую серву), но управление по сети. Мало того — из браузера. Ардуина пашет независимо от компа, спасибо езернет шылду. Перемещение либо клавишами вверх-вниз-влево-вправо, либо мышой щёлкать по соответсвующим ссылкам. Но намного интересней пропорциональное управление — в брауере нарисован квадрат, все движения мыши с нажатой левой кнопкой фиксируются и пишутся в БД, откуда читаются и обрабатываются ардуиной.
Пара ссылок на эту мою управляемую хреновинку. Первая ссылка эт первый рабочий вариант, там сервы местами перепутаны были 🙂 Вторая ссылка — видеоролик уже с окончательной крутилкой, правда я там больше процесс движения камеры снимал, а не само управление. Вроде виден там зелёный квадрат для управления.
http://www.g0l.ru/blog/n2436
http://www.g0l.ru/blog/n2446
Сейчас камера отключена, ибо хочу доработать механику и на балкон поставить. Скетчи тож пока не выкладываю, ибо там сплошь тестовый говнокод 😀 Но вот свою капельку опыта подкидываю, мож кому пригодится.
Отличная работа! На счёт конструкции вы правы — просто делал всё очень быстро — хотел по-быстрее реализовать идею. Нужно будет переделать 🙂Ethernet-шылд — тоже супер. Но у меня в планах добавить обработку видео и реализовать слежение за объектом 😉
Управление через
во, новый ролик снялhttp://www.g0l.ru/blog/n2563
правда, темновато получилось 🙂
Статья была написана больше года назад… но надеюсь мне ещё ктонибудь ответит… Пытался повторить вышеуказаный проект у себя, в качестве языка программирования использовал JavaSE в связке с библиотекой RXTX для общения по COM порту… столкнулся с проблеммой, как передавать сообщение контроллеру… Дело в том что функция myTrackbarF передает сообшения в виде массива char, а Java может отправлять либо массив байт, либо число типа int… Пробовал явное приведение типов (byte) char, никакого эффекта не получил… пробовал передавать последовательно 3 числа тоже не проходит… Подскажите как можно передать данные так, чтобы Firmata их схавал… Заранее спасибо.
Всё, разобрался — моя ошибка незнание… byte — это тоже по сути своей char, только в числовом представлении… а сообщение у меня отправлялось… вот только отправлял я его всего один раз… А при первой отправки данных контроллеру он их куда то теряет, зато все последующие идут прямо на ура)
уж точно не больше года назад, а в конце 2010-го :)))))
хм… а в примере как передаётся?
— передаётся тот же массив байт О_о
Доброго времени суток. Подскажите, как следует искать нужные точки на изображении и по ним уже делать поворот? Например что бы книга всегда была в вертикальном положение. Центрировать ее как то по углам же надо? Меня интересует поиск таких точек и дальнейший поворот на основе этих точек.
см.Трансформация изображения — аффинные преобразования, гомография . Соответственно, вам нужно сделать обратное преобразование, откуда получить углы поворота камеры.
Здравствуйте, а можно ли подключить еще одну серво-машинку (третью) чтобы она поворачивалась на запрограммированный угол когда камера находит движущийся объект? это нужно прописать в ардуино, но и в опен Cv? какие строки добавить и куда, спасибо
Привет! Можно. Разумеется, нужно будет прописать обработку и на контроллер Arduino и в программу на ПК.
Извините, а у вас есть почта?
или вк
Для всех вопросов естьфорум .
я просто хотел чтоб вы дописали код под третью серву конечно не за просто так.
Код записан для пайтона2? Установил пайтон2, вгрузил код (мини-web-cam-бота), выдает синтактическая ошибка. ПОЧЕМУ?
А где вы увидели код на питоне?
Программа одна написана для ардуино, а другая я так понял для питона 2.
В данном случае, приводится программа на C++, но, разумеется, ничего не мешает реализовать подобное и на питоне.
А лучше этот проект на чем запускать?