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

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

相关文章

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

Linux中的more 和 less区别对比分析

《Linux中的more和less区别对比分析》在Linux/Unix系统中,more和less都是用于分页查看文本文件的命令,但less是more的增强版,功能更强大,:本文主要介绍Linu... 目录1. 基础功能对比2. 常用操作对比less 的操作3. 实际使用示例4. 为什么推荐 less?5.