二值图像分析–直线拟合与极值点寻找

2023-11-23 08:50

本文主要是介绍二值图像分析–直线拟合与极值点寻找,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在图像的处理中,会遇到一种情况,根据给定的点集(比如轮廓)拟合出一条直线的情景。

1.最小二乘法拟合直线

最小二乘法多项式直线拟合,根据给定的点,求出它的函数 y = f ( x ) y=f(x) y=f(x),当然求得准确的函数是不太可能的,但是我们能够求出它的近似曲线 y = φ ( x ) y=φ(x) y=φ(x)

原理:
假如有点I = 1,2,3,……n,求近似曲线 y = φ ( x ) y=φ(x) y=φ(x),并且使得 y = φ ( x ) y=φ(x) y=φ(x) y = f ( x ) y=f(x) y=f(x)的平方偏差和最小偏差:

现在有点( x 1 , y 1 x_1,y_1 x1,y1),( x 2 , y 2 x_2,y_2 x2,y2)···( x n , y n x_n,y_n xn,yn)
设: 拟合多项式为: y = a x + b y=ax+b y=ax+b
平方偏差和如下:
e 2 = ∑ i = 1 n ( y i − y ) 2 = ∑ i = 1 n ( y i − ( a x + b ) ) 2 e^2=\sum_{i=1}^{n}(y_i-y)^2 =\sum_{i=1}^{n}(y_i-(ax+b))^2 e2=i=1n(yiy)2=i=1n(yi(ax+b))2

其中我们要找到一组最好的a和b,“最好的”就是要使选出的a b能使得所有的误差达到最小化。所以上面得到的 e 2 = ∑ i = 1 n ( y i − ( a x + b ) ) 2 e^2=\sum_{i=1}^{n}(y_i-(ax+b))^2 e2=i=1n(yi(ax+b))2就是一个关于a和b的函数。

2.多元函数极值与最值问题的理论依据

二元函数取极值的必要条件(类比一元函数)。

可以看到最小二乘法对各个变量求偏导,使得偏导值为0,即可得到最小值,因为e是关于a、b的函数,导数为0的点必定是最小值。
分别对a、b求偏导:
在这里插入图片描述
在这里插入图片描述

OpenCV中的API

  • 说明
    使线拟合2D或者3D点集。

    函数fitLine通过最小化 ∑ i ρ ( r i ) \sum_i \rho(r_i) iρ(ri)将线拟合到2维或3维点,其中 r i r_i ri是第 i t h i^{th} ith个点之间的距离,该线和 ρ ( r ) \rho(r) ρ(r)是一个距离函数。

    该算法基于M-estimator技术,该技术使用加权最小二乘算法迭代拟合直线。每次迭代后,权重 w i w_i wi被调整 ρ ( r i ) \rho(r_i) ρ(ri)

  • 声明

    void fitLine(InputArray points, OutputArray line, int distType,double param, double reps, double aeps );
    
  • 参数

    points用于拟合直线的输入点集,可以是2维或者3维点向量。保存在std::vector<>或者Mat中。
    line输出的直线。对于二维直线而言,类型为cv::Vec4f;对于三维直线类型,则为cv::Vec6f。输出参数的前半部分给出的是直线的方向,而后半部分给出的是直线上的一点(即通常所说的点斜式直线)。
    distType距离类型。拟合直线时,要使输入点到拟合直线的距离和最小化,可供选择的距离类型如下, r i r_i ri表示的是输入的点到直线的距离。
    param某些距离类型的数值参数(C)。跟所选的距离类型有关,值可以设置为0,cv::fitLine()函数本身会自动选择最优化的值如果为0。
    reps半径的足够精度(坐标原点和直线之间的距离)。
    aeps角度精度足够。对于reps和aeps,0.01将是一个很好的默认值。
    distType类型

    ① DIST_L2
    ρ ( r ) = r 2 / 2 (the simplest and the fastest least-squares method) \rho(r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)} ρ(r)=r2/2(the simplest and the fastest least-squares method)
    ② DIST_L1
    ρ ( r ) = r \rho (r) = r ρ(r)=r
    ③ DIST_L12
    ρ ( r ) = 2 ⋅ ( 1 + r 2 2 − 1 ) \rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1) ρ(r)=2(1+2r2 1)
    ④ DIST_FAIR
    ρ ( r ) = C 2 ⋅ ( r C − log ⁡ ( 1 + r C ) ) where C = 1.3998 \rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998 ρ(r)=C2(Crlog(1+Cr))whereC=1.3998
    ⑤ DIST_WELSCH
    ρ ( r ) = C 2 2 ⋅ ( 1 − exp ⁡ ( − ( r C ) 2 ) ) where C = 2.9846 \rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846 ρ(r)=2C2(1exp((Cr)2))whereC=2.9846
    ⑥ DIST_HUBER
    ρ ( r ) = { r 2 / 2 i f r < C C ⋅ ( r − C / 2 ) o t h e r w i s e where C = 1.345 \rho (r)= \begin{cases} r^2/2 &if \ \ r < C \\ C \cdot (r-C/2) &otherwise \end{cases} \quad \text{where} \quad C=1.345 ρ(r)={r2/2C(rC/2)if  r<CotherwisewhereC=1.345

应用

void apprixiLine() {//创建一个用于绘图的空白图Mat src = Mat::zeros(480, 640, CV_8UC3);//输入需要拟合的点vector<Point> points;points.push_back(Point(48, 58));points.push_back(Point(105, 98));points.push_back(Point(155, 160));points.push_back(Point(212, 220));points.push_back(Point(248, 260));points.push_back(Point(320, 300));points.push_back(Point(350, 360));points.push_back(Point(412, 400));//将拟合点画到空白画板上for (size_t i = 0; i < points.size(); i++){circle(src, points[i], 5, Scalar(0, 0, 255));}imshow("src", src);Vec4f line_para;fitLine(points, line_para, DIST_L2, 0, 1e-2, 1e-2);cout << "line_para: " << line_para << endl;Point point0;point0.x = line_para[2];point0.y = line_para[3];cout << "point0:[" << point0.x << "," << point0.y << "]" << endl;double k = line_para[1] / line_para[0];cout << "k=" << k << endl;//计算直线的端点Point point1, point2;point1.x = 0;point1.y = k * (0 - point0.x) + point0.y;point2.x = 640;point2.y = k * (640 - point0.x) + point0.y;cout << "point1:[" << point1.x << "," << point1.y << "]" << endl;cout << "point2:[" << point2.x << "," << point2.y << "]" << endl;line(src, point1, point2, Scalar(0, 255, 0), 2);imshow("dst", src);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 事例二
void findFitLine(Mat& src) {//1. 转化灰度图像Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);//2. 二值化Mat binary;threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);//3. 获得二维点集vector<Point> point_para;Point point_temp;for (size_t i = 0; i < src.rows; i++){for (size_t j = 0; j < src.cols; j++){if (binary.at<unsigned char>(i, j) < 255) {point_temp.x = j;point_temp.y = i;point_para.push_back(point_temp);}}}//4.直线拟合//拟合结果为4元素的容器,比如Vec4f-(vx,vy,x0,y0)//(vx、vy)是直线的方向向量//(x0、y0)是直线上的一个点Vec4f fitline;fitLine(point_para, fitline, DIST_L2, 0, 0.01, 0.01);//4.2 求出直线上的两个点double k = fitline[1] / fitline[0];Point p1(0, k * (0 - fitline[2]) + fitline[3]);Point p2(src.cols - 1, k * ((src.cols - 1) - fitline[2]) + fitline[3]);//4.3 显示拟合出的直线方程cout << "y-" << fitline[3] << "=" << k << "(x-" << fitline[2] << ")" << endl;line(src, p1, p2, Scalar(0, 0, 255), 2);imshow("dst", src);
}int main() {Mat src = imread("D:/test/fitline.png");if (src.empty()) {cout << " input the image error!" << endl;}imshow("src", src);findFitLine(src);waitKey(0);return 0;}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

学习:

直线拟合——cv::fitLine()详解
【算法+OpenCV】基于opencv的直线和曲线拟合与绘制(最小二乘法)
opencv学习——最小二乘法拟合直线
OpenCV—直线拟合fitLine
【OpenCV3】直线拟合–FitLine()函数详解

这篇关于二值图像分析–直线拟合与极值点寻找的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/416755

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结