1. OpenCV шаг за шагом. Введение.
2. Установка.
3. Hello World.
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения
13. Типы данных OpenCV
14. Матрица
15. Сохранение данных в XML
16. Генерация случайных чисел
17. Обработка изображения — морфологические преобразования
18. Обработка изображения — морфологические преобразования 2
Когда я говорил, что OpenCV реализует морфологические преобразования всего двумя функциями, я, разумеется, лукавил.
Есть ещё одна замечательная функция — cvMorphologyEx(). Она обеспечивает более сложные морфологические преобразования изображения.
CVAPI(void) cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp, IplConvKernel* element, int operation, int iterations CV_DEFAULT(1) );
— выполняет сложное морфологическое преобразование
src — исходное изображение
dst — изображение для сохранения результата
temp — для промежуточного хранения результатов (размер изображения должен совпадать с размером исходного изображения) — требуется при определённом значении operation
operation — определяет тип морфологического преобразования:
#define CV_MOP_OPEN 2 #define CV_MOP_CLOSE 3 #define CV_MOP_GRADIENT 4 #define CV_MOP_TOPHAT 5 #define CV_MOP_BLACKHAT 6
CV_MOP_OPEN и CV_MOP_CLOSE — комбинация сужения и расширения:
CV_MOP_OPEN — сначала сужается, а затем расширяется. Обычно используется для подсчёта регионов на двоичном изображении.
CV_MOP_CLOSE — сначала расширяется, а затем сужается. Обычно используется для уменьшения шумовых выбросов на границах регионов.
! Порядок выполнения операции CV_MOP_CLOSE при числе итераций iterations==2:
Dilate-Dilate-Erode-Erode !
CV_MOP_GRADIENT:
gradient(src) = Dilate(src)–Erode(src)
Результатом этой операции над двоичным изображением станет выделение периметров существующих пятен. На картинке с градациями серого градиент покажет как быстро меняется яркость (поэтому и называется — градиент).
CV_MOP_TOPHAT и CV_MOP_BLACKHAT:
TopHat(src) = src–Open(src)
BlackHat(src) = Close(src)–src
CV_MOP_TOPHAT — изолирует яркие локальные пики
CV_MOP_BLACKHAT — изоляция тёмных регионов
// // пример работы cvMorphologyEx() // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* dst = 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) { radius = pos; } int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); // клонируем картинку dst = cvCloneImage(image); printf("[i] image: %s\n", filename); assert( image != 0 ); // окно для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); cvNamedWindow("morphology",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); // картинка для промежуточного хранения результатов cvCreateImage IplImage* Temp = 0; Temp = cvCreateImage(cvSize(image->width, image->height) , IPL_DEPTH_8U, 1); // выолняем преобразование cvMorphologyEx(image, dst, Temp, Kern, CV_MOP_OPEN, iterations); // показываем результат cvShowImage("morphology",dst); cvReleaseStructuringElement(&Kern); cvReleaseImage(&Temp); char c = cvWaitKey(33); if (c == 27) { // если нажата ESC - выходим break; } } // освобождаем ресурсы cvReleaseImage(&image); cvReleaseImage(&dst); // удаляем окна cvDestroyAllWindows(); return 0; }
а теперь соберём все параметры преобразования cvMorphologyEx() вместе:
// // пример работы cvMorphologyEx() // // покажем все методы сразу // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* open = 0; IplImage* close = 0; IplImage* gradient = 0; IplImage* tophat = 0; IplImage* blackhat = 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) { radius = pos; } int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); // клонируем картинку open = cvCloneImage(image); close = cvCloneImage(image); gradient = cvCloneImage(image); tophat = cvCloneImage(image); blackhat = cvCloneImage(image); printf("[i] image: %s\n", filename); assert( image != 0 ); // окно для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); cvNamedWindow("CV_MOP_OPEN",CV_WINDOW_AUTOSIZE); cvNamedWindow("CV_MOP_CLOSE",CV_WINDOW_AUTOSIZE); cvNamedWindow("CV_MOP_GRADIENT",CV_WINDOW_AUTOSIZE); cvNamedWindow("CV_MOP_TOPHAT",CV_WINDOW_AUTOSIZE); cvNamedWindow("CV_MOP_BLACKHAT",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); // картинка для промежуточного хранения результатов cvCreateImage IplImage* Temp = 0; Temp = cvCreateImage(cvSize(image->width, image->height) , IPL_DEPTH_8U, 1); // выолняем преобразования cvMorphologyEx(image, open, Temp, Kern, CV_MOP_OPEN, iterations); cvMorphologyEx(image, close, Temp, Kern, CV_MOP_CLOSE, iterations); cvMorphologyEx(image, gradient, Temp, Kern, CV_MOP_GRADIENT, iterations); cvMorphologyEx(image, tophat, Temp, Kern, CV_MOP_TOPHAT, iterations); cvMorphologyEx(image, blackhat, Temp, Kern, CV_MOP_BLACKHAT, iterations); // показываем результат cvShowImage("CV_MOP_OPEN",open); cvShowImage("CV_MOP_CLOSE",close); cvShowImage("CV_MOP_GRADIENT",gradient); cvShowImage("CV_MOP_TOPHAT",tophat); cvShowImage("CV_MOP_BLACKHAT",blackhat); cvReleaseStructuringElement(&Kern); cvReleaseImage(&Temp); char c = cvWaitKey(33); if (c == 27) { // если нажата ESC - выходим break; } } // освобождаем ресурсы cvReleaseImage(&image); cvReleaseImage(&open); cvReleaseImage(&close); cvReleaseImage(&gradient); cvReleaseImage(&tophat); cvReleaseImage(&blackhat); // удаляем окна cvDestroyAllWindows(); return 0; }
CVAPI(void) cvDestroyAllWindows(void);
— удаляет все окна
Читать далее: 19. Обработка изображения — заливка части изображения
0 комментариев на «“18. OpenCV шаг за шагом. Обработка изображения — морфологические преобразования 2”»
В первом примере есть хорошая утечка памяти так как не освобождается временное изображение (переменная Temp).
Нужно пере строкой
cvReleaseStructuringElement(&Kern);
добавить следующее:
cvReleaseImage(&Temp);
🙂
Верно 🙂 Спасибо, пофиксил.
Всегда пожалуйста 🙂
А потом будет открыта тайна какое практическое значение можно выудить из этих методов, а то уже интрига есть. Уж больно интересно 🙂
Есть предложение по поводу кода, дабы не делать большую нагрузку на компьютер лучше обновлять картинки по изменению ползунков. Для этого достаточно немного модифицировать код.
1. cvWaitKey поставить с параметром 0.
2. В обработчики ползунков, после присваивания значений добавить следующую строчку:
keybd_event(VK_SPACE,0,KEYEVENTF_EXTENDEDKEY,0); //Нажата клавиша пробел
не могу понять зачем всовывать ее в обработчик ползунков. и вообще странные эти обработчики, которые вызываются однажды и работают как то постоянно, т.е. это не противоречит концепции с++, что выполненная функция должна стереться с лица памяти?)
где можно посмотреть прототип функции keybd_event() она из она библиотеки openCV?
Читая код с листа кажется, что код
void myTrackbarIterations(int pos) { radius = pos;}
должен выглядеть как
void myTrackbarIterations(int pos) { iterations = pos;}
Я что-то упускаю?
🙂 экспериментируйте 🙂