#pragma once #include "opencv.hpp" #include "StdStrFile.h" void CurvePoly(const std::vector<cv::Point>& vPtsInput, std::vector<cv::Point> &curvePoint);
#include "CurvePoly.h" //三次贝塞尔曲线 float bezier3funcX(float uu, cv::Point *controlP){ float part0 = controlP[0].x * uu * uu * uu; float part1 = 3 * controlP[1].x * uu * uu * (1 - uu); float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu); float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; } float bezier3funcY(float uu, cv::Point *controlP){ float part0 = controlP[0].y * uu * uu * uu; float part1 = 3 * controlP[1].y * uu * uu * (1 - uu); float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu); float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu); return part0 + part1 + part2 + part3; } void CurvePoly(const std::vector<cv::Point>& vPtsInput, std::vector<cv::Point> &curvePoint) { //控制点收缩系数 ,经调试0.6较好,cv::Point是opencv的,可自行定义结构体(x,y) int originCount = vPtsInput.size(); float scale = 0.6; cv::Point* midpoints = new cv::Point[originCount]; //生成中点 for (int i = 0; i < originCount; i++){ int nexti = (i + 1) % originCount; midpoints[i].x = (vPtsInput[i].x + vPtsInput[nexti].x) / 2.0; midpoints[i].y = (vPtsInput[i].y + vPtsInput[nexti].y) / 2.0; } //平移中点 cv::Point* extrapoints = new cv::Point[2 * originCount]; for (int i = 0; i < originCount; i++){ int nexti = (i + 1) % originCount; int backi = (i + originCount - 1) % originCount; cv::Point midinmid; midinmid.x = (midpoints[i].x + midpoints[backi].x) / 2.0; midinmid.y = (midpoints[i].y + midpoints[backi].y) / 2.0; int offsetx = vPtsInput[i].x - midinmid.x; int offsety = vPtsInput[i].y - midinmid.y; int extraindex = 2 * i; extrapoints[extraindex].x = midpoints[backi].x + offsetx; extrapoints[extraindex].y = midpoints[backi].y + offsety; //朝 originPoint[i]方向收缩 int addx = (extrapoints[extraindex].x - vPtsInput[i].x) * scale; int addy = (extrapoints[extraindex].y - vPtsInput[i].y) * scale; extrapoints[extraindex].x = vPtsInput[i].x + addx; extrapoints[extraindex].y = vPtsInput[i].y + addy; int extranexti = (extraindex + 1) % (2 * originCount); extrapoints[extranexti].x = midpoints[i].x + offsetx; extrapoints[extranexti].y = midpoints[i].y + offsety; //朝 originPoint[i]方向收缩 addx = (extrapoints[extranexti].x - vPtsInput[i].x) * scale; addy = (extrapoints[extranexti].y - vPtsInput[i].y) * scale; extrapoints[extranexti].x = vPtsInput[i].x + addx; extrapoints[extranexti].y = vPtsInput[i].y + addy; } CStdStrFile ssf; std::vector<cv::Point> vResPts; cv::Point controlPoint[4]; //生成4控制点,产生贝塞尔曲线 for (int i = 0; i < originCount; i++) { controlPoint[0] = vPtsInput[i]; int extraindex = 2 * i; controlPoint[1] = extrapoints[extraindex + 1]; int extranexti = (extraindex + 2) % (2 * originCount); controlPoint[2] = extrapoints[extranexti]; int nexti = (i + 1) % originCount; controlPoint[3] = vPtsInput[nexti]; float u = 1; while (u >= 0){ int px = bezier3funcX(u, controlPoint); int py = bezier3funcY(u, controlPoint); //u的步长决定曲线的疏密 u -= 0.05; cv::Point tempP = cv::Point(px, py); //存入曲线点 if (!ssf.VectorContains(vResPts, tempP)) { vResPts.push_back(tempP); } } } //这样做是为了让函数输入和输出可以使用同一个参数 curvePoint = vResPts; delete[] midpoints; midpoints = nullptr; delete[] extrapoints; extrapoints = nullptr; }