利用统计方法求π(PI),并可视化显示求解过程(C++&&OpenCV)
来源:互联网 发布:怎么找回淘宝店铺 编辑:程序博客网 时间:2024/06/12 19:58
统计方法求π的方式:如果在正方形区域内随机产生大量的均匀分布的点,那么落入内切圆和正方形中的随机点个数的比值等于它们的面积之比。该比值乘以4,即为PI值。这就是统计方法求π的过程。
可视化求解过程是指:把产生随机点的过程在图像中显示,可视化过程用到了opencv库,利用opencv创建一个图像,并将数据写入到图像数据的内存位置。
具体要求:
1、显示一幅边长为R的正方形(设置为0,全黑色),利用已经给出的画圆函数,显示出此正方形边长为R/2的内切圆(设置为255,白色),圆心位于正方形中心;
2、通过系统函数rand()产生随机数,将每一个产生的点写入图像的数组,利用上次实验的函数写入图像并在上述的正方形显示区域内显示出来,赋值为255(白色)。每个点的亮度随着时间(新的随机点的产生)减弱至0。
现在我们分步处理:(一):显示一幅边长为R的正方形,(设置为0,全黑色):
先创建一个图片(将P设置为500):
int width = 500;int height = 500;IplImage* img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);unsigned char *img_data = (unsigned char *)(img->imageData);int width_step = img->widthStep;//width_step在灰度图像中表示一行数据的个数img_data 是这个图像灰度值存贮的内存首地址。
动态声明一个二维数组,用来存储图像灰度值。
unsigned char **array_of_img; //开辟一个最初始的地址array_of_img = new unsigned char *[width_step];//开辟的行数array_of_img[0] = new unsigned char[width_step * width_step];//开辟的总空间for (int i = 1; i < width_step; ++i)//将每一行的行首地址赋值{array_of_img[i] = array_of_img[i-1] + width_step;}
然后将动态声明的二维数组初始化为0,为下面将图像灰度值赋0做准备;
for (int k = 0; k < width_step; ++k){for (int j = 0; j < width_step; ++j) {array_of_img[k][j] = 0;}}调用WriteImageData()函数,将二维数组中的灰度值写入到图像数据中:
void WriteImageData(unsigned char *src, int rows, int cols, int width_step,unsigned char ** &dst, bool flag){ //src图像数据在内存的首地址 rows 行,cols列,dst二维数组,flag 是否赋值的参数 int count =0;for (int i = 0; i < cols; ++i){for (int j = 0; j < rows; ++j){if(flag) src[count] = dst[i][j];else src[count] = (unsigned char)'a';count++;}}printf("%d\n", count); return;}
(二)利用已经给出的画圆函数,显示出此正方形边长为R/2的内切圆(设置为255,白色),圆心位于正方形中心:
调用opencv库的画圆函数,并显示图像:
cvCircle(img, cvPoint(250,250), 250, cvScalar(255), 1, 8, 0);cvNamedWindow("Image", CV_WINDOW_AUTOSIZE);cvShowImage("Image", img);cvWaitKey(0);(三)通过系统函数rand()产生随机数,将每一个产生的点写入图像的数组,利用上次实验的函数写入图像并在上述的正方形显示区域内显示出来,赋值为255(白色)。每个点的亮度随着时间(新的随机点的产生)减弱至0;
int sumSquare = 10000;int sumCircle = 0;double PI = 0.0;//generate 100 point(x,y)for(int count = 0; count < sumSquare; ++count){//数组中所有非零元素的值减5 使颜色变暗for (int n = 0; n < width_step; ++n) {for(int m = 0; m < width_step; ++m ){if (array_of_img[m][n] > 0) {array_of_img[m][n] -= 5;}}}//产生一个(0,1)之间的 随机点double numA = (double)(rand())/(double)(RAND_MAX);double numB = (double)(rand())/(double)(RAND_MAX);//将[0,1]的点 放大到 [0,500] 之间int Px = (int) (numA * 500);int Py = (int) (numB * 500);//标示 刚生成的点array_of_img[Px][Py] = 255;// 把数组写入图像中WriteImageData(img_data, width_step, width_step,width_step, array_of_img, true);//重新绘制内切圆cvCircle(img, cvPoint(250,250), 250, cvScalar(255), 1, 8, 0);//判断刚生成的点 是否在 园内if(((numA - 0.5)*(numA - 0.5) + (numB - 0.5)*(numB - 0.5)) <= 0.25){sumCircle++;}cvShowImage("Image", img);//显示图像cvWaitKey(50); //延时50毫秒PI =(double)sumCircle / (double)count;PI *= 4;printf("%d %d\n",sumCircle,count);printf("The PI is : %lf\n",PI);}
这个可视化过程其实就是在求π的循环内对图像数据进行赋值的过程,一个write函数就可。
下面是完整的程序源代码:
#include "cv.h"#include "highgui.h"#include <cstdio>//read the img data from the Memory to own arrayvoid ReadImageData(unsigned char *src, int rows, int cols, int width_step, unsigned char ** &dst){int count = 0;for (int i = 0; i < cols; ++i){for (int j = 0; j < rows; ++j){// printf("%c\n", *((unsigned char*)dst + rows * i + j));// *((unsigned char*)dst + rows * i + j) = src[count];dst[i][j] = src[count];count++;}}printf("%d\n", count);return;}//将用户自己数组存储的输入拷贝到图像相应的内存位置//write the img data ( my array) to the memoryvoid WriteImageData(unsigned char *src, int rows, int cols, int width_step,unsigned char ** &dst, bool flag){int count =0;for (int i = 0; i < cols; ++i){for (int j = 0; j < rows; ++j){if(flag) src[count] = dst[i][j];else src[count] = (unsigned char)'a';count++;}}printf("%d\n", count);return;}int main(int args,char * argv[]){//double PI = 0.0;//设定图片的大小int width = 500;int height = 500;//利用opencv创建一个 空的图片图像IplImage* img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);unsigned char *img_data = (unsigned char *)(img->imageData);//获得 一行 大小int width_step = img->widthStep;//动态创建 正方形的 二维数组 边长为widthunsigned char **array_of_img; array_of_img = new unsigned char *[width_step];array_of_img[0] = new unsigned char[width_step * width_step];//为每一行 分配地址for (int i = 1; i < width_step; ++i){array_of_img[i] = array_of_img[i-1] + width_step;}//初始化动态 声明的二维数组 0,即黑色for (int k = 0; k < width_step; ++k){for (int j = 0; j < width_step; ++j) {array_of_img[k][j] = 0;}}//将数组的数据写入到内存相应的位置WriteImageData(img_data, width_step, width_step,width_step, array_of_img, true);//画圆cvCircle(img, cvPoint(250,250), 250, cvScalar(255), 1, 8, 0);cvNamedWindow("Image", CV_WINDOW_AUTOSIZE);//创建窗口 cvShowImage("Image", img);//显示图像cvWaitKey(0); //等待按键,开始采样随机点int sumSquare = 10000;int sumCircle = 0;double PI = 0.0;//generate 100 point(x,y)for(int count = 0; count < sumSquare; ++count){//数组中所有非零元素的值减5 使颜色变暗for (int n = 0; n < width_step; ++n) {for(int m = 0; m < width_step; ++m ){if (array_of_img[m][n] > 0) {array_of_img[m][n] -= 5;}}}//产生一个(0,1)之间的 随机点double numA = (double)(rand())/(double)(RAND_MAX);double numB = (double)(rand())/(double)(RAND_MAX);//将[0,1]的点 放大到 [0,500] 之间int Px = (int) (numA * 500);int Py = (int) (numB * 500);//标示 刚生成的点array_of_img[Px][Py] = 255;// 把数组写入图像中WriteImageData(img_data, width_step, width_step,width_step, array_of_img, true);//重新绘制内切圆cvCircle(img, cvPoint(250,250), 250, cvScalar(255), 1, 8, 0);//判断刚生成的点 是否在 园内if(((numA - 0.5)*(numA - 0.5) + (numB - 0.5)*(numB - 0.5)) <= 0.25){sumCircle++;}cvShowImage("Image", img);//显示图像cvWaitKey(50); //延时50毫秒PI =(double)sumCircle / (double)count;PI *= 4;printf("%d %d\n",sumCircle,count);printf("The PI is : %lf\n",PI);}PI =(double)sumCircle / (double)sumSquare;PI *= 4;printf("The PI is : %lf\n",PI);cvDestroyWindow("Image");//销毁窗口 cvReleaseImage(&img); //释放图像delete [] array_of_img[0];delete [] array_of_img;return 0;}
0 0
- 利用统计方法求π(PI),并可视化显示求解过程(C++&&OpenCV)
- 一般法求PI,以及利用超长数运算求长PI(总结)
- python爬虫(4)——统计并可视化数据
- 经典PI求解C程序
- 读取并可视化DICOM图像(VTK & OpenCV)
- java 多线程并行求数值积分(πPI) 之 join() 方法应用
- 蒙特拉罗方法求解PI值
- C语言求解0~2*PI(0~360度)弧度值
- 利用OpenCV读入,显示并保存图像
- 利用opencv+QT打开并显示图片
- **基础题1、**通过键盘输入声明初始值一个圆柱体的高和底面半径,PI值是3.14,求圆柱体的体积,并显示输出圆柱体的体积;V=π(r^2)h。
- 初学C语言:求圆周率pi的近似值(pi/4=1-1/3+1/5-1/7...)
- C语言求高精度PI
- Erlang-蒙特卡洛方法求Pi
- erlang蒙特卡洛方法求Pi
- 利用SVD的方法求解ICP(详细推导)
- openCV 利用Mat 类读入并显示图像
- 如何利用MFC及Opencv读入摄像头并显示画面
- css BFC粗浅应用
- 一致性 hash 算法( consistent hashing )
- QT项目升级(QT4到QT)
- Java中常用缓存Cache机制的实现
- Linux内核中的内存屏障
- 利用统计方法求π(PI),并可视化显示求解过程(C++&&OpenCV)
- 14再论逃跑按钮的实现
- 10 个理由让你继续干 IT
- 关于java String格式 转Date格式 SimpleDateFormat 报java.text.ParseException 错误
- 第一篇博客
- 当程序员老去 会怎样
- mysql 中的tinyint 数据类型
- poj 3177 & 3352 【无向图双连通分量Tarjan】
- 树莓派开机自动启动程序