#include
#include
/*
函数功能:创建随机散点,x以固定步长step递增,y则随机动态分布
输入@img:原始彩图
输入@w:图宽
输入@h:图高
输入@step:步长
输入@min:生成随机数的最小值
输入@max:生成随机数的最大值
返回:生成的所有散点
备注:2020.4.18
*/
std::vector createRandPoints(cv::Mat& img, int w, int h, double k, int step, int min, int max)
{
img = cv::Mat::zeros(h, w, CV_8UC3);
std::vector points;
k = -(double)img.rows / img.cols;
//k = - k / 20;
//srand(0);
//int a = -20, b = 20;
for (int i = 0; i < img.cols; i += step)
{
cv::Point p;
p.x = i;
p.y = k * p.x + img.rows - rand() % (max - min) + min;
if (p.y > 0 && p.y < img.rows)
{
points.push_back(p);
cv::circle(img, p, 2, cv::Scalar(0, 0, 255), -1);
}
}
return points;
}
/*
函数功能:最小二乘直线拟合--计算a,b参数,直线方程为:y=ax+b
输入@points:所有散点
输出@a,b:直线方程参数
备注:2020.4.18
*/
void leaseSquares(std::vector points, double &a, double &b)
{
//double a = 0, b = 0;
double x1 = 0, x2 = 0;
double y1 = 0, y2 = 0;
int n = points.size();
for (int i = 0; i < n; i++)
{
x1 += points[i].x;
y1 += points[i].y;
x2 += pow(points[i].x, 2);
y2 += points[i].x * points[i].y;
}
a = (double)(n * y2 - x1 * y1) / (n * x2 - x1 * x1);
b = (double)(x2 * y1 - x1 * y2) / (n * x2 - x1 * x1);
}
/*
函数功能:显示拟合直线结果
输入@img:图像
输入@a,b:直线方程参数
备注:2020.4.18
*/
void showLineFitting(cv::Mat& img, double a, double b)
{
cv::Point p1, p2;
p1.x = 0;
p1.y = b;
p2.x = img.cols;
p2.y = a * p2.x + b;
cv::line(img, p1, p2, cv::Scalar(0, 255, 0), 2);
}
void onTrackbarslide(int pos, void*)
{
//std::cout << pos << std::endl;
cv::Mat src;
std::vector points = createRandPoints(src, 1280, 720, 0.5, 5, -10-pos, 10+pos);
double a, b;
leaseSquares(points, a, b);
showLineFitting(src, a, b);
cv::imshow("Line", src);
}
void main()
{
//cv::Mat src;
//std::vector points = createRandPoints(src, 1280, 720, 1, 5, -30, 30);
//double a, b;
//leaseSquares(points, a, b);
//showLineFitting(src, a, b);
cv::namedWindow("Line", cv::WINDOW_AUTOSIZE);
int position = 0;
cv::createTrackbar("Line", "Line", &position, 100, onTrackbarslide);
//cv::imshow("Line", src);
cv::waitKey(0);
}