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

OpenCV в медицине

Recommended Posts

Здравствуйте!

Прошу дать совет по фильтрам/алгоритмам (а лучше подходящие функции, если такие имеются), при помощи которых можно выделить объект, приведённый на прикреплённых снимках (на втором изображении объект обведён красным).

Пробую вариировать параметры threshold(), inRange(), GaussianBlur(), но, к сожалению безуспешно.

Так же пробовал использовать HoughCircles(), но опять же безуспешно (либо много кругов, либо вообще нет, либо ошибочно).

Буду очень рад Вашей помощи.

post-1600-0-76823700-1295119105_thumb.pnpost-1600-0-24950900-1295119114_thumb.pn

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


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

Здравствуйте!

Прошу дать совет по фильтрам/алгоритмам (а лучше подходящие функции, если такие имеются), при помощи которых можно выделить объект, приведённый на прикреплённых снимках (на втором изображении объект обведён красным).

Пробую вариировать параметры threshold(), inRange(), GaussianBlur(), но, к сожалению безуспешно.

Так же пробовал использовать HoughCircles(), но опять же безуспешно (либо много кругов, либо вообще нет, либо ошибочно).

Буду очень рад Вашей помощи.

post-1600-0-76823700-1295119105_thumb.pnpost-1600-0-24950900-1295119114_thumb.pn

Боюсь просто не отделаетесь.

Можно попробовать натренировать каскад Хаара на эти объекты.

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

Но более простого ничего в голову не приходит.

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


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

Согласен, что выделение простым не будет.

Вообще говоря, перед началом решения подобной задачи нужно на естественном (русском) языке выделить отличительные признаки объекта, как его можно однозначно классифицировать, отделить от других. Если это удаётся (например круг от прямоугольника или изображение единицы от нуля), то можно пошагово реализовывать словесную классификацию в программе. Если не удаётся (а для многих сложных объектов это так), то создавай выборку изображений, выбирай классификатор и тренируй его.

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


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

Боюсь просто не отделаетесь.

Можно попробовать натренировать каскад Хаара на эти объекты.

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

Но более простого ничего в голову не приходит.

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

Я тоже думал про каскад Хаара, точнее даже запустил его генерацию, но по истечении 36+ часов генерация практически не сдвинулась с места, это при том, что я (только для теста) сделал только 3 позитивных и три негативных изображения (или из-за такого маленького количества могут быть проблемы?), с параметрами всё в порядке вроде -- отталкивался от топиков на этом форуме и от других мануалов. Да и потом проблема то в том, что снимков с такими вот объектами в сети практически нет, а следовательно нет в принципе смысла создавать коллекцию из сгенерированных изображений. Вобщем Хаар, я думаю, отпадает. Я больше думаю в сторону отделения приближённых к окружности объектов и потом через сравнение площади определять искомый ли это объект или нет.

За ссылку спасиБо!

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


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

Согласен, что выделение простым не будет.

Вообще говоря, перед началом решения подобной задачи нужно на естественном (русском) языке выделить отличительные признаки объекта, как его можно однозначно классифицировать, отделить от других. Если это удаётся (например круг от прямоугольника или изображение единицы от нуля), то можно пошагово реализовывать словесную классификацию в программе. Если не удаётся (а для многих сложных объектов это так), то создавай выборку изображений, выбирай классификатор и тренируй его.

Единственное отличие - это округлая форма, и возможно более яркий цвет. Но на данном снимке этот объект - не единственное яркое "пятно". С созданием классификации тоже проблема, как я уже писал выше, так как нет такой базы данных.

В любом случае, спасиБо за советы!

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


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

Если принять гипотезу, что наш объект внутри тёмный, а снаружи светлый, то можно воспользоваться операциями математической морфологии: CV_MOP_TOPHAT - поиск светлых областей и CV_MOP_BLACKHAT - поиск тёмных областей. После построить гистограмму для каждого результата, найти по ней порог, бинаризовать, отсеять мелкие объекты эрозией, результат нарастить, найти на нём контуры. Если в результате получатся вложенные контуры, то искомый объект найден. Как тебе идея?

Сразу предупреждаю, что код довольно корявый - писал его быстро, только ради иллюстрации:

#include "stdafx.h"


#include <cv.h>

#include <highgui.h>


int main(int argc, char* argv[])

{

	IplImage* image = cvLoadImage("d:\\resultFrame4.png", 0);

	IplImage* tophat = cvCloneImage(image);

	IplImage* blackhat = cvCloneImage(image);


	IplImage *result = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);


	cvShowImage("original",image);


	int radius = 2;

	IplConvKernel* Kern = cvCreateStructuringElementEx(radius * 2 + 1, radius * 2 + 1, radius, radius, CV_SHAPE_ELLIPSE);


	IplImage* Temp = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);

	int iterations = 7;

	cvMorphologyEx(image, tophat, Temp, Kern, CV_MOP_TOPHAT, iterations);

	cvMorphologyEx(image, blackhat, Temp, Kern, CV_MOP_BLACKHAT, iterations);



	cvShowImage("CV_MOP_TOPHAT", tophat);

	cvShowImage("CV_MOP_BLACKHAT", blackhat);


	{

		int hist[256] = {0};

		for (unsigned char *ib = (unsigned char *)tophat->imageData, *stopb = (unsigned char *)(tophat->imageData + tophat->imageSize); ib != stopb; ++ib)

		{

			++hist[*ib];

		}

		int threshold = 255;

		int sum = 0;

		for (int i = 255; i != 0; --i)

		{

			sum += hist[i];

			if (sum > tophat->imageSize / 100)

			{

				threshold = i;

				break;

			}

		}

		cvThreshold(tophat, tophat, threshold, 255, CV_THRESH_BINARY);

		cvErode(tophat, tophat, NULL, 1);

		cvDilate(tophat, tophat, NULL, 7);

		cvShowImage("binary_tophat", tophat);

	}


	{

		int hist[256] = {0};

		for (unsigned char *ib = (unsigned char *)blackhat->imageData, *stopb = (unsigned char *)(blackhat->imageData + blackhat->imageSize); ib != stopb; ++ib)

		{

			if (*ib > 100)

				*ib = 0;

			++hist[*ib];

		}

		int threshold = 255;

		int sum = 0;

		for (int i = 255; i != 0; --i)

		{

			sum += hist[i];

			if (sum > blackhat->imageSize / 100)

			{

				threshold = i;

				break;

			}

		}

		cvThreshold(blackhat, blackhat, threshold, 255, CV_THRESH_BINARY);

		cvErode(blackhat, blackhat, NULL, 1);

		cvDilate(blackhat, blackhat, NULL, 7);

		cvShowImage("binary_blackhat", blackhat);

	}


#if 1

	cvSet(result, cvScalar(0));

#else

	cvOr(tophat, blackhat, result);

#endif


	{

		CvMemStorage *storage = cvCreateMemStorage(0);

		CvContourScanner cs = cvStartFindContours(tophat, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


		CvSeq *mContour = 0;

		for (CvSeq *contour = cvFindNextContour(cs); contour; contour = cvFindNextContour(cs))

		{

			if (contour->total >= 6)

			{

				CvBox2D box = cvFitEllipse2(contour);

				CvPoint center = cvPointFrom32f(box.center);

				CvSize size = cvSize(cvRound(box.size.width * 0.5), cvRound(box.size.height * 0.5));

				cvEllipse(result, center, size, -box.angle, 0, 360, CV_RGB(0, 0, 255), 1, CV_AA, 0);

			}

		}


		cvEndFindContours(&cs);

		cvReleaseMemStorage(&storage);

	}


	{

		CvMemStorage *storage = cvCreateMemStorage(0);

		CvContourScanner cs = cvStartFindContours(blackhat, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


		CvSeq *mContour = 0;

		for (CvSeq *contour = cvFindNextContour(cs); contour; contour = cvFindNextContour(cs))

		{

			if (contour->total >= 6)

			{

				CvBox2D box = cvFitEllipse2(contour);

				CvPoint center = cvPointFrom32f(box.center);

				CvSize size = cvSize(cvRound(box.size.width * 0.5), cvRound(box.size.height * 0.5));

				cvEllipse(result, center, size, -box.angle, 0, 360, CV_RGB(0, 0, 255), 1, CV_AA, 0);

			}

		}


		cvEndFindContours(&cs);

		cvReleaseMemStorage(&storage);

	}


	cvShowImage("result", result);


	cvReleaseStructuringElement(&Kern);

	cvReleaseImage(&Temp);


	while(1)

	{

		if (cvWaitKey(33) > 0)

			break;

	}


	cvReleaseImage(&result);

	cvReleaseImage(&image);

	cvReleaseImage(&tophat);

	cvReleaseImage(&blackhat);


	cvDestroyAllWindows();

	return 0;

}

post-391-0-49827300-1295167993_thumb.png

  • Like 1

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


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

Если принять гипотезу, что наш объект внутри тёмный, а снаружи светлый, то можно воспользоваться операциями математической морфологии: CV_MOP_TOPHAT - поиск светлых областей и CV_MOP_BLACKHAT - поиск тёмных областей. После построить гистограмму для каждого результата, найти по ней порог, бинаризовать, отсеять мелкие объекты эрозией, результат нарастить, найти на нём контуры. Если в результате получатся вложенные контуры, то искомый объект найден. Как тебе идея?

Сразу предупреждаю, что код довольно корявый - писал его быстро, только ради иллюстрации:

...

Огромное-огромное спасиБо!!

Видать, я слишком быстро "прощёлкал" tophat и blackhat. Буду пробовать, потом отпишусь.

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


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

Здравствуйте всем!

Имеется видеоролик с записью передвижения живых клеток крови. Передо мной поставлена задача выделить каждую клетку на видео и построить галерею найденных объектов.

Подскажите, пожалуйста, как это можно реализовать? Дело в том, что я здесь на форуме нашел код где используется преобразование Хафа для выделения окружностей, но в результате получаются множественные окружности в произвольных местах и видео сильно тормозит. Как это исправить? Или может есть другой способ решения поставленной задачи?

Вот ролик test.rar

и код CircleDetection.rar.

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


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

при вызове cvHoughCircles задайте минимальный и максимальный радиус окружности, тогда правильно выделится процентов 60, я поставил 5 и 40. Также можно попробовать отделить клетки от фона и потом применять преобразование Хафа, короче надо экспериментировать...

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


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

Сохрани изображение одной клетки, а после используй его как шаблон для функции cvMatchTemplate. Порог выбирай небольшой, в районе 0.1

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


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

Да, ещё можно, как советовал Romiks, отделить клетки от фона. И искать уже по бинарному изображению Это можно сделать, например, так:

cvSmooth(gray, gray, CV_GAUSSIAN, 5, 5);

cvCanny(gray, gray, 50, 150);

cvDilate(gray, gray, NULL, 2);

cvErode(gray, gray, NULL, 2);

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


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

Пока я решил остановиться только на применении TopHat и вычислении площади контуров, этого вполне достаточно. По логике ведь, выпуклые объекты всегда будут светлее при освещении эндоскопической камеры (да и не только её). Ну края тоже бывают светлыми, т.к. они ближе, но я накладываю круглую маску на изображение и края обрезаются (http://nashruddin.com/OpenCV_Circular_ROI).

Огромное спасиБо ещё раз за идею, Вы меня спасли! =)

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


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

Спасибо всем за предложения, попробую похимичить.

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

Возможно ли сделать так чтобы пользователь щелчком мыши указывал на клетку, она сохранялась как образец, и затем искались и выделялись клетки подобные ей?

Может что-то похожее есть в примерах к OpenCV?

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


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

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

Возможно ли сделать так чтобы пользователь щелчком мыши указывал на клетку, она сохранялась как образец, и затем искались и выделялись клетки подобные ей?

Может что-то похожее есть в примерах к OpenCV?

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

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


Ссылка на сообщение
Поделиться на других сайтах
Может что-то похожее есть в примерах к OpenCV?
Есть выделение мышью в стандартном примере camshiftdemo.

Вот программа с иллюстрацией работы cvMatchTemplate:

#include "stdafx.h"

#include <cv.h>  

#include <highgui.h>


#define USE_BINARY_TEMPL

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


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

{

	CvCapture* capture = cvCaptureFromAVI("d:\\test.avi");

	if (!capture)

		return 1;


#ifdef USE_BINARY_TEMPL

	IplImage *tpl = cvLoadImage("d:\\cell.png", 0);

#else

	IplImage *tpl = cvLoadImage("d:\\cell_cl.png", 1);

#endif

	IplImage *gray = NULL;

	IplImage *res = NULL;


	for (IplImage *frame = cvQueryFrame(capture); frame; frame = cvQueryFrame(capture))

	{

		if (!gray)

			gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);


		int w = frame->width - tpl->width + 1;

		int h = frame->height - tpl->height + 1;

		if (!res)

			res = cvCreateImage(cvSize(w, h), IPL_DEPTH_32F, 1);



#ifdef USE_BINARY_TEMPL

		cvCvtColor(frame, gray, CV_BGR2GRAY);

		cvSmooth(gray, gray, CV_GAUSSIAN, 5, 5);

		cvCanny(gray, gray, 50, 150);

		cvDilate(gray, gray, NULL, 2);

		cvErode(gray, gray, NULL, 2);


		cvMatchTemplate(gray, tpl, res, CV_TM_SQDIFF_NORMED);

#else

		cvMatchTemplate(frame, tpl, res, CV_TM_SQDIFF_NORMED);

#endif


		cvShowImage("gray", gray);

		cvSet(gray, cvScalar(0));


#ifdef USE_BINARY_TEMPL

		float threshold = 0.8f;

#else

		float threshold = 0.08f;

#endif

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

		{

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

			{

				CvScalar s = cvGet2D(res, y, x);

				if (s.val[0] < threshold)

					cvSet2D(gray, y, x, cvScalar(255));

			}

		}


		CvMemStorage *storage = cvCreateMemStorage(0);

		CvContourScanner cs = cvStartFindContours(gray, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


		for (CvSeq *contour = cvFindNextContour(cs); contour; contour = cvFindNextContour(cs))

		{

			if (contour->total >= 6)

			{

				CvBox2D box = cvFitEllipse2(contour);

				CvPoint center = cvPointFrom32f(box.center);

				cvCircle(frame, cvPoint(center.x + tpl->width / 2, center.y + tpl->height / 2), tpl->width / 2, CV_RGB(0, 255, 255));

			}

		}


		cvEndFindContours(&cs);

		cvReleaseMemStorage(&storage);



		cvShowImage("color", frame);


		if (cvWaitKey(30) == 27)   

			break;

	}


	cvReleaseImage(&res);

	cvReleaseImage(&tpl);

	cvReleaseImage(&gray);

	cvReleaseCapture(&capture);

	cvDestroyAllWindows();

	return 0;

}

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

Если закомментируешь строку #define USE_BINARY_TEMPL, то сравнение будет идти с цветной клеткой (cell_cl.png), иначе с чёрно-белой бинаризованной (cell.png). Примеры клеток шаблонов:

post-391-0-00771400-1295463429_thumb.png

post-391-0-46393200-1295463439_thumb.png

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


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

Есть задачка:

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

Не подскажешь каким методом лучше реализовать?

1 Думаю использовать обучение каскадов Хаара

2 Или как-нибудь задать шаблоны контуров и делать поиск по контурам.

Есть какие-нибудь идеи?

То есть суть задачи пользователь задает какой-то шаблон и дает название. На изображении по шаблону ищутся объекты. Сложность в том объект может отображаться по-разному.

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


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

Спасибо!

1 SURF мне точно не подойдет.

2 каскадов Хаара - если только самому обучить все органы и ищет он все равно слабо. А так если сделать какой-то конструктор, что бы пользователь сам мог обучать, но обучение долго идет.

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

Есть ли какие-нибудь решения, которые более менее ищут объекты? Что бы можно было ввести либо параметры или шаблоны какие-то, а по ним уже поиск делать.

PS: Много битых ссылок на страницах.

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


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

Ссылки посмотрю. Форум падал как то, до сих пор разгребаю.

По поводу SURF , я бы подумал. На счет Хаара это Вы правильно решили.

Легкого пути здесь не будет. Модель объекта придется делать в любом случае, и чем модель содержит больше информации об объекте, тем лучше будет качество работы алгоритма поиска.

Часто для выделения органов на медицинских изображениях используют Active Appeareance Models (AAM), Active Shape Models (ASM), и змеиные алгоритмы.

Вот ссылки:

http://www.scs.ryerson.ca/tmcinern/mypapers/papers.html

http://www.lumc.nl/con/1010/83058/87377/87386/904011158482222/

Можно подгонять еще и трехмерные модели (параметрические), но для этого надо их создать.

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


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

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

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


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

рентгеновские снимки. К примеру сердце. Вид сердца на картинке может быть разный.

Хотелось сделать, что-то универсальное. Что бы можно было через какой-то конструктор задавать шаблон и по нему был бы поиск.

Я понял уже что так сделать не просто. Скорее всего придется для каждого органа писать свой алгоритм распознавания.

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


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

если они имеют non-rigid форму, то да будет сложно, то что выше обозначено

Часто для выделения органов на медицинских изображениях используют Active Appeareance Models (AAM), Active Shape Models (ASM), и змеиные алгоритмы.

наверно может помочь.

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


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

Вот тут посмотрите, может пригодится:

http://www.compvision.ru/forum/index.php?showtopic=443

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


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

Вот тут посмотрите, может пригодится:

http://www.compvision.ru/forum/index.php?showtopic=443

это не то, так как мне поиск надо делать. То есть будет поиск либо по алгоритму или по шаблону для нужного органа.

Сейчас вот смотрю Active Appeareance Models, Active Shape Models (ASM).

Или думаю использовать SURF, только сравнивать не с одной картинкой, а с несколькими в разных положениях.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×