生成逼近曲線:approxPolyDP 函數
該函數采用 Douglas-Peucker 算法(也稱迭代終點擬合算法)。可以有效減少多邊形曲線上點的數量,生成逼近曲線,簡化后繼操作。
經典的 Douglas-Peucker 算法描述如下:
- 在曲線首尾兩點 A,B 之間連接一條直線 AB,該直線為曲線的弦;
- 得到曲線上離該直線段距離最大的點 C,計算其與 AB 的距離 d;
- 比較該距離與預先給定的閾值 threshold 的大小,如果小於 threshold,則該直線段作為曲線的近似,該段曲線處理完畢。
- 如果距離大於閾值,則用 C 將曲線分為兩段 AC 和 BC ,並分別對兩段曲線進行 1~3 的處理。
- 當所有曲線都處理完畢時,依次連接各個分割點形成的折線,即可以作為曲線的近似。
void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);
- curve,輸入的二維點集,可以為 vector 或 Mat 類型。
- approxCurve,多邊形逼近的結果,其類型應該和輸入的二維點集類型一致。
- epsilon,逼近的精度,設定的原始曲線與近似曲線之間的最大距離,即上文提到的的閾值。
- closed,如果為真,則近似的曲線為封閉曲線(第一個頂點和最后一個頂點相連),否則,近似的曲線不封閉。
代碼示例:
//作品《抽象的牛》
#include<opencv.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Mat src = imread("C:/Users/齊明洋/Desktop/6.jpg"); imshow("src", src); Mat gray, bin_img; cvtColor(src, gray, COLOR_BGR2GRAY); //將原圖轉換為灰度圖 imshow("gray", gray); //二值化 threshold(gray, bin_img, 150, 255, THRESH_BINARY_INV); Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(bin_img, bin_img, MORPH_CLOSE, kernel, Point(-1, -1), 2);//閉操作,先膨脹后腐蝕,消除小黑點 imshow("bin_img", bin_img); //尋找輪廓 vector<vector<Point> >contours; findContours(bin_img, contours, RETR_TREE, CHAIN_APPROX_NONE); //生成逼近曲線 Mat dst = Mat::zeros(src.size(), src.type()); RNG rngs = { 12345 }; vector<vector<Point> >approx_contours(contours.size());//存放逼近曲線的數組 for (int i = 0; i < contours.size(); i++) { approxPolyDP(contours[i], approx_contours[i], 40, true); Scalar colors = Scalar(rngs.uniform(0, 255), rngs.uniform(0, 255), rngs.uniform(0, 255)); drawContours(dst, approx_contours, i, colors, 3); } imshow("dst", dst); waitKey(0); }
效果演示:
借鑒博客:https://blog.csdn.net/u013925378/article/details/86075230