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

расспараллеливание матчинга снимков

Recommended Posts

есть код для получения 1 пары.

MatchesInfo get_pair(Mat& im1, Mat& im2)

{

	MatchesInfo info;

	double surf_param=100; // чем меньше значение тем больше точек

	SurfFeaturesFinder finder(surf_param);

    ImageFeatures features1;

	ImageFeatures features2;


	finder(im1,features1);

	finder(im2,features2);


	finder.collectGarbage();


	match_flann(features1,features2,info);


	Mat affine;

	string method="translation";

	//string method="translation+rotation";

	//string method="affine";

	int thres=3;


	std::vector<DMatch> inliners;

	double score= ransac(features1.keypoints,

						features2.keypoints,

						info.matches,

						affine,inliners,thres,method);


	info.num_inliers= inliners.size();

	Mat M= affine.reshape(1,2);

	info.H= M;

	info.confidence= (double)inliners.size()/(8+0.3*info.matches.size());// по пейперу Lowe


	return info;

}
есть код для всех, который хочеться распараллелить. например с помощью boost. как это правильно сделать? составить список пар заранее? (непонятно надо ли копировать отдельно изображения или несколько тредов могут читать из одной памяти?)
vector<MatchesInfo> GetSURFCorrespondences(vector<Mat>& vec_im)

{

	vector<MatchesInfo> vec;


	int k=0;

	for(int i=0;i<vec_im.size();++i)

	{

		++k;

		for(int j=k;j<vec_im.size();++j)

		{

			MatchesInfo info= get_pair(vec_im[i], vec_im[j]);

			info.src_img_idx= i;

			info.dst_img_idx= j;

			vec.push_back(info);

		} 

	}


	return vec;

}

основную часть времени съедает именно матчинг, немного меньше детектирование фич+экстракция дескрипторов.

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


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

Можно распараллелить при помощи openmp-ишной директивы

#pragma omp parallel for
выглядит обычно так:

#ifdef _OPENMP
#pragma omp parallel for
for (int i = 0; i < ferns.size(); i++)
{
}
#else
нераспараллеленая реализация
#endif
[/code]

Чтобы это работало надо включить заголовок

#include <omp.h>

и разрешить использование openmp в опциях проекта (options -> C++ -> Language -> поставить галку OpenMP support).

Что касается кода, то явно будут проблемы с

vec.push_back(info);

Тут лучше выделить каждому потоку свой кусок памяти.

Хорошее руководство тут: http://msdn.microsoft.com/ru-ru/library/dd335940.aspx

  • Like 1

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


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

	#pragma omp parallel

	{

		printf("Hello World\n");

	}
так выводит 2 раза
	cvSetNumThreads(2);

	int nthreads = cvGetNumThreads();

но nthreads почему то =1

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

http://stackoverflow.com/questions/9269097/openmp-and-stl-vector

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


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

попробовал распараллелить внутренний цикл

	int n=8;

	int c=0;

	for(int i=n-1;i>=0;--i)

		c+=i;

	int k=0;

	vector<pair<int,int>> vec(c);

	c=0;

	for(int i=0;i<n;++i)

	{

		++k;

		cout<<"k= "<<k<<endl;

		#pragma omp parallel for

		for(int j=k;j<n;++j)

		{

                        //вычисление чего нибудь и присваивание

			vec[c]= make_pair(i,j); // так неправильно


			#pragma omp critical

			{

				//vec[c]= make_pair(i,j); //так правильно


				cout<<"i= "<<i<<" j= "<<j<<endl;

				cout<<"c= "<<c<<endl;

				++c;

			}

		} 

	}

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


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

vector<MatchesInfo> GetSURFCorrespondences(vector<Mat>& vec_im)

{

	vector<MatchesInfo> vec;


	#ifndef _OPENMP

	int k=0;

	for(int i=0;i<vec_im.size();++i)

	{

		++k;

		for(int j=k;j<vec_im.size();++j)

		{

			MatchesInfo info= get_pair(vec_im[i], vec_im[j]);

			info.src_img_idx= i;

			info.dst_img_idx= j;

			vec.push_back(info);

		} 

	}

	#else

	int c=0;

	int n= vec_im.size();

	for(int i=n-1;i>=0;--i)

		c+=i;

	int k=0;

	vec.resize(c);

	c=0;

	for(int i=0;i<n;++i)

	{

		++k;

		//cout<<"k= "<<k<<endl;

		#pragma omp parallel for

		for(int j=k;j<n;++j)

		{

			MatchesInfo info= get_pair(vec_im[i], vec_im[j]);

			info.src_img_idx= i;

			info.dst_img_idx= j;

			vec[c]= info;


			#pragma omp critical

			{

				/*cout<<"i= "<<i<<" j= "<<j<<endl;

				cout<<"c= "<<c<<endl;*/

				++c; // должно быть в крит секции

			}

		} 

	}

	#endif


	return vec;

}

судя по времени выполнения код вообще не ускоряется

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


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

так тоже работает

	int k=0;

	for(int i=0;i<vec_im.size();++i)

	{

		++k;

		#pragma omp parallel for

		for(int j=k;j<vec_im.size();++j)

		{

			MatchesInfo info= get_pair(vec_im[i], vec_im[j]);

			info.src_img_idx= i;

			info.dst_img_idx= j;


			#pragma omp critical

			{

				cout<<"i= "<<i<<" j= "<<j<<endl;

				vec.push_back(info);

			}

		} 

	}

проблема была в том, что тестировал в релизе и забыл там включить openmp, а так ускорение где в 1.7 раз получилось(на 2 процессорном).

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


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

class CTask

{

public:

	int id1;

	int id2;

	Mat m1;

	Mat m2;

};

	vector<CTask> vec_task;

	int k=0;

	for(int i=0;i<vec_im.size();++i)

	{

		++k;

		for(int j=k;j<vec_im.size();++j)

		{

			CTask t;

			t.id1= i;

			t.id2= j;

			t.m1= vec_im[i];

			t.m2= vec_im[j];


			vec_task.push_back(t);

		} 

	}


	#pragma omp parallel for

	for(int i=0;i<vec_task.size();++i)

	{

		MatchesInfo info= get_pair(vec_task[i].m1, vec_task[i].m2);

		info.src_img_idx= vec_task[i].id1;

		info.dst_img_idx= vec_task[i].id2;

		#pragma omp critical

		{

			vec.push_back(info);

		}

	}

попробовал всё в 1 цикл, ускорения не получил, хотя думал будет, т.к. в предыдущей реализации были нечётные циклы.

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


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

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

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


Ссылка на сообщение
Поделиться на других сайтах
Так критическая секция, а данном случае, из параллельного кода последовательный делает.

да вообще то нет, код в крит. секции выполняется быстро относительно основных вычислений, так что норм., я имею ввиду что я не получил дополнительного относительно 1.7.

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


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

1.7 это близко к пределу для 2-х ядер.

Большее ускорение вряд ли получится выжать.

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


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

Не о распараллеливании конечно, но думаю что здесь будет уместно упомянуть:

http://code.opencv.org/issues/1498

When using CvInvert with SVD method, OpenCV 2.3 is 3x slower than OpenCV 2.2

Исправлять, по плану, собираются только к 3-ей версии (примерно через 3 месяца).

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


Ссылка на сообщение
Поделиться на других сайтах
1.7 это близко к пределу для 2-х ядер.

Большее ускорение вряд ли получится выжать.

вопрос не в том, 1.3,1.5 или 1.7, а в том, что в предыдущей версии были циклы нечетной длины и я предполагал, что 1 остаточная итерация в таком цикле делается на 1 процессоре, что видимо неверно.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×