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

Nuzhny

Пользователи
  • Количество публикаций

    1 427
  • Зарегистрирован

  • Посещение

  • Days Won

    176

Все публикации пользователя Nuzhny

  1. Не ошибаешься.
  2. Кстати. В gimp'е есть фильтр "убрать искажение оптики". Там несколько движков, передвигая которые можно убирать дисторсию. В автоматическом режиме такое работать не будет, но можно один раз настроить для конкретной камеры, если она стационарная. Ещё есть убирание дисторсии в проекте с открытыми исходниками IVT. Пример называется UndistortionRectificationDemo. В этом же примере есть "выпрямление" изображения, если оно снималось под наклоном.
  3. DELPHI + OpenCV 2.2

    [offtop] Сижу я тут, в укромном уголке и радуюсь, что от Делфи ушёл. [/offtop]
  4. Можно сделать массив на указатели с картинками IplImage и при старте программы их загрузить. Твой код выделить в функцию, в которую параметром передавать IplImage - элемент массива.
  5. Ух ты! Оказывается, я велосипеды изобретаю. Надо справку внимательней читать...
  6. Я как-то уже приводил пример для однотонного изображения (не RGB!): std::vector<int> hist(img->width, 0); for (int y = 0; y < img->height; ++y) { unsigned char *pbuf = (unsigned char *)(img->imageData + y * img->widthStep); for (int x = 0; x < img->width; ++x) { if (*pbuf) ++hist[x]; ++pbuf; } } В итоге hist[0] содержит число белых пикселей в первом столбце, hist[1] - во втором,... Можно ещу попробовать вызвать cvIntegralImage. Но там и вычислений больше, и после всякие телодвижения применять при вычислении суммы для каждого столбца (пару сложений/вычитаний и пару делений).
  7. 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). Примеры клеток шаблонов:
  8. OpenCV в медицине

    Да, ещё можно, как советовал Romiks, отделить клетки от фона. И искать уже по бинарному изображению Это можно сделать, например, так: cvSmooth(gray, gray, CV_GAUSSIAN, 5, 5); cvCanny(gray, gray, 50, 150); cvDilate(gray, gray, NULL, 2); cvErode(gray, gray, NULL, 2);
  9. OpenCV в медицине

    Сохрани изображение одной клетки, а после используй его как шаблон для функции cvMatchTemplate. Порог выбирай небольшой, в районе 0.1
  10. Первая мысль - построение гистограммы: IplImage *img = cvLoadImage("f:\\74a72cd615f3.jpg", 0); cvErode(img, img, NULL, 1); cvDilate(img, img, NULL, 1); cvShowImage("img", img); std::vector<int> hist(img->width, 0); for (int y = 0; y < img->height; ++y) { unsigned char *pbuf = (unsigned char *)(img->imageData + y * img->widthStep); for (int x = 0; x < img->width; ++x) { if (*pbuf) ++hist[x]; ++pbuf; } } IplImage *img_hist = cvCreateImage(cvGetSize(img), 8, 1); cvSet(img_hist, cvScalar(0)); for (int i = 0; i < hist.size(); ++i) { cvRectangle(img_hist, cvPoint(i, 0), cvPoint(i, hist[i]), cvScalar(255)); } cvShowImage("img_hist", img_hist); for(; { if (cvWaitKey(10) > 0) break; } cvReleaseImage(&img_hist); cvReleaseImage(&img);[/code] Вторая - построение контуров: [code]IplImage *img = cvLoadImage("f:\\74a72cd615f3.jpg", 0); cvErode(img, img, NULL, 1); cvDilate(img, img, NULL, 2); cvShowImage("img", img); IplImage *img_cont = cvCreateImage(cvGetSize(img), 8, 1); cvSet(img_cont, cvScalar(0)); CvMemStorage *storage = cvCreateMemStorage(0); CvContourScanner cs = cvStartFindContours(img, 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(img_cont, center, size, -box.angle, 0, 360, CV_RGB(0, 0, 255), 1, CV_AA, 0); } } cvEndFindContours(&cs); cvReleaseMemStorage(&storage); cvShowImage("img_cont", img_cont); for(; { if (cvWaitKey(10) > 0) break; } cvReleaseImage(&img_cont); cvReleaseImage(&img); А вообще - надо подумать.
  11. OpenCV в медицине

    Если принять гипотезу, что наш объект внутри тёмный, а снаружи светлый, то можно воспользоваться операциями математической морфологии: 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; }
  12. OpenCV в медицине

    Согласен, что выделение простым не будет. Вообще говоря, перед началом решения подобной задачи нужно на естественном (русском) языке выделить отличительные признаки объекта, как его можно однозначно классифицировать, отделить от других. Если это удаётся (например круг от прямоугольника или изображение единицы от нуля), то можно пошагово реализовывать словесную классификацию в программе. Если не удаётся (а для многих сложных объектов это так), то создавай выборку изображений, выбирай классификатор и тренируй его.
  13. О, сразу вспоминаются школьные лабораторные по физике - мы тоже такое делали.
  14. Да, если это не запрещено какими-нибудь внутренними правилами, то выложи здесь на форуме итоговый проект. Когда закончишь конечно. Хороший пример практического применения компьютерного зрения вместе с OpenCV.
  15. Я думаю, что вырезать полоску не проблема. Гистограмма яркости по столбцам: 1. создаёшь массив целых чисел шириной, равной ширине изображения, каждый элемент массива - сумма яркостей в соответствующем столбце; 2. в цикле проходишь по строкам изображения и суммируешь значения. В результате получится некоторая плавная волнистая кривая с небольшими резкими проседаниями в области нахождения символов. Если такие проседания встречаются на небольшом расстоянии друг от друга, то это область с символами. Это всё мождет сработать, но пример привести не могу - времени совсем нет.
  16. Надо экспериментировать: адаптивную бинаризацию, а после контуры. Или построить гистограмму по столбцам и посмотреть будут ли у неё провалы в области символов. Что-нибудь ещё. Ответа я не знаю.
  17. "Можно сделать изображение-маску" - mask = cvCreateImage "закрасить его чёрным цветом" - cvSet(img, cvScalar(0, 0, 0)) "нарисовать белый круг большего диаметра" - cvCircle + cvFloodFill "нарисовать чёрный круг меньшего диаметра" - cvCircle + cvFloodFill "сделать логическое сложение твоего изображения и маски" - cvAnd(img, mask, mask) mask - как раз должен быть искомым изображением. Писал на глаз, но работать должно.
  18. 1. Можно сделать изображение-маску: закрасить его чёрным цветом, нарисовать белый круг большего диаметра, нарисовать чёрный круг меньшего диаметра. И сделать логическое сложение твоего изображения и маски. 2. Можно попиксельно пройти по твоему изображению, проверяя попадание пикселей в кольцо.
  19. 2quosego: о, этот робот смотрится не так стильно, как rovio, но создан как раз для моих целей - научиться обращаться с роботами. Спасибо!
  20. Спасибо, интересная штука. Забавно, что на ebay есть и по 50$, а в наших интернет магазинах находил аж за 600$. Не люблю покупать технику через интернет, надо подумать.
  21. Давно хотел спросить про роботов. Допустим, мне нужна радиоуправляемая машинка с одной или несколькими камерами на ней. И, разумеется, возможностью программного управления и получения видео с камер. Собирать из деталей я её не очень хочу - лучше готовая. Можно такое достать где-нибудь?
  22. Работа с камерами

    Какой протокол выбирал? RTSP, RTP? Имя пользователя и пароль ввёл правильно?
  23. Немного оффтопика: чем мне не нравится SetImageROI, так это своей жуткой тормознутостью. На каждый ROI выделяется память, после копируется и удаляется. Бррр! Будто нельзя было сделать без копирования. Поэтому ради быстродействия мне приходится переписывать под себя кучу всего готового, что есть в OpenCV - лишь бы не использовать SetImageROI.
  24. Если искомые образы меняются слабо, то можно с помощью преобразования Фурье перейти в частотную область и там считать корреляцию. В Матлабе есть готовый пример - если подойдёт, то в OpenCV его реализовать тоже можно.
×