Перейти к содержимому
Compvision.ru
nhr

Оптический поток

Recommended Posts

Пишу программу для определения траекторий движения. Ниже представлен код программы. Проблема в следующем, она написана на С, у меня многие функции просто не воспринимаются. Переписываю под синтаксис С++, что мог, то исправил, помогите исправить оставшееся. Проблема в resize(frame, frame1, Size(200, 200)); не воспринимает frame

#include "opencv/cv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include "opencv2/objdetect/objdetect.hpp"
#include <fstream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>


using namespace std;
using namespace cv;

CvCapture* g_capture = NULL;
//IplImage* frame;
//IplImage* frame1 = 0;

int main(int argc, char** argv)

{
	
	Mat video, gray, frame, prevgray, flow, cflow;
	bool frame1 = true;
	cvNamedWindow("Testing", CV_WINDOW_AUTOSIZE);
	string fname = "D:/miting_Kharkov.mp4";
	// получение следующего кадра
	while (1)
		{
        // получаем следующий кадр
			
		VideoCapture cam(fname);
		cam >> frame;

        // показываем кадр
		imshow("Testing", frame);
		
		// уменьшаем размер изображения для убыстрения работы
		if (frame1)
		{
			//CvSize c = cvGetSize(frame); //аналоги ли это frame.size()
			CvSize c = frame.size();
			c.height = c.height / 2;
			c.width = c.width / 2;
			frame1 = cvCreateImage(c, 8, 3); // серое изображение

		}
					
		resize(frame, frame1, Size(200, 200));
		cvtColor(frame1, gray, CV_BGR2GRAY);
		
		// вычисление оптического потока
		if (prevgray.data)
		{
			calcOpticalFlowFarneback(prevgray, gray, flow, 0.5, 3, 15, 3, 5, 1.2,0);
			cvtColor(prevgray, cflow, CV_GRAY2BGR);
			//drawOptFlowMap(flow, cflow, 16, 1.5, CV_RGB(0, 255, 0));
			imshow("flow", cflow);
		}

		//Ожидание нажатия ESCAPE
		char c = cvWaitKey(10);
		if (c == 27) break;
		//i++;
		//onTrackbarSlide(i);
		swap(prevgray, gray);
	}
	cvReleaseCapture(&g_capture);
	cvDestroyWindow("Testing");
	return 0;
}

При отладке выскакивают следующие ошибки:

 

1>Source.cpp(58): warning C4800: 'IplImage *' : forcing value to bool 'true' or 'false' (performance warning)

1>Source.cpp(62): error C2664: 'void cv::resize(cv::InputArray,cv::OutputArray,cv::Size,double,double,int)' : cannot convert argument 2 from 'bool' to 'cv::OutputArray'

1>          Reason: cannot convert from 'bool' to 'const cv::_OutputArray'

1>          No constructor could take the source type, or constructor overload resolution was ambiguous

1>Source.cpp(68): error C3861: 'calcOpticalFlowFarneback': identifier not found

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Такс, одну ошибку исправил, добавил библиотеку video.hpp и calcOpticalFlowFarneback теперь воспринимается программой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Взято из стандартных примеров OpenCV, идущих в комплекте с исходниками (fback.cpp):

#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/videoio/videoio.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>

using namespace cv;
using namespace std;

static void help()
{
    cout <<
            "\nThis program demonstrates dense optical flow algorithm by Gunnar Farneback\n"
            "Mainly the function: calcOpticalFlowFarneback()\n"
            "Call:\n"
            "./fback\n"
            "This reads from video camera 0\n" << endl;
}
static void drawOptFlowMap(const Mat& flow, Mat& cflowmap, int step,
                    double, const Scalar& color)
{
    for(int y = 0; y < cflowmap.rows; y += step)
        for(int x = 0; x < cflowmap.cols; x += step)
        {
            const Point2f& fxy = flow.at<Point2f>(y, x);
            line(cflowmap, Point(x,y), Point(cvRound(x+fxy.x), cvRound(y+fxy.y)),
                 color);
            circle(cflowmap, Point(x,y), 2, color, -1);
        }
}

int main(int, char**)
{
    VideoCapture cap(0);
    help();
    if( !cap.isOpened() )
        return -1;

    Mat flow, cflow, frame;
    UMat gray, prevgray, uflow;
    namedWindow("flow", 1);

    for(;;)
    {
        cap >> frame;
        cvtColor(frame, gray, COLOR_BGR2GRAY);

        if( !prevgray.empty() )
        {
            calcOpticalFlowFarneback(prevgray, gray, uflow, 0.5, 3, 15, 3, 5, 1.2, 0);
            cvtColor(prevgray, cflow, COLOR_GRAY2BGR);
            uflow.copyTo(flow);
            drawOptFlowMap(flow, cflow, 16, 1.5, Scalar(0, 255, 0));
            imshow("flow", cflow);
        }
        if(waitKey(30)>=0)
            break;
        std::swap(prevgray, gray);
    }
    return 0;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо за столь быстрый ответ. 

Вот только 

UMat gray, prevgray, uflow;

у меня нет такого оператора

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно заменить на Mat.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кластеризуйте четырехмерные векторы (x,y,vx,vy), это даст Вам движущиеся объекты (компактные группы точек, движущихся в одном направлении).

 

Правда сразу возникает проблема выбора количества кластеров.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кластеризуйте четырехмерные векторы (x,y,vx,vy), это даст Вам движущиеся объекты (компактные группы точек, движущихся в одном направлении).

 

Правда сразу возникает проблема выбора количества кластеров.

 

Чтобы не париться с числом кластеров, можно применять, например, иерархическую кластеризацию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Мне кажется это подойдет: http://docs.opencv.org/modules/flann/doc/flann_clustering.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

using namespace std;
using namespace cv;

void drawOptFlowMap(const Mat& flow, Mat& cflowmap, int step, double scale, const Scalar& color)
{
for (int y = 0; y < cflowmap.rows; y += step)
for (int x = 0; x < cflowmap.cols; x += step)
{
const Point2f& fxy = flow.at<Point2f>(y, x);
line(cflowmap, Point(x, y), Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), color);
circle(cflowmap, Point(x, y), 2, color, -1);
}
}

int main(int argc, char** argv)
{
int s = 2; // масштабирующий коэффициент
Mat  frame, flow, cflow;
Mat  prvs, next, gray;
Mat framepoints;
cv::flann::KMeansIndexParams fln_idx = cv::flann::KMeansIndexParams();

cvNamedWindow("Testing", 1);
char fname[100] = "miting_Kharkov.mp4";
VideoCapture cam(fname);


if (!(cam.read(frame)))
return 0;
resize(frame, prvs, Size(frame.size().width / s, frame.size().height / s));
cvtColor(prvs, prvs, CV_BGR2GRAY);

while (1)
{
if (!(cam.read(frame)))
break;

resize(frame, next, Size(frame.size().width / s, frame.size().height / s));
cvtColor(next, next, CV_BGR2GRAY);


calcOpticalFlowFarneback(
prvs,
next,
flow,
0.5, //Определяет масштаб изображения.0.5 означает классическую пирамиду
5,   //Количество уровней пирамиды, включая начальное изображение
15,  //Средний размер окна
3,   //Количество итераций алгоритма на каждом уровне пирамиды
7,   //Размер окрестностей пикселей для нахождения расширенного полиномиала(polyN)
1.5, //Стандартное отклонение Гауссиана, которое используется для сглаживания в polyN. Для polyN=5 - polySigma=1.1, для polyN=7 - polySigma=1.5
0
);

cvtColor(prvs, cflow, CV_GRAY2BGR);
drawOptFlowMap(flow, cflow, 8, 2, CV_RGB(0, 255, 0));
imshow("Testing", cflow);
imshow("prvs", prvs);
imshow("next", next);

Mat centers(flow.size(), 4, CV_32FC1);
int count;

count = cv::flann::hierarchicalClustering(flow, ceners, fln_idx);
//Ожидание нажатия ESCAPE
char c = cvWaitKey(10);
if (c == 27) break;

prvs = next.clone();
}
}
 

Вот на данный момент код выглядит так. Функция  cv::flann::hierarchicalClustering выделена красным и написано, что что-то не так с параметрами, кстати вот ошибкa:

Error 1 error C2783: 'int cv::flann::hierarchicalClustering(const cv::Mat &,cv::Mat &,const cvflann::KMeansIndexParams &)' : could not deduce template argument for 'ELEM_TYPE' D:\Visual Studio 2013\Projects\opticalflow\ConsoleApplication2\Source.cpp 130 1 ConsoleApplication2
 и так для каждого аргумента

 

Что надо подкорректировать?

Изменено пользователем nhr

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот один из примеров использования (нашел в сети, сам не тестировал), похоже у Вас действительно не хватает параметров шаблона (судя по всему там задается метрика), ну и другие параметры не очень похожи на используемые ниже.

int count = cv::flann::hierarchicalClustering<cvflann::L1<float>>(groupped_one_person_features,centroids,cvflann::KMeansIndexParams(2000,11,cvflann::FLANN_CENTERS_KMEANSPP));

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В общем мне сказали, что надо использовать кластеризацию к-means. Проблема в том, что при реализации, которая представлена ниже выводится только один кадр. Как сделать, чтобы шел непрерывный видеопоток?

using namespace std;
using namespace cv;

void drawOptFlowMap(const Mat& flow, Mat& cflowmap, int step, double scale, const Scalar& color)
{
for (int y = 0; y < cflowmap.rows; y += step)
for (int x = 0; x < cflowmap.cols; x += step)
{
const Point2f& fxy = flow.at<Point2f>(y, x);
line(cflowmap, Point(x, y), Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), 1);
//circle(cflowmap, Point(x, y), 2, color, -1);
}
}

int main(int argc, char** argv)
{
int s = 2; // масштабирующий коэффициент
Mat  frame, flow, cflow, bestlabels, centers, dst;
Mat  img1, img2, img1_gray, img2_gray;
Mat framepoints;
vector<Vec4i> hierarchy;
vector<vector<Point> > contours;
vector<vector<Point> > p;
Point center;

RNG rng(12345);
int win_size = 21;

string capture = "video1.avi";
VideoCapture cam(capture);

if (!(cam.read(frame)))
return 0;
resize(frame, img1, Size(frame.size().width / s, frame.size().height / s));
cvtColor(img1, img1, CV_BGR2GRAY);

while (1)
{
if (!(cam.read(frame)))
break;

resize(frame, img2, Size(frame.size().width / s, frame.size().height / s));
cvtColor(img2, img2, CV_BGR2GRAY);

calcOpticalFlowFarneback(
img1,
img2,
flow,
0.5, //Определяет масштаб изображения.0.5 означает классическую пирамиду
5,   //Количество уровней пирамиды, включая начальное изображение
15,  //Средний размер окна
3,   //Количество итераций алгоритма на каждом уровне пирамиды
7,   //Размер окрестностей пикселей для нахождения расширенного полиномиала(polyN)
1.5, //Стандартное отклонение Гауссиана, которое используется для сглаживания в polyN. Для polyN=5 - polySigma=1.1, для polyN=7 - polySigma=1.5
0
);

cvtColor(img1, cflow, CV_GRAY2BGR);
drawOptFlowMap(flow, cflow, 8, 2, CV_RGB(0, 255, 0));

Mat bin(cflow.size(), CV_8UC3);

Canny(cflow, bin, 50, 200, 3);
//------------------------------------
char c = waitKey(2);
if (c == 'c') break;
//------------------------------------
imshow("cvCanny", bin);
// ищем контуры
findContours(bin, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

//рисуем контуры
Mat drawing = Mat::zeros(bin.size(), CV_8UC3);

for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}

cvtColor(bin, dst, CV_GRAY2BGR);
imshow("Contours", drawing);
imshow("Testing", cflow);

Mat points(drawing.rows * drawing.cols, 3, CV_32F);
for (int y = 0; y < drawing.rows; y++)
for (int x = 0; x < drawing.cols; x++)
for (int z = 0; z < 3; z++)
points.at<float>(y + x*drawing.rows, z) = drawing.at<Vec3b>(y, x)[z];

int k = 21;
int attempts = 5;
Mat centers;

kmeans(points, k, bestlabels, TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001), attempts, KMEANS_PP_CENTERS, centers);

Mat clustered(drawing.size(), drawing.type());
for (int y = 0; y < drawing.rows; y++)
for (int x = 0; x < drawing.cols; x++)
{
int cluster_idx = bestlabels.at<int>(y + x*drawing.rows, 0);
clustered.at<Vec3b>(y, x)[0] = centers.at<float>(cluster_idx, 0);
clustered.at<Vec3b>(y, x)[1] = centers.at<float>(cluster_idx, 1);
clustered.at<Vec3b>(y, x)[2] = centers.at<float>(cluster_idx, 2);
}

clustered.convertTo(clustered, CV_8U);
imshow("clustered", clustered);

//Ожидание нажатия ESCAPE
char c1 = cvWaitKey(10);
if (c1 == 27) break;
}
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

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

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×