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
19. Обработка изображения — заливка части изображения
20. Обработка изображения — альфа-смешивание
21. Обработка изображения — пороговое преобразование
Как помним, изображение — это массив пикселей. Нетрудно придумать задачи, когда будет требоваться выбрать пиксели выше(ниже, между) определённого порогового значения.
И тут нам на выручку приходит функция cvThreshold()
CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type );
— выполняет фиксированное пороговое преобразование для элементов массива.
src — исходный массив(изображение) (одноканальное, 8-битное или 32-битное)
dst — целевой массив, должен иметь тот же тип что и src или 8-битный
threshold — пороговая величина
max_value — максимальное значение (используется совместно с CV_THRESH_BINARY и CV_THRESH_BINARY_INV)
threshold_type — тип порогового преобразования:
#define CV_THRESH_BINARY 0 /* value = value > threshold ? max_value : 0 */ #define CV_THRESH_BINARY_INV 1 /* value = value > threshold ? 0 : max_value */ #define CV_THRESH_TRUNC 2 /* value = value > threshold ? threshold : value */ #define CV_THRESH_TOZERO 3 /* value = value > threshold ? value : 0 */ #define CV_THRESH_TOZERO_INV 4 /* value = value > threshold ? 0 : value */ #define CV_THRESH_MASK 7 #define CV_THRESH_OTSU 8 /* use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values */
обычное пороговое преобразование никак не учитывает, что части объектов могут иметь различную яркость из-за разности в освещённости. Это можно исправить если использовать адаптивное пороговое преобразование, которое рассматривает значение не в одном пикселе, а в окрестности пикселя. Это значение может быть просто средним значением пикселей окрестности(т.е. все пиксели равнозначны)(CV_ADAPTIVE_THRESH_MEAN_C), либо пиксели окрестности умножаются на весовой коэффициент (взвешиваются) в соответствии с функцией, например с гауссовой функцией (CV_ADAPTIVE_THRESH_GAUSSIAN_C).
CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value, int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C), int threshold_type CV_DEFAULT(CV_THRESH_BINARY), int block_size CV_DEFAULT(3), double param1 CV_DEFAULT(5));
— выполняет адаптивное пороговое преобразование для элементов массива.
src — исходное изображение
dst — целевое изображение
max_value — максимальное значение (используется совместно с CV_THRESH_BINARY и CV_THRESH_BINARY_INV)
adaptive_method — используемый адаптационный алгоритм:
#define CV_ADAPTIVE_THRESH_MEAN_C 0 #define CV_ADAPTIVE_THRESH_GAUSSIAN_C 1
threshold_type — тип порогового преобразования:
#define CV_THRESH_BINARY 0 /* value = value > threshold ? max_value : 0 */ #define CV_THRESH_BINARY_INV 1 /* value = value > threshold ? 0 : max_value */
block_size — размер окрестности (в пикселях), которая используется для расчёта порогового значения: 3, 5, 7 и т.д.
param1 — параметр, зависящий от используемого метода. Для методов CV_ADAPTIVE_THRESH_MEAN_C и CV_ADAPTIVE_THRESH_GAUSSIAN_C — это константа, вычитаемая из среднего или взвешенного значения (может быть отрицательной)
// // пример порогового преобразования // cvThreshold() и cvAdaptiveThreshold() // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char* argv[]) { IplImage *src=0, *dst=0, *dst2=0; // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку src = cvLoadImage(filename, 0); printf("[i] image: %s\n", filename); assert( src != 0 ); // покажем изображение cvNamedWindow( "original", 1 ); cvShowImage( "original", src ); dst = cvCreateImage( cvSize(src->width, src->height), IPL_DEPTH_8U, 1); dst2 = cvCreateImage( cvSize(src->width, src->height), IPL_DEPTH_8U, 1); cvThreshold(src, dst, 50, 250, CV_THRESH_BINARY); cvAdaptiveThreshold(src, dst2, 250, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 1); // показываем результаты cvNamedWindow( "cvThreshold", 1 ); cvShowImage( "cvThreshold", dst); cvNamedWindow( "cvAdaptiveThreshold", 1 ); cvShowImage( "cvAdaptiveThreshold", dst2); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(&src); cvReleaseImage(&dst); cvReleaseImage(&dst2); // удаляем окна cvDestroyAllWindows(); return 0; }
Аналогичный результат можно получить, используя функции для выборки тех пикселей изображения, которые лежат в заданном интервале значений ( могут храниться как в массиве — cvInRange(), так и задаваться скалярами cvInRangeS() )
CVAPI(void) cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );
— по-элементная проверка элементов массива: проверяет, что значения элементов массива лежат между значениями элементов двух других массивов.
формула:
dst(idx) = lower(idx) <= src(idx) < upper(idx)
src - исходный массив
lower - массив с нижней границей (включая)
upper - массив с верхней границей (не включая)
dst - массив для хранения результата (тип 8S или 8U)
CVAPI(void) cvInRangeS( const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst );
- проверяет, что элемент массива лежит между двух скаляров
формула:
dst(idx) = lower <= src(idx) < upper
src - исходный массив
lower - скаляр с нижней границей (включая)
upper - скаляр с верхней границей (не включая)
dst - массив для хранения результата (тип 8S или 8U)
Пример использования:
// // пример выборки значений в заданном интервале // cvInRangeS() // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char* argv[]) { IplImage *src=0, *dst=0; // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку src = cvLoadImage(filename, 0); printf("[i] image: %s\n", filename); assert( src != 0 ); // покажем изображение cvNamedWindow( "original", 1 ); cvShowImage( "original", src ); dst = cvCreateImage( cvSize(src->width, src->height), IPL_DEPTH_8U, 1); cvInRangeS(src, cvScalar(50), cvScalar(255), dst); // показываем результаты cvNamedWindow( "cvInRangeS", 1 ); cvShowImage( "cvInRangeS", dst); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(&src); cvReleaseImage(&dst); // удаляем окна cvDestroyAllWindows(); return 0; }
Простой пример практического применения этих функций - выборка определённых областей изображения, которые отличаются от других яркостью (в случае изображения 1-канального изображения (в градациях серого) ) или цветом (в случае цветного изображения).
дополнительно:
Вопросы OpenCV - пороговое преобразование над цветной картинкой
Читать далее: 22. Поиск объекта по цвету - RGB.
0 комментариев на «“21. OpenCV шаг за шагом. Обработка изображения — пороговое преобразование”»
Огромное спасибо тебе за уроки!!! если можно пришли свой Email хочу переговорить с тобой….
[email protected]
А почему на вход должны поступать только изображения в градациях серого?
В cvAdaptiveThreshold не можест стоять что-то, кроме Binary и Binary_inv
opencv.willowgarage.com/documentation/miscellaneous_image_transformations.html
Спасибо! пофиксил