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

Majority фильтр

Recommended Posts

А есть ли в OpenCV majority фильтр, наподобие такого? Нужно выполнить "сглаживание" растра. Пробовал реализовать комбинируя dilate и erode, но они не совсем подходят.

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


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

Сам и отвечаю.

В OpenCV нет majority фильтра, равно как и многих других вещей :-(. Наиболее близкий вариант medianBlur, но все равно не то.

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


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

Он довольно прост. Если хочешь, могу реализовать его.

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


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

Он довольно прост. Если хочешь, могу реализовать его.

Если не сложно, то буду рад взглянуть на код.

P.S.: тоже пробую реализовать

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


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

Вот, набросал (ничего, что без комментариев?):

bool majority_filter(IplImage* src_img, IplImage* dest_img, int filter_size)

{

	if (!(filter_size % 2) ||

		src_img->width != dest_img->width || src_img->height != dest_img->height ||

		src_img->nChannels > 1 || dest_img->nChannels > 1)

		return false;


	int filter_size_2 = filter_size / 2;

	CvRect r = cvRect(0, 0, filter_size, filter_size);


	int bins = 255;

	int hist_size[] = { bins };

	float range[] = { 0, 255 };

	float* ranges[] = { range };

	CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);


	for (int y = 0; y < src_img->height; ++y)

	{

		r.y = y - filter_size_2;

		if (r.y < 0)

		{

			r.height = filter_size + r.y;

			r.y = 0;

		}

		else if (r.y + filter_size > src_img->height)

		{

			r.height = src_img->height - r.y;

		}

		else

			r.height = filter_size;


		for (int x = 0; x < src_img->width; ++x)

		{

			r.x = x - filter_size_2;

			if (r.x < 0)

			{

				r.width = filter_size + r.x;

				r.x = 0;

			}

			else if (r.x + filter_size > src_img->width)

			{

				r.width = src_img->width - r.x;

			}

			else

				r.width = filter_size;


			cvSetImageROI(src_img, r);


			cvCalcHist(&src_img, hist, 0, 0);


			int max1 = 0, max2 = 0;

			int ind1 = 0, ind2 = 0;

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

			{

				CvScalar v = cvGet1D(hist->bins, i);

				if ((int)v.val[0] >= max1)

				{

					max2 = max1;

					ind2 = ind1;

					max1 = (int)v.val[0];

					ind1 = i;

				}

			}


			cvResetImageROI(src_img);


			if (max1 > max2)

				cvSet2D(dest_img, y, x, cvScalar(ind1));

		}

	}


	cvReleaseHist(&hist);


	return true;

}

////////////////////////////////////////////////////////////////////////////


void print_img(const IplImage* img)

{

	for (int y = 0; y < img->height; ++y)

	{

		for (int x = 0; x < img->width; ++x)

		{

			CvScalar v = cvGet2D(img, y, x);

			printf("% 4.0f ", v.val[0]);

		}

		printf("\n");

	}

	printf("\n");

}

////////////////////////////////////////////////////////////////////////////


int _tmain(int argc, _TCHAR* argv[])

{

	cvNamedWindow("before", 0);

	cvNamedWindow("after", 0);


#if 0

	IplImage* img1 = cvLoadImage("D:\\video_bmp\\black_23.jpg", 0);

#else

	IplImage* img1 = cvCreateImage(cvSize(6, 6), 8, 1);

	char data[] = { 4, 4, 4, 4, -3, 7, 0, 0, \

	                4, 4, 7, 7,  7, 7, 0, 0, \

	                5, 5, 7, 7,  6, 7, 0, 0, \

	                5, 5, 5, 5,  5, 6, 0, 0, \

	                7, 7, 5, 5,  5, 5, 0, 0, \

	                7, 0, 5, 2,  0, 0, 0, 0 };

	memcpy(img1->imageData, data, sizeof(data));

#endif

	cvShowImage("before", img1);


	IplImage* img2 = cvCloneImage(img1);

	majority_filter(img1, img2, 3);

	cvShowImage("after", img2);


	print_img(img1);

	print_img(img2);


	cvWaitKey(0);


	cvReleaseImage(&img1);

	cvReleaseImage(&img2);


	cvDestroyAllWindows();


	return 0;

}

////////////////////////////////////////////////////////////////////////////

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

Я правильно понимаю, что по изображению просто проходят каким-то окном (нечётного размера), находят максимально встречающееся значение и присваивают в текущую позицию? Если да, то ответ по ссылке не совсем правильный: в верхней строке, четвёртый элемент должен быть "7", так как вокруг него находится две "4", три "7" и одна "-3". Так же?

  • Like 1

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


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

есть еще фильтр кувахара(kuwahara filter)- сохраняющий грани сглаживающий фильтр.

пример работы

http://rsbweb.nih.gov/ij/plugins/kuwahara.html

  • Like 1

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


Ссылка на сообщение
Поделиться на других сайтах
Вот, набросал (ничего, что без комментариев?):

Огромное спасибо, буду разбираться. Отсутствие комментариев не помеха.

Я правильно понимаю, что по изображению просто проходят каким-то окном (нечётного размера), находят максимально встречающееся значение и присваивают в текущую позицию? Если да, то ответ по ссылке не совсем правильный: в верхней строке, четвёртый элемент должен быть "7", так как вокруг него находится две "4", три "7" и одна "-3". Так же?

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

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×