CyMKuH 0 Жалоба Опубликовано January 30, 2011 Здравствуйте! Недавно познакомился с библиотекой. Прошу помощи. Есть широко известная функция cvFloodFill, выполняющая заливку смежных схожих пикселов с определенным порогом. Нужна функция, выполняющая только поиск таковых. Скажем, отмечающая область заливки маской, преобразующая ROI или сразу создающая дубликат области. В конечном счете хочется получить бинарную копию прямоугольника, ограничивающего искомую область, где "закрашиваемая часть" будет выделена одним цветом, а все остальное - другим. Есть ли такая функция в библиотеке, или ее придется написать? Я пока не очень осознал логику пакета и не хочу изобретать велосипеды. В документации и гайде от O'Reily не нашел. И совсем ламерский вопрос. Для написания этой функции нужны тривиальные GetPixel(x,y) и SetPixel(x,y,v), их тоже нет. Нормально ли, что для доступа к данным автор предлагает пользовать эту конструкцию, или я что-то не уловил? о_О float* ptr = (const float*)(mat->data.ptr + row * mat->step + cols); Спасибо за внимание! Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
quosego 5 Жалоба Опубликовано January 30, 2011 Нужная Вам функция и есть FloodFill: void cvFloodFill( CvArr* image, CvPoint seed point, CvScalar new_val, CvScalar lo diff=cvScalarAll(0), CvScalar up diff=cvScalarAll(0), CvConnectedComp* comp=NULL, int flags=4, CvArr* mask=NULL ); Если flag содержит CV_FLOODFILL_MASK_ONLY, то значение new_val игнорируется и заливается не само входное изображение image, а mask (естественно она не должна быть NULL). Только обратите внимание на то, что mask имеет ширину и высоту на 2 пиксела больше чем image и пикселу (x,y) на image соответствует пиксел (x-1,y-1) на mask. Ответ на свой второй вопрос, Вы можите найди здесь http://www.compvision.ru/wiki/Доступ_к_элементам_и_подматрицам 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
CyMKuH 0 Жалоба Опубликовано February 13, 2011 Спасибо за ответ! Помогло. Ниже примерный код, если кому пригодится. Библиотека действительно удобна и довольно продумана. Вот только столкнулся с одной неожиданностью - после cvFloodFill граничная рамка матрицы с маской закрашивается цветом 1. Чтобы найти края выделяемого объекта, приходится сначала закрашивать ее обратно черным 0. // Возвращает указатель на матрицу, содержащую бинарное изображение только выделенной фигуры CvMat* floodMask(int x, int y, CvMat* image) { // Создаем матрицу маски. Ее размер на 2 больше, чем у исходного изображения. Закрашиваем 0. CvMat* mask = cvCreateMat(image->height + 2, image->width + 2, CV_8UC1); cvSet(mask, cvScalar(0)); // Флаги заливки - манипулируйте по необходимоcти int flags = 8 | CV_FLOODFILL_MASK_ONLY | CV_FLOODFILL_FIXED_RANGE | (255 << 8); // Выделяем фигуру в матрице с маской cvFloodFill(image, cvPoint(x,y), cvScalarAll(1), cvScalarAll(1), cvScalarAll(1), NULL, flags, mask); cvRectangle(mask, cvPoint(0,0), cvPoint(mask->width - 1, mask->height -1), cvScalar(0)); // Вычисляем построчно/постолбно сумму всех пикселов в строке. Если не равна 0 - значит, в строке/столбце есть выделенная фигура CvMat* yys = cvCreateMat(mask->height, 1, CV_32SC1); CvMat* xxs = cvCreateMat(1, mask->width, CV_32SC1); cvReduce(mask, yys, 1, CV_REDUCE_SUM); cvReduce(mask, xxs, 0, CV_REDUCE_SUM); // Теперь ищем габариты выделенной фигуры int* ptr = yys->data.i; int y1 = 0; for (; (*ptr) == 0; ptr++) y1++; int height = 0; for (; (*ptr) != 0; ptr++) height++; ptr = xxs->data.i; int x1 = 0; for (; (*ptr) == 0; ptr++) x1++; int width = 0; for (; (*ptr) != 0; ptr++) width++; // Сохраняем и возвращаем фигуру CvMat* out = cvCreateMat(width, height, CV_8UC1); cvGetSubRect(mask, out, cvRect(x1, y1, width, height)); return out; } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах