1. OpenCV шаг за шагом. Введение.
2. Установка.
3. Hello World.
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения
13. Типы данных OpenCV
14. Матрица
15. Сохранение данных в XML
16. Генерация случайных чисел
17. Обработка изображения — морфологические преобразования
Основные морфологические преобразования:
Erode — размывание(операция сужения)
Dilate — растягивание(операция расширения)
OpenCV реализует их двумя функциями:
CVAPI(void) cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element CV_DEFAULT(NULL), int iterations CV_DEFAULT(1) );
— размывает(операция сужения) изображение с использованием фильтра(ядра) один или несколько раз,
если element == NULL используется ядро 3х3
(изображение формируется из локальных минимумов — т.е. будут увеличиваться тёмные области)
CVAPI(void) cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element CV_DEFAULT(NULL), int iterations CV_DEFAULT(1) );
— растягивает(операция расширения) изображение с использованием фильтра(ядра) один или несколько раз,
если element == NULL используется ядро 3х3
(изображение формируется из локальных максимумов — т.е. будут увеличиваться светлые области)
// #define CV_DEFAULT(val) = val
src — исходное изображение
dst — получаемое изображение
element — структурирующий элемент (ядро) по-умолчанию NULL — соответствует ядру 3×3 с якорем по-центру.
[ ][ ][ ] [ ][+][ ] [ ][ ][ ]
структура ядра:
typedef struct _IplConvKernel { int nCols; int nRows; int anchorX; int anchorY; int *values; int nShiftR; } IplConvKernel;
iterations — число итераций (сколько раз повторить морфологическое преобразование)
! обе функции позволяют, чтобы в качесте dst выступало исходное изображение src.
В cvErode() ядро накладывается на изображение и на месте якоря (центр ядра) остаётся минимальное значение, лежащее под ядром (в случае cvDilate() — наоборот — максимальное )
Эрозия (размывание/сужение) изображения обычно используется для избавления от случайных вкраплений на изображении. Идея состоит в том, что вкрапления при размывании устранятся, тогда как крупные и соответсвенно более визуально-значимые регионы остаются.
Растягивание (расширение) же, по идее, так же должно устранять шум и способствовать объединению областей изображения, которые были разделены шумом, тенями, etc.
Применение же небольшого растягивания должно сплавить эти области в одну.
Морфологические операции, чаще всего, применяются над двоичными изображениями, которые получаются после порогового преобразования (thresholding).
Создание ядра произвольной формы осуществляется функцией cvCreateStructuringElementEx():
CVAPI(IplConvKernel*) cvCreateStructuringElementEx( int cols, int rows, int anchor_x, int anchor_y, int shape, int* values CV_DEFAULT(NULL) );
— создание структурирующего элемента (ядра) для морфологических операций.
например, cvErode() или cvDilate()
cols — число колонок ядра
rows — число стор ядра
anchor_x — относительное горизонтальное смещение якоря ядра
anchor_y — относительное вертикальное смещение якоря ядра
shape — форма ядра:
#define CV_SHAPE_RECT 0 #define CV_SHAPE_CROSS 1 #define CV_SHAPE_ELLIPSE 2 #define CV_SHAPE_CUSTOM 100
— в последнем случае, форму определяет пользователь через values, которая содержит маску, определяющую какие соседние пиксели должны учитываться
values — указатель на массив, в котором ненулевые элементы определяют значимые пиксели. Если values==NULL все элементы считаются ненулевыми.
(этот параметр учитывается только в случае shape==CV_SHAPE_CUSTOM)
CVAPI(void) cvReleaseStructuringElement( IplConvKernel** element );
— освобождение памяти, выделенной под структурирующий элемент(ядро)
Выбирая различную структуру ядра можно решать различные задачи обработки изображений:
— подавление шумов;
— выделение границ объекта;
— выделение скелета объекта;
// // пример базовых морфологических преобразований // cvErode() и cvDilate() // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* dst = 0; IplImage* erode = 0; IplImage* dilate = 0; int radius = 1; int radius_max=10; // // функция-обработчик ползунка - // радиус ядра void myTrackbarRadius(int pos) { radius = pos; } int iterations = 1; int iterations_max = 10; // // функция-обработчик ползунка - // число итераций void myTrackbarIterations(int pos) { iterations = pos; } int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); // клонируем картинку dst = cvCloneImage(image); erode = cvCloneImage(image); dilate = cvCloneImage(image); printf("[i] image: %s\n", filename); assert( image != 0 ); // окно для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); cvNamedWindow("erode",CV_WINDOW_AUTOSIZE); cvNamedWindow("dilate",CV_WINDOW_AUTOSIZE); cvCreateTrackbar("Radius", "original", &radius, radius_max, myTrackbarRadius); cvCreateTrackbar("Iterations", "original", &iterations, iterations_max, myTrackbarIterations); while(1){ // показываем картинку cvShowImage("original",image); // создаём ядро IplConvKernel* Kern = cvCreateStructuringElementEx(radius*2+1, radius*2+1, radius, radius, CV_SHAPE_ELLIPSE); // выполняем преобразования cvErode(image, erode, Kern, iterations); cvDilate(image, dilate, Kern, iterations); // показываем результат cvShowImage("erode",erode); cvShowImage("dilate",dilate); cvReleaseStructuringElement(&Kern); char c = cvWaitKey(33); if (c == 27) { // если нажата ESC - выходим break; } } // освобождаем ресурсы cvReleaseImage(&image); cvReleaseImage(&dst); cvReleaseImage(&erode); cvReleaseImage(&dilate); // удаляем окно cvDestroyWindow("original"); cvDestroyWindow("erode"); cvDestroyWindow("dilate"); return 0; }
Далее: 18. Обработка изображения — морфологические преобразования 2
0 комментариев на «“17. OpenCV шаг за шагом. Обработка изображения — морфологические преобразования”»
Что-то у меня вообще код не идет. Вылетает «прекращена работа lala.exe» и все тут!
в чем косяк?=\
сразу после запуска или в процессе работы?
да, окно открывается и сразу же вылетает такое сообщение и все.
странно 🙂 а какая версия OpenCV?
2.2. Наверняка с установкой какие-то проблемы=\ у меня Visual Studio 2008 Express Edition стоит, мб в этом косяк?
Express Edition ни при чём, хотя 2.2 по-дефолту идёт для 2010 студии.
фэйл… Мда, видимо скелетам придется еще подождать..=(
fatal error LNK1104: cannot open file ‘C:\Program.obj’
вот что он пишет теперь…
а у Вас программы с предыдущих шагов работали? 🙂
с предыдущих вылетал .exe, а теперь тема с этим C:\Program. Но откуда оно взялось, я только что поняла: когда в линкере-инпуте прописываешь пути к .lib, там стоит C:\Program Files\OpenCV и тд. Так вот когда я нажимаю ОК, закрываю все, запускаю прогу, появляется эта ошибка. Если снова зайти в линкер, то там вместо того, что я прописывала, появляется следующая картина:
C:\Program
Files\OpenCV\и тд. И почему он слово «Files» перекидывает на другую строчку, мне ваще не понятно ><
щас на VS 2010 все проверили: работает. А у меня так и нет!
м, кстати, может Вы посоветуете насчет алгоритмом скелетизации и сред для их реализации что-нить? где лучше, какой именно?)
думаю, нужно просто пересобрать библиотеку под 2008-й и всё заработает 😉 библиотека пересобирается с помощью CMake так же как описано проустановку 2.0
вроде по инструкции я все поставила, и теперь снова вылетает .exe!!! ><
Так, наконец-то все заработало)
Скажите, а как выделять скелет с помощью этого всего?
Маааленькая ошибочка:
// функция-обработчик ползунка —
// число итераций
void myTrackbarIterations(int pos) {
// radius = pos;
iterations = pos;
}
А вопрос мой вот в чём:
Позволяет ли OpenCV реализовать слушателей трэкбара без колбэков?
(Пишу на JavaCV, с колюэком возникли проблемы, тк функции типа cvCreateTrackbar(…) не принимают в качестве параметра указатель на функцию)
Спасибо! пофиксил.
кажется — нет, но ведь никто не мешает использовать вместо OpenCV-х трэкбаров любые другие 😉
И правда… Спасибо! Так быстрее заработало 😉