Opencv(C++)学习之 一种用opencv实现高斯曲线拟合的方法

Python | 高斯分布拟合示例 当我们绘制一个数据集(如直方图)时,图表的形状就是我们所说的分布。最常见的连续值形状是钟形曲线,也称为高斯分布或正态分布。它以德国数学家卡尔·弗里德里希·高斯的名字命名。遵循高斯分布的一些常见示例数据集是体温、人的身高、汽车里程、IQ分数。让我们尝试生成理想的正态分布,并使用Python绘制它。 阅读详情
AI摘要

本文介绍了如何在OpenCV库中利用solve函数实现数据的高斯拟合,通过将高斯公式转化为多项式形式,然后求解矩阵参数来提取标准差。作者给出了详细的步骤和代码示例,展示了从输入数据到求解高斯参数的过程。,

背景:

项目中需要实现数据的高斯拟合,进而提取数据中标准差,手头只有opencv库,经过资料查找验证,总结该方法。

基础知识:

1、opencv中solve可以实现对矩阵参数的求解;
2、线的拟合就是对多项式参数求解的过程,多项式可表示为矩阵形式;
3、高斯公式中的指数幂,可以通过取对数的方式转变成多项式的形式;
求解思路:
高斯公式->多项式公式->矩阵参数->调用solve求解;

实现过程及代码

1、确定所选的高斯公式形式

G(x)=a*exp(-((x-b)/c)^2);

2、对于给定的输入x1 ~ xn,有对输出y1 ~ yn。可以形成如下等式:

高斯公式及等式组

对等式左右两边取对数,并进行变换,可形成如下形式
对等式左右取自然对数
注意!!!:这处公式中,c和b符号互换了,图片不好修改,在此说明。感谢 姜丝稀饭 指出
在这里插入图片描述
这里,就形成了AX^2+BX+C=Y的形式,其中
注意!!!:这处公式中,c和b符号互换了,图片不好修改,在此说明。
在这里插入图片描述
用A,B,C替换后后,原等式可写作
在这里插入图片描述
此时,我们只需要计算出A,B,C的值,再通过ABC与abc的关系即可得到abc的值。(请读者自行推导abc的公式,或见代码部分)

得到如上的多项式的形式后,直接构造参数矩阵,调用cv::solve(X,Y,A‘)接口,即可得到参数矩阵A’,其中即含有A,B,C的值。

上代码:

基础定义:

typedef struct StructMultinomialParamt
{
    double dB0;//多项式拟合的参数,数字表示幂次
    double dB1;
    double dB2;
}S_MULTNMNL_PARAMT;
typedef struct StructGaussParamT
{
    double dA;//指定的高斯参数
    double dB;//中心点
    double dC;//标准差
}S_GAUS_PARAMT;
void Gauss(S_GAUS_PARAMT sGsParamm, cv::Mat mX, cv::Mat& mY)
{
    cv::Mat mRslt = Mat::zeros(mX.size(), mX.type());
    double dx = 0;
    for (double i = 0.; i < mX.cols; i++)
    {
        for (double j = 0.; j < mX.rows; j++)
        {
            dx = mX.at<double>(j, i);
            mRslt.at<double>(j, i) = sGsParamm.dA * exp(-(pow((dx - sGsParamm.dB) / sGsParamm.dC, 2)));
        }
    }
    mY = mRslt;
    return;
}

高斯参数求解函数

void GaussFitT(cv::Mat mX, cv::Mat mY, S_GAUS_PARAMT* psGsParamm)
{
    //step1 构造参数矩阵mx与my
    cv::Mat X = Mat::zeros(mX.rows, 3, CV_64FC1);
    for (size_t i = 0; i < mX.rows; i++)
    {
        for (size_t J = 0; J < 3; J++)
        {
            X.at<double>(i, J) = pow(mX.at<double>(i, 0), 2 - J);
        }
    }
    cv::log(mY, mY);//对结果取对数
    //step2 多项式拟合
    cv::Mat A;//参数矩阵
    cv::solve(X, mY, A, cv::DECOMP_SVD);
    S_MULTNMNL_PARAMT sBparam;
    sBparam.dB2 = A.at<double>(0);
    sBparam.dB1 = A.at<double>(1);
    sBparam.dB0 = A.at<double>(2);

    //step3 高斯参数计算ABC-》abc
    psGsParamm->dA = exp(sBparam.dB0 - pow(sBparam.dB1, 2) / (4 * sBparam.dB2));
    psGsParamm->dB = -sBparam.dB1 / (2 * sBparam.dB2);
    psGsParamm->dC = sqrt(-1 / sBparam.dB2);

    return;
}

# 测试代码

double dX[50];//输入数据X
double dY[50];//输入数据Y
std::vector<cv::Point> pointsOri;

for (int i = 0; i < 50; i++)
{

    dX[i] = double(i);
    dY[i] = -0.5 * pow((dX[i] - 25), 2) + 320 + i;
    pointsOri.push_back(cv::Point(dX[i], dY[i]));
}
//转换成求解函数输入需要的数据格式
cv::Mat mGsInputX = Mat::zeros(50, 1, CV_64FC1);
cv::Mat mGsInputY = Mat::zeros(50, 1, CV_64FC1);
for (size_t i = 0; i < 50; i++)
{
    mGsInputX.at<double>(i) = dX[i];
    mGsInputY.at<double>(i) = dY[i];
}

S_GAUS_PARAMT sGsParamm;//求解结果
GaussFitT(mGsInputX, mGsInputY, &sGsParamm);

//结果对比
Mat mGsOutputY;
Gauss(sGsParamm, mGsInputX, mGsOutputY);
std::vector<cv::Point> pointsNew;//拟合结果
for (int i = 0; i < 50; i++)
{
    pointsNew.push_back(cv::Point(dX[i], mGsOutputY.at<double>(i)));
}
cv::Mat img(450, 60, CV_8UC3, cv::Scalar(0, 0, 0));
cv::polylines(img, std::vector<std::vector<cv::Point>>{pointsOri}, false, cv::Scalar(0, 0, 255), 2);
cv::polylines(img, std::vector<std::vector<cv::Point>>{pointsNew}, false, cv::Scalar(255, 255, 255), 0.5);

// 显示图像
cv::imshow("Line Chart", img);
cv::waitKey(0);

运行输出

在这里插入图片描述

红色的为原始数据分布,白色的为拟合计算结果。
而我需要的标准差,则为sGsParamm.dC。

参考:https://blog.youkuaiyun.com/guangjie2333/article/details/115629152
https://blog.youkuaiyun.com/KYJL888/article/details/103073956
https://blog.youkuaiyun.com/qq_35097289/article/details/103910984

后记:

调用solve的接口求解时,OPENCV提供了以下六种方式以对应不同的情况。对于多项式的求解,也可以采用最小二乘法的逼近,不再调用solve方法,这块后面再填坑吧。

cv::DECOMP_LU 高斯消元法(LU分解)
cv::DECOMP_SVD 奇异值分解(SVD)
cv::DECOMP_CHOLESKY 对于对称正定矩阵
cv::DECOMP_EIG 特征值分解,只用于对称矩阵
cv::DECOMP_QR QR因式分解
cv::DECOMP_NORMAL 可选附加标志,表示要求解标准方程

22_OpenCV中求解方程的一系列cv::solve...()函数 1. 求解线性系统的函数 cv::solve() 函数原型: int cv::solve( cv::InputArray lhs, // lefthand side of system, n-by-n cv::InputArray rhs, // righthand side of system, n-by-n cv::OutputArray dst, // result array, will be n-by-1 int method = cv::DECOMP_LU // metho 阅读详情

相关推荐

OpenCV教程(C++)

本教程旨在搬运官方 OpenCV Tutorials 目的有三:一是系统学习OpenCV函数的使用;二是学习系统的教程书写规范;三是学习OpenCV框架系统的底层设计及实现。 下面的链接描述了一组基本的OpenCV教程。这里提到的所有源代码都是作为OpenCV常规发行版的一部分提供的,所以在开始复制和粘贴代码之前要进行检查。下面的教程列表是根据GIT存储库中的reST文件自动生成的。 OpenCV概述 您将学习如何在计算机上安装OpenCV 核心功能(core 模块) 在这里,您将了解这个库的基.

weixin_42715287的博客 1万+

C++ opencv曲线拟合

简介:此问题是在做旋转模板匹配的时候,选择最好的匹配结果时产生的。查找资料发现多项式拟合问题可以变成一个超定方程的求解问题,而opencv中本身有一个cv::solve()函数可以求解线性方程组,因此对于大多数用到opencv又要进行曲线拟合的地方都可以参考此处的求解过程来解决。 1. 问题: 原始数据是一些离散的散点,下图是用matplotlib的plot方法画出来的,我想得到下图中最高处附近的近似的曲线方程,以得到一个最大值和最大值对应的横坐标。从下图看,在最高处附近很像一条抛物线,那就用2次函数去拟合

qq_40622955的博客 9202

OpenCV与Eigen (C++)【学习备忘】

C++ OpenCV

expert_joe的博客 7969

C++:opencv求解矩阵方程的解--solve()

OpenCV中的solve函数主要用于求解线性系统或最小二乘问题。这个函数的功能非常强大,可以处理不同类型的线性方程组,包括非奇异、奇异以及超定方程组。以下是关于OpenCV中solve。

Ethan_Rich的博客 2308

opencv中的椭圆拟合

参考:http://blog.sina.com.cn/s/blog_662c785901011i7z.html

记录计算机应用的点点滴滴!!!!! 2万+

opencv(C++) 图像滤波

图像可以通过灰度分布(空间域)或变化频率(频率域)进行分析。频率域方法将图像分解为不同频率成分,低频对应缓慢变化区域,高频对应快速变化边缘细节。低通滤波器通过卷积核加权平均抑制高频成分,实现图像平滑和去噪,主要包括均值滤波和高斯滤波两种方法。高斯滤波采用中心权重更大的高斯核,能更好保留边缘信息。图像下采样前需先进行低通滤波以防止混叠,OpenCV提供了pyrDown()和resize()等函数实现这一过程,其中pyrDown()内部使用5×5高斯核进行预处理。

seaeress的博客 1629

基于opencv的车道线检测(c++)

基于opencv的车道线检测 原理: 算法基本思想说明: 传统的车道线检测,多数是基于霍夫直线检测,其实这个里面有个很大的误区,霍夫直线拟合容易受到各种噪声干扰,直接运用有时候效果不好,更多的时候通过霍夫直线检测进行初步的筛选,然后再有针对性的进行直线拟合,根据拟合的直线四个点坐标,绘制出车道线,这种方式可以有效避免霍夫直线拟合不良后果,是一种更加稳定的车道线检测方法,在实际项目中,可以选择两种方...

desian 2万+

【算法+OpenCV】基于三次Bezier原理的曲线拟合算法C++与OpenCV实现

Bezier曲线拟合算法是一种相对较容易实现、且拟合的效果较好的算法。关于Bezier曲线原理,请参照(Bezier曲线原理),这里就不再做具体介绍了,我们使用的是Besier三次曲线拟合原理。下面主要介绍算法的实现过程。

guduruyu的专栏 1万+

opencv 直线拟合

一、话说直线拟合霍夫直线检测容易受到线段形状与噪声的干扰而失真,这个时候我们需要另辟蹊径,通过对图像进行二值分析,提取骨架,对骨架像素点拟合生成直线,这种做法在一些场景下非常有效,而且效果还比较好。前面已经讲过霍夫变换,这里就不再叙述,直接上干货。二、距离变换距离变换是二值图像处理与操作中常用手段,在骨架提取,图像窄化中常有应用。距离变换的结果是得到一张与输入图像类似的灰度图像,但是灰度值只出现在...

zhangjunp3的博客 1万+

Opencv学习笔记 - 多项式求解和拟合

曲线的函数类型有:双曲线型、对数型、指数型、多项式型等。对于最常见的曲线, 其特征接近于多项式型, 所以这里的曲线拟合问题就变成了多项式回归求解.一般情况下,对实际的点数据进行求解是无解的, 所以我们需要引入最小二乘法来求解。

学以致用 知行合一 2760

安装升级最新版本postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题

软件版本迭代更新真快,最近升级最新Postman版本时出现以下问题 我就简单纪录下解决办法: 备注:我用的是最新的postman工具包:Postman-win64-7.25.0-Setup.exe,目前是最新 0. 前提是已经到postman官网https://www.postman.com/downloads/下载好软件工具包 1.安装window7系统更新补丁KB2533623,请到微软公司官网https://support.microsoft.com/en-us/help/2...

董广明的博客 1万+

2024:VsCode中配置opencv(C++)

最近在vscode中配置opencv,在网上找了很多帖子,但是可能因为版本不正确,导致库导入失败。所以自己写一个成功的案例

2303_82327196的博客 1万+

博客系统 - 系统简介与首页设计

用Bootstrap实现手机端的博客导航栏效果。

m0_53450409的博客 1237

OpenCV(C++)的曲线拟合polyfit

曲线拟合表达式: f(x)=a0+a1∗x+a2∗x2+a3∗x3+...+an∗xn=[a0,a1,a2,...,an][1,x1,x12,...,x1n]Tf(x) = a_0 + a_1*x + a_2*x^2 + a_3*x^3 + ... + a_n*x^n = [a_0, a_1, a_2 ,..., a_n][1, x_1, x_1^2,..., x_1^n]^Tf(x)=a0​+...

进击的Explorer 8304

Windows环境下pcl点云库 安装配置全流程(精简、有效)

本文为Windows配置点云库pcl步骤,具体是win10、visual studio 2017、pcl1.11.1。

zaibeijixing的专栏 1万+

uniapp - 最新微信小程序手机号一键登录功能效果,uniapp小程序实现手机号码一键登录,uniapp微信小程序端通过手机号授权完成立即登录操作(详细示例源码,新手小白一键复制开箱即用)

uniapp,微信小程序,uniapp小程序平台,uniApp手机号一键登录,uniapp小程序端手机号一键登录功能,实现微信小程序手机号一键登录,在uniapp中实现获取手机一键登录功能,uniapp手机号快捷登录,uniapp微信小程序授权登录并获取手机号,微信小程序手机号快速验证组件调用方式,uniapp小程序怎么用手机号一键登录,uniapp一键登录流程及代码,如何获取手机号一键登录到小程序,微信小程序获取本机手机号一键登录功能,新手详细教程,详细手机一键登录完整示例代码,uni-app微信unia

✅ 精选推荐文章 1万+

【OpenCV(C++)快速入门】--opencv学习

是OpenCV中的一个函数,用于对图像进行高斯模糊处理。高斯模糊是一种图像处理技术,通过使用高斯核对图像进行卷积,可以有效地减少图像的噪声和细节,使图像变得模糊。高斯核的大小必须是正奇数,以确保核的中心能够对准图像的每个像素。腐蚀操作可以缩小图像中的白色区域,通常用于去除小的噪点或分离粘连的部分。输出图像是一个二值图像,边缘部分的像素值为255,非边缘部分的像素值为0。是OpenCV中的一个函数,用于创建形态学操作的结构元素(也称为核或掩模)。:输入图像,这是一个经过Canny边缘检测的二值图像。

StudyWinter的博客 2220

C#实战大华智能安防系统:从SDK封装到视频流与智能报警的全链路落地

本文将介绍C#集成大华SDK开发安防系统的实战经验,重点解决多路视频预览卡顿和报警延迟问题。文章通过三层架构设计(SDK封装层、业务服务层、应用层)实现解耦,详细分析线程安全封装、高效解码显示和智能事件联动等核心技术。针对16路摄像头同时预览时CPU占用率过高的问题,提出使用子码流拉流与异步解码的优化方案,并总结8个常见开发陷阱的解决方案。文中还提供了大华智能安防系统的完整架构图,展示从设备层到应用层的交互流程,特别强调业务服务层中视频流服务和智能报警服务的核心功能设计。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 430

基于Opencv的平面拟合 C++实现。

最小二乘平面拟合。 假设有n多个点,我们需要对这n多个点进行平面拟合,我们会考虑采用最小二乘法去拟合这个平面。 下面我们介绍以下最小二乘拟合平面的原理: 从推导过程分析,我们只需要计算出所有点的系数矩阵,然后等式同时左乘系数矩阵的逆,我们便能很容易的计算出a,b,c C++实现: 实现思路:(此处随机以一个已知平面生成了一个平面点集) 1.首先初始化一个系数矩阵和结果矩阵。 2.判断系数矩阵是否为...

Alonewaiting 8920

PINN求解PDE

PINN求解Dirichlet泊松方程 泊松方程引入 −Δu=f,x∈Ω=(0,1)2-\Delta u=f,x \in \Omega=(0,1)^2−Δu=f,x∈Ω=(0,1)2 u=g,x∈∂Ωu=g,x \in \partial \Omegau=g,x∈∂Ω import torch import time import numpy as np import matplotlib.pyplot as plt import torch.nn as nn def UU(X, order,prob):

forrestguang的博客 3804

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

算法大师! 792

椭圆拟合方法

最近工作中遇到了有关椭圆拟合的问题,把在这一过程中踩坑和最后使用的方法进行了总结。 参考链接:https://github.com/seisgo/EllipseFit https://github.com/xiamenwcy/EllipseFitting opencv3.2的方法 首先使用的是opencv的方法,该方法有时候会失效。 //待拟合的点 vector<Point> vpfi...

千人斩的博客 1万+

Android Framework WMS面试题及参考答案

什么是 WindowManagerService(WMS)?它的作用是什么? WindowManagerService(WMS)是 Android 系统中非常重要的一个系统服务。它运行在系统进程(system_server 进程)中。 从本质上来说,WMS 是 Android 窗口管理系统的核心。它负责管理系统中的所有窗口,包括应用程序窗口、系统窗口(如状态栏、导航栏)等。 它的主要作用有很多。首先是窗口的创建和销毁。当一个应用请求创建一个窗口时,WMS 会协调各个模块完成窗口的创建工

大模型大数据攻城狮的专栏 2163

OpenCV 安装(C++)

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,包含了数百个计算机视觉算法,广泛应用于图像处理、视频分析、物体检测、人脸识别等领域。C++ 是 OpenCV 的原始开发语言,适合高性能应用。在 C++ 项目中使用 OpenCV 之前,首先需要安装 OpenCV 库。

fufu18888的博客 4145

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

OpenCV直线拟合检测

点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达 本文转自:opencv学堂OpenCV直线拟合检测霍夫直线检测容易受到线段形状与噪声的干扰而失真,...

小白学视觉 2902

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

OpenCV车牌识别(C++)

本文介绍了基于OpenCV的车牌识别技术,重点讲解了车牌定位与字符分割的预处理步骤。通过图像缩放、灰度转换、高斯模糊、Gamma校正等操作增强车牌区域特征,去除背景干扰。接着,使用顶帽变换、差分增强、二值化、边缘检测等方法进一步提取车牌区域。最后,通过形态学闭运算和开运算增强车牌轮廓连通性,便于后续轮廓检测与定位。车牌定位部分则通过轮廓提取、形状筛选、面积占比和纹理判断等多维度条件,筛选出可能为车牌的矩形区域,并按宽高比排序,最终输出候选车牌位置。整个流程通过C++代码实现,为车牌识别提供了基础处理方案。

zht678的博客 1825

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: 【算法编程心得记录】
下一篇: Opencv(C++)学习之cv::calcHist 任意bin数量进行直方图计算
沉木渡香
博客等级 码龄14年 652粉丝 68原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉木渡香

感谢鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值