1. 程式人生 > >利用統計方法求π(PI),並可視化顯示求解過程(C++&&OpenCV)

利用統計方法求π(PI),並可視化顯示求解過程(C++&&OpenCV)

  統計方法求π的方式:如果在正方形區域內隨機產生大量的均勻分佈的點,那麼落入內切圓和正方形中的隨機點個數的比值等於它們的面積之比。該比值乘以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 array
void 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 memory
void 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;
	
	//動態建立 正方形的 二維陣列  邊長為width
	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,即黑色
	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;
}


相關推薦

利用統計方法πPI顯示求解過程C++&&OpenCV

  統計方法求π的方式:如果在正方形區域內隨機產生大量的均勻分佈的點,那麼落入內切圓和正方形中的隨機點個數的比值等於它們的面積之比。該比值乘以4,即為PI值。這就是統計方法求π的過程。   視覺化求解過程是指:把產生隨機點的過程在影象中顯示,視覺化過程用到了opencv庫,

Java日歷Date類、DATe Format類、Calendar類綜合運用開發日歷小程序

nextline inf 表示 輸入日期 static lin print void 日期 Java時間日期類綜合運用,開發可視化日歷小程序 由鍵盤輸入指定格式的日期,打印這個月的日歷 1、代碼 import java.text.DateFormat; import jav

Python+ITchart實現微信中男女比例城市分佈統計顯示

直接上程式碼:   import itchat import os import csv import pandas as pd from pyecharts import Bar,Pie,Geo import shutil as sh # 根據index列印朋友的資訊 def print_I

pytorch實現self-attention機制

pytorch 實現 self attention 並可視化 python 3 pytorch 0.4.0 請閱讀原文。 模型 class SelfAttention(nn.Module): def __init__(self, hidden

Pandas 批量提取Excel檔案分析顯示

Topic 本文主要是使用Pandas批量處理Excel檔案,使用read_excel函式獲取指定列的資料,然後使用concat功能把所有檔案合併,合併完成的資料使用groupby函式按兩個Key分組求取平均值,最後視覺化畫圖; 1. 匯入使用到的模組 Num

Keras實現LeNet-5網路網路結構圖

        模型源自Yann LeCun(1998)的論文《Gradient-Based Learning Applied to Document Recognition》,用於MNIST資料集。模型輸入為32X32的灰度影象,第一層為6個5X5卷積核,不擴充套件邊界;

JavaScript數據編程學習Flotr2包含簡單的柱狀圖折線圖餅圖散點圖

基礎 沒有 cat 勝利 而是 5.4 最好的 表數據 聯系 一、基礎柱狀圖 二、基礎的折線圖 三、基礎的餅圖 四、基礎的散點圖 一、基礎柱狀圖 如果你還沒有想好你的數據用什麽類型的圖表來展示你的數據,你應該首先考慮是否可以做成柱狀圖。柱狀圖可以表示數據的

1.5神經網絡顯示matplotlib

可視化 orm session 移除 and 混亂 style 操作 pri 神經網絡訓練+可視化顯示 #添加隱層的神經網絡結構+可視化顯示 import tensorflow as tf def add_layer(inputs,in_size,out_si

交互式數據-D3.js形狀生成器

star 弧度 cat raw 圖表 函數 wid 形狀 line 形狀生成器 線段生成器 var linePath = d3.line() - 使用默認的設置構造一個 line 生成器。 linePath.x() - 如果指定了 x 則將 x 訪問器設置為指定的函數或數值

演算法研究1python實現經典排序演算法分析複雜度

排序演算法在演算法界是一個怎麼樣的存在?就好像在學術界中數學的地位,說直接用好像用不上,可是不會做起事情來總會捉襟見肘,左支右絀。找工作的時候,有的面試官甚至會讓我們手寫排序演算法。既然排序演算法如此重要,就讓我們一起去夯實基礎,切切實實得掌握它吧。 前言

TensorFlow——Mnist手寫數字識別 實戰教程

要點: 該教程為深度學習tensorflow框架mnist手寫數字識別。 實戰教程分為(一)(二)(三)分別從tensorflow和MATLAB雙角度來實現。 筆者資訊:Next_Legend  Q

caffe cnn提取各層特徵結果Python介面

親測有用,之前參考的薛開宇的學習筆記,部分程式碼需要修改,自己修改後的版本如下: </p> #caffe特徵的視覺化 import numpy  as np import matplotlib.pyplot as plt import matplotlib.im

Python數據 之 使用API

targa 數據 ces and 模塊 epo form posit 包含 使用requests模塊來請求網站數據 1 import requests 2 3 4 #執行API調用並存儲響應 5 url = ‘https://api.github

學習TensorFlowTensorBoard網絡結構和參數

pla code ext world hold 技巧 n) sample 化工 在學習深度網絡框架的過程中,我們發現一個問題,就是如何輸出各層網絡參數,用於更好地理解,調試和優化網絡?針對這個問題,TensorFlow開發了一個特別有用的可視化工具包:TensorBoard

如何利用mysql+pyecharts儲存資料

目標 爬取紅嶺創投(https://www.my089.com/)日投資發標記錄,儲存在mysql資料庫中, 並將資料視覺化以便分析. 行動 爬取資料 通過selenium+FIrefox的無頭模式將需要的資料爬取出來,程式碼實現不在贅述,詳細步驟可檢視我的上一篇圖文(如何

【Visual Studio 擴展工具】使用 ComponentOne迷你圖控件進行數據趨勢分析

eva lex 擴展工具 連續 cti 支持 人物 論壇 安全   概述    迷你圖 —— Sparklines是迷你的輕量級圖表,有助於快速可視化數據。 它們是由數據可視化傳奇人物Edward Tufte發明的,他將其描述為“數據密集,設計簡單,字節大小的圖形。”雖然迷

java-打印101-200之間的素數PrimeNumber統計個數每5行輸出

ole enum math com math.sqrt day 輸出 package out package com.day3.one; public class PrimeNumber1 {   /**   * @param args   * 打印101-200之間

寫出一種排序算法要寫出代碼說出優化它的方法

TE 插入排序 我們 part while IT 如果 urn class 1 <?php 2 //快速排序 3 function partition(&$arr, $low, $high) 4 { 5 $pivotkey = $arr[$

win10家庭版升級專業版的一些經驗方法超簡單用於專業版的啟用

win10家庭版總有一些不太方便,有好多設定都沒法更改。 於是自己查找了許多教程,找到一條最可靠的、最簡單的升級/啟用方法,在此分享給大家。 此方法有兩種(均要聯網),先看看手動操作是什麼樣的           &