利用opencv2直接绘制数值向量(std::vector)

以下是一个使用OpenCV 2绘制向量曲线图的C ++函数的示例代码。假设向量xy包含要绘制的数据点:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

void plotCurve(vector<double> x, vector<double> y) {
    // 创建一个黑色的图像
    Mat plot = Mat::zeros(Size(500, 500), CV_8UC3);
    
    // 绘制坐标轴
    line(plot, Point(50, 450), Point(450, 450), Scalar(255, 255, 255), 2, 8, 0);
    line(plot, Point(50, 450), Point(50, 50), Scalar(255, 255, 255), 2, 8, 0);
    
    // 计算数据的范围
    double minX = *min_element(x.begin(), x.end());
    double maxX = *max_element(x.begin(), x.end());
    double minY = *min_element(y.begin(), y.end());
    double maxY = *max_element(y.begin(), y.end());
    
    // 将数据点转换为像素坐标
    vector<Point> points;
    for (int i = 0; i < x.size(); i++) {
        int px = (x[i] - minX) / (maxX - minX) * 400 + 50;
        int py = 450 - (y[i] - minY) / (maxY - minY) * 400;
        points.push_back(Point(px, py));
    }
    
    // 绘制曲线
    polylines(plot, points, false, Scalar(255, 0, 0), 2, 8, 0);
    
    // 显示图像
    imshow("Plot", plot);
    waitKey(0);
}

该函数创建一个大小为500x500像素的黑色图像,并在图像上绘制坐标轴。然后,函数计算数据的范围,并将每个数据点转换为像素坐标。最后,使用polylines函数绘制数据点的曲线,并使用imshow函数显示图像。函数将等待按下任意键才会关闭显示窗口。

要使用该函数,只需将要绘制的数据点存储在vector<double>类型的向量xy中,并将它们传递给plotCurve函数即可。例如:

int main() {
    vector<double> x = {0, 1, 2, 3, 4, 5};
    vector<double> y = {0, 1, 4, 9, 16, 25};
    
    plotCurve(x, y);
    
    return 0;
}

简化改造,不用输入x轴数据

以下是将前面的函数修改后,可以只输入y数据,x数据使用自动生成的刻度的C ++函数示例代码:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

void plotCurve(vector<double> y) {
    // 创建一个黑色的图像
    Mat plot = Mat::zeros(Size(500, 500), CV_8UC3);
    
    // 绘制坐标轴
    line(plot, Point(50, 450), Point(450, 450), Scalar(255, 255, 255), 2, 8, 0);
    line(plot, Point(50, 450), Point(50, 50), Scalar(255, 255, 255), 2, 8, 0);
    
    // 计算数据的范围和刻度
    double minY = *min_element(y.begin(), y.end());
    double maxY = *max_element(y.begin(), y.end());
    double rangeY = maxY - minY;
    double stepY = rangeY / 10;
    
    // 绘制刻度和标签
    for (int i = 0; i <= 10; i++) {
        int py = 450 - i * 40;
        double labelY = minY + i * stepY;
        putText(plot, format("%.1f", labelY), Point(10, py + 5), FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 255, 255), 1);
        line(plot, Point(45, py), Point(55, py), Scalar(255, 255, 255), 2, 8, 0);
    }
    
    // 将数据点转换为像素坐标
    vector<Point> points;
    for (int i = 0; i < y.size(); i++) {
        int px = (i + 0.5) / y.size() * 400 + 50;
        int py = 450 - (y[i] - minY) / rangeY * 400;
        points.push_back(Point(px, py));
    }
    
    // 绘制曲线
    polylines(plot, points, false, Scalar(255, 0, 0), 2, 8, 0);
    
    // 显示图像
    imshow("Plot", plot);
    waitKey(0);
}

该函数与前面的函数类似,但是在绘制坐标轴之后,它计算y数据的范围和步长,然后绘制y轴的刻度和标签。函数将自动生成x数据,并将每个数据点转换为像素坐标。最后,使用polylines函数绘制数据点的曲线,并使用imshow函数显示图像。函数将等待按下任意键才会关闭显示窗口。

要使用该函数,只需将要绘制的y数据点存储在vector<double>类型的向量y中,并将其传递给plotCurve函数即可。例如

int main() {
    vector<double> y = {0, 1, 4, 9, 16, 25};
    
    plotCurve(y);
    
    return 0;
}

改进:允许输入任意数值类型变量

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

template<typename T>
void plotCurve(vector<T> x, vector<T> y) {
    // 创建一个黑色的图像
    Mat plot = Mat::zeros(Size(500, 500), CV_8UC3);
    
    // 绘制坐标轴
    line(plot, Point(50, 450), Point(450, 450), Scalar(255, 255, 255), 2, 8, 0);
    line(plot, Point(50, 450), Point(50, 50), Scalar(255, 255, 255), 2, 8, 0);
    
    // 计算数据的范围和刻度
    double minY = *min_element(y.begin(), y.end());
    double maxY = *max_element(y.begin(), y.end());
    double rangeY = maxY - minY;
    double stepY = rangeY / 10;
    
    // 绘制刻度和标签
    for (int i = 0; i <= 10; i++) {
        int py = 450 - i * 40;
        double labelY = minY + i * stepY;
        putText(plot, format("%.1f", labelY), Point(10, py + 5), FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 255, 255), 1);
        line(plot, Point(45, py), Point(55, py), Scalar(255, 255, 255), 2, 8, 0);
    }
    
    // 将数据点转换为像素坐标
    vector<Point> points;
    for (int i = 0; i < y.size(); i++) {
        int px = (x[i] - x[0]) / (x[x.size()-1] - x[0]) * 400 + 50;
        int py = 450 - (y[i] - minY) / rangeY * 400;
        points.push_back(Point(px, py));
    }
    
    // 绘制曲线
    polylines(plot, points, false, Scalar(255, 0, 0), 2, 8, 0);
    
    // 显示图像
    imshow("Plot", plot);
    waitKey(0);
}

还可以在内部加入类型校对进行类型限制,单变量的输入参数写法类似上面的代码,改一下就好了

猜你喜欢

转载自blog.csdn.net/Q_Linfeng/article/details/129124799