KNCH 0 Report post Posted January 15, 2011 Здравствуйте! Прошу дать совет по фильтрам/алгоритмам (а лучше подходящие функции, если такие имеются), при помощи которых можно выделить объект, приведённый на прикреплённых снимках (на втором изображении объект обведён красным). Пробую вариировать параметры threshold(), inRange(), GaussianBlur(), но, к сожалению безуспешно. Так же пробовал использовать HoughCircles(), но опять же безуспешно (либо много кругов, либо вообще нет, либо ошибочно). Буду очень рад Вашей помощи. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted January 15, 2011 Здравствуйте! Прошу дать совет по фильтрам/алгоритмам (а лучше подходящие функции, если такие имеются), при помощи которых можно выделить объект, приведённый на прикреплённых снимках (на втором изображении объект обведён красным). Пробую вариировать параметры threshold(), inRange(), GaussianBlur(), но, к сожалению безуспешно. Так же пробовал использовать HoughCircles(), но опять же безуспешно (либо много кругов, либо вообще нет, либо ошибочно). Буду очень рад Вашей помощи. Боюсь просто не отделаетесь. Можно попробовать натренировать каскад Хаара на эти объекты. Или активные модели применить, и то и другое потребует изрядных усилий. Но более простого ничего в голову не приходит. Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 15, 2011 Согласен, что выделение простым не будет. Вообще говоря, перед началом решения подобной задачи нужно на естественном (русском) языке выделить отличительные признаки объекта, как его можно однозначно классифицировать, отделить от других. Если это удаётся (например круг от прямоугольника или изображение единицы от нуля), то можно пошагово реализовывать словесную классификацию в программе. Если не удаётся (а для многих сложных объектов это так), то создавай выборку изображений, выбирай классификатор и тренируй его. Share this post Link to post Share on other sites
KNCH 0 Report post Posted January 15, 2011 Боюсь просто не отделаетесь. Можно попробовать натренировать каскад Хаара на эти объекты. Или активные модели применить, и то и другое потребует изрядных усилий. Но более простого ничего в голову не приходит. СпасиБо за быстрый ответ. Я тоже думал про каскад Хаара, точнее даже запустил его генерацию, но по истечении 36+ часов генерация практически не сдвинулась с места, это при том, что я (только для теста) сделал только 3 позитивных и три негативных изображения (или из-за такого маленького количества могут быть проблемы?), с параметрами всё в порядке вроде -- отталкивался от топиков на этом форуме и от других мануалов. Да и потом проблема то в том, что снимков с такими вот объектами в сети практически нет, а следовательно нет в принципе смысла создавать коллекцию из сгенерированных изображений. Вобщем Хаар, я думаю, отпадает. Я больше думаю в сторону отделения приближённых к окружности объектов и потом через сравнение площади определять искомый ли это объект или нет. За ссылку спасиБо! Share this post Link to post Share on other sites
KNCH 0 Report post Posted January 15, 2011 Согласен, что выделение простым не будет. Вообще говоря, перед началом решения подобной задачи нужно на естественном (русском) языке выделить отличительные признаки объекта, как его можно однозначно классифицировать, отделить от других. Если это удаётся (например круг от прямоугольника или изображение единицы от нуля), то можно пошагово реализовывать словесную классификацию в программе. Если не удаётся (а для многих сложных объектов это так), то создавай выборку изображений, выбирай классификатор и тренируй его. Единственное отличие - это округлая форма, и возможно более яркий цвет. Но на данном снимке этот объект - не единственное яркое "пятно". С созданием классификации тоже проблема, как я уже писал выше, так как нет такой базы данных. В любом случае, спасиБо за советы! Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 16, 2011 Если принять гипотезу, что наш объект внутри тёмный, а снаружи светлый, то можно воспользоваться операциями математической морфологии: 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; } 1 Share this post Link to post Share on other sites
KNCH 0 Report post Posted January 17, 2011 Если принять гипотезу, что наш объект внутри тёмный, а снаружи светлый, то можно воспользоваться операциями математической морфологии: CV_MOP_TOPHAT - поиск светлых областей и CV_MOP_BLACKHAT - поиск тёмных областей. После построить гистограмму для каждого результата, найти по ней порог, бинаризовать, отсеять мелкие объекты эрозией, результат нарастить, найти на нём контуры. Если в результате получатся вложенные контуры, то искомый объект найден. Как тебе идея? Сразу предупреждаю, что код довольно корявый - писал его быстро, только ради иллюстрации: ... Огромное-огромное спасиБо!! Видать, я слишком быстро "прощёлкал" tophat и blackhat. Буду пробовать, потом отпишусь. Share this post Link to post Share on other sites
kudukSweetone 3 Report post Posted January 18, 2011 Здравствуйте всем! Имеется видеоролик с записью передвижения живых клеток крови. Передо мной поставлена задача выделить каждую клетку на видео и построить галерею найденных объектов. Подскажите, пожалуйста, как это можно реализовать? Дело в том, что я здесь на форуме нашел код где используется преобразование Хафа для выделения окружностей, но в результате получаются множественные окружности в произвольных местах и видео сильно тормозит. Как это исправить? Или может есть другой способ решения поставленной задачи? Вот ролик test.rar и код CircleDetection.rar. Share this post Link to post Share on other sites
Romiks 6 Report post Posted January 18, 2011 при вызове cvHoughCircles задайте минимальный и максимальный радиус окружности, тогда правильно выделится процентов 60, я поставил 5 и 40. Также можно попробовать отделить клетки от фона и потом применять преобразование Хафа, короче надо экспериментировать... Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 18, 2011 Сохрани изображение одной клетки, а после используй его как шаблон для функции cvMatchTemplate. Порог выбирай небольшой, в районе 0.1 Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 18, 2011 Да, ещё можно, как советовал Romiks, отделить клетки от фона. И искать уже по бинарному изображению Это можно сделать, например, так:cvSmooth(gray, gray, CV_GAUSSIAN, 5, 5); cvCanny(gray, gray, 50, 150); cvDilate(gray, gray, NULL, 2); cvErode(gray, gray, NULL, 2); Share this post Link to post Share on other sites
KNCH 0 Report post Posted January 19, 2011 Пока я решил остановиться только на применении TopHat и вычислении площади контуров, этого вполне достаточно. По логике ведь, выпуклые объекты всегда будут светлее при освещении эндоскопической камеры (да и не только её). Ну края тоже бывают светлыми, т.к. они ближе, но я накладываю круглую маску на изображение и края обрезаются (http://nashruddin.com/OpenCV_Circular_ROI). Огромное спасиБо ещё раз за идею, Вы меня спасли! =) Share this post Link to post Share on other sites
kudukSweetone 3 Report post Posted January 19, 2011 Спасибо всем за предложения, попробую похимичить. В ходе раздумий появилась следующая идея усовершенствования программы: дело в том, что на изображении есть как правило несколько видов клеток крови. Возможно ли сделать так чтобы пользователь щелчком мыши указывал на клетку, она сохранялась как образец, и затем искались и выделялись клетки подобные ей? Может что-то похожее есть в примерах к OpenCV? Share this post Link to post Share on other sites
Romiks 6 Report post Posted January 19, 2011 В ходе раздумий появилась следующая идея усовершенствования программы: дело в том, что на изображении есть как правило несколько видов клеток крови. Возможно ли сделать так чтобы пользователь щелчком мыши указывал на клетку, она сохранялась как образец, и затем искались и выделялись клетки подобные ей? Может что-то похожее есть в примерах к OpenCV? а разве клетки на видео чем-то друг от друга отличаются?, если да это это сложновато будет сделать, а если нет то попробовать можно Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 19, 2011 Может что-то похожее есть в примерах к 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). Примеры клеток шаблонов: Share this post Link to post Share on other sites
Gizatulin 9 Report post Posted January 10, 2012 Есть задачка: Есть изображения с органами человека. На картинке нужно распознавать органы. То есть если там сердце, программа должна выделить и подписать "сердце". Не подскажешь каким методом лучше реализовать? 1 Думаю использовать обучение каскадов Хаара 2 Или как-нибудь задать шаблоны контуров и делать поиск по контурам. Есть какие-нибудь идеи? То есть суть задачи пользователь задает какой-то шаблон и дает название. На изображении по шаблону ищутся объекты. Сложность в том объект может отображаться по-разному. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted January 10, 2012 Темы для "почитать и подумать": http://www.compvision.ru/forum/index.php?showtopic=411&st=0&p=2266&hl=%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5&fromsearch=1&#entry2266 http://www.compvision.ru/forum/index.php?showtopic=502&st=0&p=3019&hl=%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5&fromsearch=1&#entry3019 http://www.compvision.ru/forum/index.php?showtopic=15&st=80&p=4581&hl=%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5&fromsearch=1&#entry4581 Share this post Link to post Share on other sites
bbbbbaran 0 Report post Posted January 11, 2012 Спасибо! 1 SURF мне точно не подойдет. 2 каскадов Хаара - если только самому обучить все органы и ищет он все равно слабо. А так если сделать какой-то конструктор, что бы пользователь сам мог обучать, но обучение долго идет. Как я понял решения, что бы задать какой-то шаблон для объекта и потом искать по шаблону объект нету. В каждом случаи идет подбор определенных параметров под искомый объект. Но под каждый орган такое делать... Есть ли какие-нибудь решения, которые более менее ищут объекты? Что бы можно было ввести либо параметры или шаблоны какие-то, а по ним уже поиск делать. PS: Много битых ссылок на страницах. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted January 11, 2012 Ссылки посмотрю. Форум падал как то, до сих пор разгребаю. По поводу 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/ Можно подгонять еще и трехмерные модели (параметрические), но для этого надо их создать. Share this post Link to post Share on other sites
mrgloom 242 Report post Posted January 12, 2012 непонятно как у вас выглядят эти органы, как они могут варьироваться и т.д. Share this post Link to post Share on other sites
Gizatulin 9 Report post Posted January 12, 2012 рентгеновские снимки. К примеру сердце. Вид сердца на картинке может быть разный. Хотелось сделать, что-то универсальное. Что бы можно было через какой-то конструктор задавать шаблон и по нему был бы поиск. Я понял уже что так сделать не просто. Скорее всего придется для каждого органа писать свой алгоритм распознавания. Share this post Link to post Share on other sites
mrgloom 242 Report post Posted January 12, 2012 если они имеют non-rigid форму, то да будет сложно, то что выше обозначено Часто для выделения органов на медицинских изображениях используют Active Appeareance Models (AAM), Active Shape Models (ASM), и змеиные алгоритмы. наверно может помочь. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted January 12, 2012 Вот тут посмотрите, может пригодится: http://www.compvision.ru/forum/index.php?showtopic=443 Share this post Link to post Share on other sites
Gizatulin 9 Report post Posted January 12, 2012 вот примеры фалов Share this post Link to post Share on other sites
Gizatulin 9 Report post Posted January 12, 2012 Вот тут посмотрите, может пригодится: http://www.compvision.ru/forum/index.php?showtopic=443 это не то, так как мне поиск надо делать. То есть будет поиск либо по алгоритму или по шаблону для нужного органа. Сейчас вот смотрю Active Appeareance Models, Active Shape Models (ASM). Или думаю использовать SURF, только сравнивать не с одной картинкой, а с несколькими в разных положениях. Share this post Link to post Share on other sites