1. 程式人生 > >基於OpenCV的圓周率PI值的估計

基於OpenCV的圓周率PI值的估計

 好久沒有寫部落格了,今天有空寫一下自己做的一個小實驗,有興趣的夥伴一起驗證一下。剛剛開始學習計算機視覺,OpenCV沒有基礎,剛剛接觸這門語言,就做幾個小實驗練習一下。

 好了,廢話不多說,進入正題。吾理小子估計圓周率的值是通過內接圓完成的,首先簡述一下原理。

                                             

如上圖所示,圓內接於正方形。設圓的半徑為R,易得圓的面積和正方形的面積如下:

                                                               S_{a}=Pi*R^{2}

                                                               S_{s}=4*R^{2}

由此可得:

                                                               Pi=4*\frac{S^{_{a}}}{S_{s}}

有上式可知,如果知道圓的面積和正方形的面積,就可以求出圓周率Pi的值。

此時,我們假設有一個未知邊長的正方形及其內接圓。我們可以通過向正方形內隨機撒入多個噪點,由噪點的個數來近似正方形的面積,用落在圓內的噪點個數來等效圓的面積,由此就可以估算圓周率Pi的值了。

接下來,使用OpenCV來實現上述過程。我將原始碼貼在文末,供各位小夥伴參考。

下面先給出程式的執行過程,以及估計結果。

                              

                              

                              

上面三幅圖分別是估計過程中的三個圖,最後一幅圖是估計結果3.13908,與真實值3.1415還是比較接近的。可以通過進一步增大正方形的邊長來提高估計精度。最後貼上原始碼。


#include <iostream>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	const int side = 600;        //定義正方形邊長
	const int npixels = 300000;  //定義隨機點個數

	int i, j;
	Mat s1 = Mat::zeros(side,side,CV_8UC1);
	Mat s2 = s1.clone();         //影象s1,s2均為0值,即純黑
	circle(s1, Point(side / 2, side / 2), side / 2, 255, -1);//在s1正方形影象中開闢一個內接圓
	imshow("s1", s1); //顯示s1影象

	for (int k = 0; k < npixels; k++)  //產生隨機數,撒在影象s2中
	{
		i = rand() % side;
		j = rand() % side;
		s2.at<uchar>(i, j) = 255;
	}

	Mat r;    //定義輸出影象r
	bitwise_and(s1,s2,r); //影象s1與s2進行與運算

	imshow("s2", s2);     //顯示影象s2
	imshow("r", r);       //顯示影象r

	int Acircle = countNonZero(r);   //統計影象r中的非零點個數
	int Square = countNonZero(s2);   //統計影象s2中的非零點個數
	float pi = 4 * (float)Acircle / Square;  //估計圓周率的值

	cout << "PI的值:" << pi << endl;  //輸出圓周率的值

	waitKey(0);
	return 0;

}