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; 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; xwidth; 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 шаг за шагом. Генерация случайных чисел”»

    • наверно так…

      #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-е, а кто-то может свой собственный язык разработает 🙂 И у него не будет стандартного способа генерации псевдослучайных чисел, или будут свои нехорошие особенности…

    • Не встречал — видимо, придётся реализовывать самостоятельно.

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение