轉自:http://www.bfcat.com/index.php/2012/11/random-polygon-ellipse/
今天在一個部落格上看到的。
在一張紙上隨機畫一些點,然後將他們連起來形成隨機的多邊形。找到多邊形所有邊的中點並將這些中點連成一個新的多邊形,如此重複下去,最終的結果會是一個越來越小的形狀,而且會趨向與一個橢圓!
這個過程如,也可以進入作者提供的一個app網頁自己動手操作一下:
matthen 部落格裡還給了這個過程的代碼。這個部落格還介紹了其他很多有意思的數學和科學問題,值得訂閱。
================== 以下內容為原創 ==================
本文地址:http://blog.csdn.net/houston11235/article/details/8498938轉載請註明
這個現象看起來挺有意思的,於是用 OpenCV 類比了一下,遇到了幾個問題
1、座標歸一化,由於這麼取中點多邊形肯定是越來越小的,不做歸一化一會就收到到一點了
2、座標的資料類型,開始用的整型,發現點多了很難收斂,可能是在近似的過程中達到穩態了,於是改成浮點型,這下收斂了,點數多也能收斂到橢圓
把代碼貼出來,有想一探究竟的朋友可以拿去看看
// Poly2Ellipse.h#include <opencv.hpp>#include <vector>#include <iostream>using namespace std;using namespace cv;#define img_width 400#define img_height 400#define n_pts 100
// Poly2Ellipse.cpp#include "Poly2Ellipse.h"void display(Mat& img, string win_name, int wait_time = 1){namedWindow(win_name);imshow(win_name, img);waitKey(wait_time);}void drawPts(Mat& img, vector<Point2f>& pts){for (size_t i = 0; i < pts.size(); ++i){circle(img, pts[i], 3, Scalar(0,255,0));}for (size_t i = 0; i < pts.size() - 1; ++i){line(img, pts[i], pts[i+1], Scalar(0,0,255));}line(img, pts.back(), pts.front(), Scalar(0,0,255));}void interpPt(const vector<Point2f>& pts1, vector<Point2f>& pts2){float x_max = -1;float y_max = -1;float x_min = 10000;float y_min = 10000;for (size_t i = 0; i < pts1.size() - 1; ++i){pts2[i].x = (pts1[i].x + pts1[i + 1].x) / 2;pts2[i].y = (pts1[i].y + pts1[i + 1].y) / 2;if (pts2[i].x > x_max){x_max = pts2[i].x;}if (pts2[i].y > y_max){y_max = pts2[i].y;}if (pts2[i].x < x_min){x_min = pts2[i].x;}if (pts2[i].y < y_min){y_min = pts2[i].y;}}pts2.back().x = (pts1.front().x + pts1.back().x) / 2;pts2.back().y = (pts1.front().y + pts1.back().y) / 2;if (pts2.back().x > x_max){x_max = pts2.back().x;}if (pts2.back().y > y_max){y_max = pts2.back().y;}if (pts2.back().x < x_min){x_min = pts2.back().x;}if (pts2.back().y < y_min){y_min = pts2.back().y;}float x_ratio = 0.8 * img_width / (x_max - x_min);float y_ratio = 0.8 * img_height / (y_max - y_min);int x_shift = 0.1 * img_width;int y_shift = 0.1 * img_height;for (size_t i = 0; i < pts2.size(); ++i){pts2[i].x = x_ratio * (pts2[i].x - x_min) + x_shift;pts2[i].y = y_ratio * (pts2[i].y - y_min) + y_shift;}}int main(void){Mat img_show(img_height, img_width, CV_8UC3, Scalar(0));Mat img_black = img_show.clone();//int n_pts = 10;RNG rng(getTickCount());Mat tmp(1, 2, CV_32S);vector<Point2f> pts1(n_pts);vector<Point2f> pts2(n_pts);for (int i = 0; i < n_pts; ++i){pts1[i].x = rng.uniform(0, img_width);pts1[i].y = rng.uniform(0, img_height);}drawPts(img_show, pts1);display(img_show, "img");for (;;){interpPt(pts1, pts2);img_black.copyTo(img_show);pts1 = pts2;drawPts(img_show, pts1);display(img_show, "interp");if (waitKey(50)=='e'){break;}}waitKey(0);return 0;}