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; xwidth; 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 (НЗР) ?!
чет нифига не получается…
наверно так…
#include <stdio.h> #include <stdlib.h> #include "cv.h" #include "cvaux.h" #include "cxcore.h" #include "highgui.h" int main( int argc, char** argv ) { int n = 10; int m = 1; CvMat* noise = cvCreateMat(n, m, CV_8UC1 ); //CvRNG rng[] = { cvRNG(time(0)), cvRNG(time(0)) }; CvRNG rng[] = {cvRNG(10)}; //>//CvRNG rng[] = {cvRNG(10), cvRNG(10)}; //CvRNG rng = cvRNG(0xffffffff); // seems only cvScalar(first) is effective //>//cvRandArr(rng, noise, CV_RAND_UNI, cvScalar(0,0), cvScalar(15,2) ); cvRandArr(rng, noise, CV_RAND_NORMAL, cvScalar(10), cvScalar(3) ); //cvRandArr(rng, noise, CV_RAND_UNI, cvScalar(5), cvScalar(10) ); //cvPrintMat( noise ); for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { printf(" %.0f", cvGetReal2D(noise, i, j)); } printf("\n"); } return 0; }а где видно что это три процента шума?
Интересно, а зачем нужны все эти функции, если в стандартной библиотеке уже есть функции для работы со случайными числами.
Для независимости от стандартных библиотек?
В данном случае стандартная библиотека — это фактически часть языка (C или C++), без неё никак.
OpenCV доступна на разных языках. Я, например, пишу на c#, кто-то на python-е, а кто-то может свой собственный язык разработает 🙂 И у него не будет стандартного способа генерации псевдослучайных чисел, или будут свои нехорошие особенности…
А как задать линейчатый шум?
Не встречал — видимо, придётся реализовывать самостоятельно.