基於OpenCV的圓周率PI值的估計
好久沒有寫部落格了,今天有空寫一下自己做的一個小實驗,有興趣的夥伴一起驗證一下。剛剛開始學習計算機視覺,OpenCV沒有基礎,剛剛接觸這門語言,就做幾個小實驗練習一下。
好了,廢話不多說,進入正題。吾理小子估計圓周率的值是通過內接圓完成的,首先簡述一下原理。
如上圖所示,圓內接於正方形。設圓的半徑為R,易得圓的面積和正方形的面積如下:
由此可得:
有上式可知,如果知道圓的面積和正方形的面積,就可以求出圓周率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;
}