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 так же как описано про
вроде по инструкции я все поставила, и теперь снова вылетает .exe!!! ><
Так, наконец-то все заработало)
Скажите, а как выделять скелет с помощью этого всего?
Маааленькая ошибочка:
// функция-обработчик ползунка —
// число итераций
void myTrackbarIterations(int pos) {
// radius = pos;
iterations = pos;
}
А вопрос мой вот в чём:
Позволяет ли OpenCV реализовать слушателей трэкбара без колбэков?
(Пишу на JavaCV, с колюэком возникли проблемы, тк функции типа cvCreateTrackbar(…) не принимают в качестве параметра указатель на функцию)
Спасибо! пофиксил.
кажется — нет, но ведь никто не мешает использовать вместо OpenCV-х трэкбаров любые другие 😉
И правда… Спасибо! Так быстрее заработало 😉