CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

16. OpenCV шаг за шагом. Генерация случайных чисел

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; y<dst->height; y++ ) {
		uchar* ptr = (uchar*) (dst->imageData + y * dst->widthStep);
		for( int x=0; x<dst->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; y<dst->height; y++ ) {
		for( int x=0; x<dst->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 шаг за шагом. Обработка изображения — морфологические преобразования
  • 0
  • 9 сентября 2010, 10:55
  • noonv

Комментарии (8)

RSS свернуть / развернуть
+
0
а как получить, скажем 10 чисел при param1 = 10, param2 = 3, dist_type = 1 (НЗР) ?!
чет нифига не получается…
avatar

ns5d

  • 22 августа 2012, 20:03
+
0
наверно так…
#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(NULL)), cvRNG(time(NULL)) };
	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;
}
avatar

ns5d

  • 23 августа 2012, 10:36
+
0
примера рассмотрим засеивание изображение 3% шума

а где видно что это три процента шума?
avatar

Zybr

  • 20 февраля 2014, 19:58
+
0
Интересно, а зачем нужны все эти функции, если в стандартной библиотеке уже есть функции для работы со случайными числами.
avatar

laborer

  • 23 марта 2015, 01:30
+
0
Для независимости от стандартных библиотек?
avatar

Evtomax

  • 10 августа 2015, 01:42
+
0
В данном случае стандартная библиотека — это фактически часть языка (C или C++), без неё никак.
avatar

laborer

  • 10 августа 2015, 09:26
+
0
OpenCV доступна на разных языках. Я, например, пишу на c#, кто-то на python-е, а кто-то может свой собственный язык разработает :) И у него не будет стандартного способа генерации псевдослучайных чисел, или будут свои нехорошие особенности…
avatar

JohnJ

  • 10 августа 2015, 09:59

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.