好久没有写博客了,今天有空写一下自己做的一个小实验,有兴趣的伙伴一起验证一下。刚刚开始学习计算机视觉,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;
}