CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

7. OpenCV шаг за шагом. Захват видео с камеры

1. OpenCV шаг за шагом. Введение.
2. OpenCV шаг за шагом. Установка.
3. OpenCV шаг за шагом. Hello World.
4. OpenCV шаг за шагом. Загрузка картинки.
5. OpenCV шаг за шагом. Вывод видео
6. OpenCV шаг за шагом. Ползунок
7. OpenCV шаг за шагом. Захват видео с камеры

Работа с камерой почти ничем не отличается от работы с видео.
Просто вместо функции cvCreateFileCapture() нужно использовать функцию cvCreateCameraCapture(), которая в качестве параметра принимает не название файла, а идентификатор камеры.
Данная программа представляет собой удобную утилиту для работы с камерой.
Программа подключается и начинает захват с камеры с помощью cvCreateCameraCapture(), далее получает ширину и высоту кадра с помощью cvGetCaptureProperty(). А потом в цикле при помощи cvQueryFrame() получает картинку с камеры и выводит в окошко.
При нажатии клавиши ESC программа выйдет из цикла и завершится, а при нажатии клавиши Enter текущий кадр будет сохранён в файл ImageN.jpg, где N — номер кадра, начиная от 0 (Image0.jpg, Image1.jpg и т.д.)

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	// получаем любую подключённую камеру
	CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY); //cvCaptureFromCAM( 0 );
	assert( capture );

	//cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);//1280); 
	//cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);//960); 

	// узнаем ширину и высоту кадра
	double width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
	double height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
	printf("[i] %.0f x %.0f\n", width, height );

	IplImage* frame=0;

	cvNamedWindow("capture", CV_WINDOW_AUTOSIZE);

	printf("[i] press Enter for capture image and Esc for quit!\n\n");

	int counter=0;
	char filename[512];

	while(true){
		// получаем кадр
		frame = cvQueryFrame( capture );

		// показываем
		cvShowImage("capture", frame);
	
		char c = cvWaitKey(33);
		if (c == 27) { // нажата ESC
			break;
		}
		else if(c == 13) { // Enter
			// сохраняем кадр в файл
			sprintf(filename, "Image%d.jpg", counter);
			printf("[i] capture... %s\n", filename);
			cvSaveImage(filename, frame);
			counter++;
		}
	}
	// освобождаем ресурсы
	cvReleaseCapture( &capture );
	cvDestroyWindow("capture");
	return 0;
}


Посмотрим результаты работы (камера – дешёвая USB Gembird 69U):

OpenCV v1.0 показывает и сохраняет картинку минимального разрешения камеры 320x240
Установить большее разрешение при помощи cvSetCaptureProperty() не даёт

А вот что выдаёт последняя стабильная версия OpenCV 2.1
у которой, кстати, сразу в комплекте идут скомпилированные lib-файлы C:\DevTools\OpenCV2.1\lib\ и которая завелась даже под VC++ 6.0
Установка аналогична 2.0 только теперь нужно линковать библиотеки
cxcore210.lib cv210.lib highgui210.lib cvaux210.lib


а теперь раскомментируем строчки
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);//1280); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);//960); 


так же заработало и при 1280x960.
Однако, должен отметить, что не всегда удаётся установить нужное разрешение штатными средствами и приходится делать финт ушами.

новые функции:
#define cvCaptureFromCAM cvCreateCameraCapture

CVAPI(CvCapture*) cvCreateCameraCapture( int index );
— начинает захват с камеры

index — номер камеры в системе (состоит из суммы порядкового номера и т.н. домена)
0 — первая попавшаяся камера(можно использовать, если работает всего одна камера)
возможные домены:
#define CV_CAP_ANY      0     // autodetect
#define CV_CAP_MIL      100   // MIL proprietary drivers
#define CV_CAP_VFW      200   // platform native
#define CV_CAP_V4L      200
#define CV_CAP_V4L2     200
#define CV_CAP_FIREWARE 300   // IEEE 1394 drivers
#define CV_CAP_FIREWIRE 300
#define CV_CAP_IEEE1394 300
#define CV_CAP_DC1394   300
#define CV_CAP_CMU1394  300
#define CV_CAP_STEREO   400   // TYZX proprietary drivers
#define CV_CAP_TYZX     400
#define CV_TYZX_LEFT    400
#define CV_TYZX_RIGHT   401
#define CV_TYZX_COLOR   402
#define CV_TYZX_Z       403
#define CV_CAP_QT       500   // QuickTime
#define CV_CAP_UNICAP   600   // Unicap drivers
#define CV_CAP_DSHOW    700   // DirectShow (via videoInput)


CVAPI(int) cvSaveImage( const char* filename, const CvArr* image, const int* params CV_DEFAULT(0) );
— сохраняет изображение в файл
filename — имя файла
image — изображение для сохранения

при успешном сохранении функция вернёт 1, а при неудаче — 0.



Далее: 8. OpenCV шаг за шагом. Запись видео

Дополнительно:
24. Работа с камерой через библиотеку videoInput
OpenCV и работа с видео
  • 0
  • 17 июля 2010, 10:19
  • admin

Комментарии (49)

RSS свернуть / развернуть
+
+1
Скопировал пример один к одному. Все скомпилировалось, программа запускается, но выдает разрешение 0*0 и серый квадрат.
Камера в других приложения (проводник, VLC) нормально работает.
В чем может быть дело?
avatar

Upryamyj

  • 7 января 2011, 18:23
+
0
версия OpenCV?
какая камера?
пробовали изменить разрешение/ не изменять разрешения (оставить дефолтным)?
avatar

noonv

  • 10 января 2011, 20:43
+
0
OpenCV 2.2.0, ОС Windows, VC++ 2005 Express Edition.
Библиотеки скомпилировались без ошибок, сделал все уроки со 2-го по 23-й, все работает, кроме захвата с камеры.
Камера в китайском телефоне, подключается телефон по USB, работает во всех приложениях без драйверов.
Пробовал не указывать разрешение, 320*240, 540*480.
Результат — серый квадрат, а в консоли информация о разрешении 0*0.
avatar

Upryamyj

  • 10 января 2011, 21:21
+
0
640*480 конечно.
avatar

Upryamyj

  • 10 января 2011, 21:38
+
0
похоже проблема именно в доступе к камере — попробуйте использовать библиотеку videoInput
avatar

noonv

  • 14 января 2011, 10:49
+
0
Была та же проблема. Помогает videoInput. И еще у меня заработало после включения программы WebcamMax. Кто-нибудь знает как работает эта программа?
avatar

CaptNemo

  • 3 мая 2015, 11:03
+
0
Тоже самое, что и у «Upryamyj»-серый квадрат и разрешение 0*0. Что делать? Может, проблемы с камерой?
avatar

passick

  • 10 января 2011, 20:20
+
0
avatar

noonv

  • 10 января 2011, 20:43
+
0
OpenCV 2.2, Windows, Code::Blocks.
Телефон от philips в качестве вебкамеры.
Пробывал менять — всё равно серый экран и выдаёт в качестве разрешения 0*0.
avatar

passick

  • 11 января 2011, 20:40
+
0
как видите — у вас с Upryamyj-м и камеры чем-то похожи, так что похоже проблема именно в доступе к камере — попробуйте использовать библиотеку videoInput
avatar

noonv

  • 14 января 2011, 10:50
+
0
У меня камера нормальная, также разрешение 0 на 0 если использовать cvCreateCameraCapture, но videoinput к счастью помогла :)
avatar

jne100

  • 15 июня 2011, 23:17
+
0
else if(c == 13) { // Enter

В Линукс не работает. Поменял на 10 запустилось. Видимо в Линуксе в конце строки LF а не CR
avatar

v1ctor

  • 21 марта 2011, 16:43
+
0
верно — в линуксе коды клавиш отличаются :)
avatar

noonv

  • 21 марта 2011, 16:44
+
0
Уважаемый Господин! Возник у меня вопрос вот я сейчас пробежался и дошел увидел как раз урок — то что мне надо, это захват изображения с камеры, попробывал не работает, хотя камера не с телефона нормальная 720p, Посмотрел библиотеку videoInput и вопрос смогу ли я захватив камеры с этой библиотекой сохранить его в файл, и смогу ля я к этому захваченному изображению применять функции из OpenCV прям то есть находу, а не открывая сохраненный видеофайл заново Я нуб в этом деле) Спасибо за Help))))
avatar

DOMOVOI

  • 20 ноября 2011, 22:14
+
0
да. там же в исходнике есть комментарий:
// здесь уже можно работать с картинкой
// с помощью функций OpenCV

так что в image уже хранится данные захваченной картинки и к ней можно применять средства OpenCV.
avatar

noonv

  • 21 ноября 2011, 06:28
+
0
Не могу сделать захват со второй камеры. Opencv 2.2 win QtSDK 4.7.4
cvCreateCameraCapture -индексам <0...10, 10...99, 200...299 всегда соответствует захват 1 камеры, остальные возвращает нулевыми
Обе камеры определяются как видеоустройства 1 и 2. Штатными средствами ОС можно с них получить картинку.
В faq ocv видел ссылки на модуль cvcam с инструментарием для выбора камеры, но, похоже из текущих версий библиотеки его убрали.
Вообще стоит задача получения синхронных снимков с нескольких камер.
avatar

ibnz

  • 6 декабря 2011, 22:06
+
0
к сожалению, пока руки никак не дойдут поработать со стереозрением, хотя в планах это и есть (для начала, хотя бы купить две одинаковых камеры :)))
Для конкретных задач, похоже, лучше всё же использовать не штатный захват OpenCV, а кастомные решения.
Например, под Windows — можно попробовать библиотеку videoInput, а под Linux — libv4l2cam.
avatar

noonv

  • 7 декабря 2011, 07:14
+
0
да videoinput помог с решением, спасибо.
avatar

ibnz

  • 7 декабря 2011, 10:20
+
0
серый квадрат вылечился заменой на cvCaptureFromCAM(1)
avatar

ales_aleles

  • 24 апреля 2013, 19:03
+
0
Добрый день. А нет ли здесь утечки памяти? не нужно ли делать в конце каждого цикла cvReleaseImage(&frame)?
avatar

igormat

  • 12 июня 2013, 14:50
+
0
нет. с картинкой frame, получаемой от cvQueryFrame() ничего делать не нужно.
avatar

noonv

  • 12 июня 2013, 21:01
+
0
А как подключать IP-камеры?
avatar

Misha

  • 19 июня 2013, 12:20
+
0
если камера выдаёт картинку в MJPG, то посмотрите сюда
avatar

noonv

  • 19 июня 2013, 16:30
+
0
Спасибо за быстрый ответ и ссылочку!
Однако вопросы ещё имеются.
1. Нельзя ли для работы с IP-камерой использовать возможности только самой OpenCV?
Работать-то с USB-камерами в OpenCV очень просто: в одной строке захватил камеру, в другой — считал кадр, в третьей — показал его. Хочется такого же комфорта и с IP-камерой.
2. Ваш вариант работает только с MJPEG, а как работать с MPEG-4, H.264, наконец, просто JPEG?
3. Как всё это организовать на чистом Си (без "++")?
avatar

Misha

  • 20 июня 2013, 02:04
+
0
если OpenCV собран с поддержкой FFmpeg и ffmpeg позволяет работать, то должен подхватить ;)
т.е. будет достаточно сделать стандартный
cv::VideoCapture vcap;

    // This works on a D-Link CDS-932L
    const std::string videoStreamAddress = "http://<username:password>@<ip_address>/video.cgi?.mjpg";

    //open the video stream and make sure it's opened
    if(!vcap.open(videoStreamAddress)) {
        std::cout << "Error opening video stream" << std::endl;
        return -1;
    }
avatar

noonv

  • 20 июня 2013, 06:45
+
0
Спасибо за быстрый ответ!

Как узнать, собран OpenCV с поддержкой FFmpeg или нет?

Я имею ввиду вариант, когда OpenCV не собирается из исходников (CMake и всё такое), а используется «из коробки». Интересуют последние, на текущий момент, версии OpenCV: 2.4.3… 2.4.5.
avatar

Misha

  • 20 июня 2013, 10:25
+
0
Добрый вечер! Столкнулся с проблемой: Скопировал пример, все работает, НО! изображение идет с ТВ-тюнера! Кто-нибудь сталкивался с подобным? Какой параметр cvCreateCameraCapture( int index ) указать для обычной веб-камеры? Как в программе указать, с какой камерой (устройством видеозахвата) нужно работать?
avatar

goga770

  • 4 августа 2013, 00:42
+
0
Перечитал форум, разобрался)))
CvCapture* capture = cvCaptureFromCAM( 1 );
avatar

goga770

  • 4 августа 2013, 00:46
+
0
какой протокол использует opencv при работе с камерами?
avatar

jacknk88

  • 24 ноября 2013, 14:15
+
0
avatar

noonv

  • 27 ноября 2013, 12:49
+
0
есть ли примеры по кадровой обработки видео, т.е. в реальном времени сравнить два кадра, пр., текущий и предыдущий кадр?
avatar

jacknk88

  • 30 ноября 2013, 17:14
+
0
Ребят, нужна помощь. Хочу эту программу совместить с программой для подсчета и определения доминирующих цветов в изображении. Нужно чтобы камера по нажатию кнопки фотографировала и определяла доминирующие цвета в полученном изображении. Как это правильно сделать? Вот ссылка на прогу, определяющую доминирующие цвета robocraft.ru/blog/computervision/1063.html
avatar

posehn

  • 2 февраля 2014, 18:08
+
0
Не подскажите как вывести или записать изображения с экрана? Как захватить изображение целого экрана?
avatar

Lokki23

  • 3 января 2016, 19:27
+
0
Здравствуйте.
Как у некоторых выше, и я получил черный экран. Вебка USB, дрова винда сама поставила. Библиотеку videoInput мне не удалось прикрутить к Eclipse Kepler + MinGW 4.8.1 + OpenCV 3.1.0. Но пример с этой страницы успешно заработал. Подскажите пожалуйста как теперь мне например воспользоватся функцией cvSmooth тоесть как из переменной типа «Mat» взять данные типа «IplImage». Я Си++ почти незнаю, только начал изучать, а попробовать хочется.
avatar

Apparatchik

  • 25 мая 2016, 16:15
+
0
Привет!
Если используется интерфейс C++, то и функции логичнее использовать С++-ые, которые работают с cv::Mat.
Хотя cvSmooth() считается устаревшей и вместо неё рекомендуется использовать: GaussianBlur(), blur(), medianBlur()

Преобразовать cv::Mat в IplImage можно при помощи оператора IplImage.
avatar

noonv

  • 25 мая 2016, 16:27
комментарий был удален

+
0
Можно примерчик с этим оператором. После Си не совсем въеду как им пользоватся. функцию взял для примера, ведь во всех мануалах подобные функции. Не подскажите где почитать на русском по поводу устаревших и их рекомендуемой замены? Цель как и у многих — научится распознавать предметы, попутно изучая Си++.
avatar

Apparatchik

  • 25 мая 2016, 17:49
+
0
// To pass the new matrices to the functions that only work with IplImage or CvMat do:
// step 1) Convert the headers (tip: data will not be copied).
// step 2) call the function   (tip: to pass a pointer do not forget unary "&" to form pointers) 
cv::Mat mat_img;
IplImage ipl_img = mat_img;

// преобразование IplImage в cv::Mat
// и обратно
IplImage ipl_img;
cv::Mat mat_img(ipl_img);

Про устаревшие и замену — только в документации.
avatar

noonv

  • 25 мая 2016, 18:04
+
0
Не выходит чет у меня:

VideoCapture cap(CAP_ANY); // открыть доступную камеру
 if (!cap.isOpened())  // проверить открылась ли
      return -1;

Mat frame;
namedWindow("original", WINDOW_AUTOSIZE);

cap >> frame; // получаем очередной кадр

imshow("original", frame); // выводим кадр в окно

IplImage* image = 0;
cvNamedWindow("test", WINDOW_AUTOSIZE);

// как сделать чтоб в image попал этот же кадр и например вывести его в другое окошко функцией ниже (либо использовать любую другую функцию)
// что я не делал либо проблемы при компиляции либо открывается окошко и "программа завершила свою работу, поиск решений бла-бла"

cvShowImage("test", image);



P.S нужно ли специально освобождать память как в здешних мануалах, в примере с VideoCapture сказано чтото про автоматически освободится или я не так понял.
avatar

Apparatchik

  • 25 мая 2016, 19:43
+
0
С первым разобрался, огромное спасибо за помощь. Кому интересно надо было сделать так:

IplImage image;
image = IplImage(frame);
cvShowImage("test", &image);

Второй вопрос остается в силе.
avatar

Apparatchik

  • 25 мая 2016, 23:04
+
0
Здравствуйте.

Один кадр я беру так:

Mat frame;

capture.read(frame);

Как мне скопировать этот кадр и дальше обрабатывать его независимо?

Mat frame_2;

frame_2 = frame;

вот так не работает, вернее работает но нарисованое на frame попадает в frame_2.
avatar

Apparatchik

  • 3 ноября 2016, 14:40
+
0
Mat frame_2 = frame.clone(); // Creates a full copy of the array and the underlying data.
avatar

noonv

  • 3 ноября 2016, 14:44
+
0
Спасибо!
avatar

Apparatchik

  • 3 ноября 2016, 14:58
+
0
Здравствуйте! Сделал все как указано в уроке, но при запуске программы получаю черное окошко, в котором по идее должно отображаться изображение с вебки. Вебка при этом включается, но изображение не выводится, только черный квадрат. Как это можно решить?
Visual Studio 2015, OpenCV 3.1.0
avatar

Batradz

  • 5 ноября 2016, 12:28
+
0
Попробуйте пройтись отладчиком (OpenCV и работа с видео)
avatar

admin

  • 5 ноября 2016, 12:52
+
0
Не очень разобрался, с тем как с этим работать, не могли бы описать действия?
avatar

Batradz

  • 5 ноября 2016, 13:37
+
0
Суть еще в том, что, если данный код закомпилить на 2012 студии то проблем не возникает, но хотелось бы разобраться в чем проблема в 15 студии и как это можно решить
avatar

Batradz

  • 5 ноября 2016, 13:39

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.