1. OpenCV шаг за шагом. Введение.
2. Установка.
3. Hello World.
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения
13. Типы данных OpenCV
14. Матрица
15. Сохранение данных в XML
16. Генерация случайных чисел
Рассмотрим функции, которые предоставляет OpenCV для генерации псевдо-случайных чисел.
CV_INLINE void cvRandInit( CvRandState* state, double param1, double param2, int seed, int disttype CV_DEFAULT(CV_RAND_UNI))
-инициализация работы с ГСЧ
state — указатель на структуру ГСЧ:
typedef struct CvRandState { CvRNG state; /* RNG state (the current seed and carry)*/ int disttype; /* distribution type */ CvScalar param[2]; /* parameters of RNG */ } CvRandState;
param1 — первый параметр распределения (в случае однородного — это нижняя граница диапазона, в случае нормального — величина случайных чисел)
param2 — второй параметр распределения (в случае однородного — это верхняя граница диапазона, в случае нормального — стандартное отклонение случайных чисел).
seed — начальная установка
disttype — тип распределения:
#define CV_RAND_UNI 0
#define CV_RAND_NORMAL 1
CV_INLINE void cvRandSetRange( CvRandState* state, double param1, double param2, int index CV_DEFAULT(-1))
— изменение диапазона ГСЧ с сохранением состояния ГСЧ
state — указатель на структуру ГСЧ
param1
param2
index
CV_INLINE void cvRand( CvRandState* state, CvArr* arr )
— заполнение массива случайными значениями
state — указатель на структуру ГСЧ
arr — указатель на массив для заполнения
фактически сводится к вызову:
cvRandArr( &state->state, arr, state->disttype, state->param[0], state->param[1] );
CVAPI(void) cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );
— заполнение массива случайными значениями
rng — указатель на состояние ГСЧ
typedef uint64 CvRNG;
arr — указатель на массив для заполнения
dist_type — тип распределения
param1 — первый параметр распределения (в случае однородного — это нижняя граница диапазона, в случае нормального — величина случайных чисел)
param2 — второй параметр распределения (в случае однородного — это верхняя граница диапазона, в случае нормального — стандартное отклонение случайных чисел).
typedef uint64 CvRNG; // инициализация состояния ГСЧ CV_INLINE CvRNG cvRNG( int64 seed CV_DEFAULT(-1)) { CvRNG rng = seed ? (uint64)seed : (uint64)(int64)-1; return rng; } // возвращает случайное 32-bit unsigned int CV_INLINE unsigned cvRandInt( CvRNG* rng ) { uint64 temp = *rng; temp = (uint64)(unsigned)temp*4164903690U + (temp >> 32); *rng = temp; return (unsigned)temp; } // возвращает случайное float между 0 and 1 CV_INLINE double cvRandReal( CvRNG* rng ) { return cvRandInt(rng)*2.3283064365386962890625e-10 /* 2^-32 */; }
В качестве примера рассмотрим засеивание изображение 3% шума.
// // засеиваем изображение шумом // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* dst = 0; int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); assert( image != 0 ); // клонируем картинку dst = cvCloneImage(image); int count = 0; // окно для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); cvNamedWindow("noise",CV_WINDOW_AUTOSIZE); // инициализация состояния ГПСЧ CvRNG rng = cvRNG(0xffffffff); // пробегаемся по всем пикселям изображения for( int y=0; yheight; y++ ) { uchar* ptr = (uchar*) (dst->imageData + y * dst->widthStep); for( int x=0; x width; x++ ) { if(cvRandInt(&rng)%100>=97){ // 3 канала ptr[3*x] = cvRandInt(&rng)%255; // B ptr[3*x+1] = cvRandInt(&rng)%255; // G ptr[3*x+2] = cvRandInt(&rng)%255; // R count++; /** // красные пиксели ptr[3*x]=0; ptr[3*x+1]=0; ptr[3*x+2]=255; /**/ } } } printf("[i] noise: %d (%.2f%c)\n", count, (float)count/(dst->height*dst->width)*100, '%'); // показываем картинку cvShowImage("original",image); cvShowImage("noise",dst); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(&image); cvReleaseImage(&dst); // удаляем окна cvDestroyWindow("original"); cvDestroyWindow("noise"); return 0; }
по типу макроса CV_MAT_ELEM можно написать макрос для получения заданного пикселя изображения:
#define CV_PIXEL(type,img,x,y) (((type*)(img->imageData+(y)*img->widthStep))+(x)*img->nChannels)
тогда вот как будет выглядеть обход всех пикселей 3-канального изображения из примера засеивания шумом:
// пробегаемся по всем пикселям изображения for( int y=0; yheight; y++ ) { for( int x=0; x width; x++ ) { if(cvRandInt(&rng)%100>=97){ // 3 канала CV_PIXEL(unsigned char, dst, x, y)[0] = cvRandInt(&rng)%255; // B CV_PIXEL(unsigned char, dst, x, y)[1] = cvRandInt(&rng)%255; // G CV_PIXEL(unsigned char, dst, x, y)[2] = cvRandInt(&rng)%255; // R count++; } } }
Далее: 17. OpenCV шаг за шагом. Обработка изображения — морфологические преобразования
9 комментариев на «“16. OpenCV шаг за шагом. Генерация случайных чисел”»
а как получить, скажем 10 чисел при param1 = 10, param2 = 3, dist_type = 1 (НЗР) ?!
чет нифига не получается…
наверно так…
а где видно что это три процента шума?
Интересно, а зачем нужны все эти функции, если в стандартной библиотеке уже есть функции для работы со случайными числами.
Для независимости от стандартных библиотек?
В данном случае стандартная библиотека — это фактически часть языка (C или C++), без неё никак.
OpenCV доступна на разных языках. Я, например, пишу на c#, кто-то на python-е, а кто-то может свой собственный язык разработает 🙂 И у него не будет стандартного способа генерации псевдослучайных чисел, или будут свои нехорошие особенности…
А как задать линейчатый шум?
Не встречал — видимо, придётся реализовывать самостоятельно.