opencv CvSolve函数深度解析

2023-11-11

Opencv CvSolve函数主要是用来求解线性系统Ax=b的方程,X的解。solve函数跟它的算法是一样的,也是用来求解线性系统。

        设方程Ax = b.根据有效的方程个数和未知数的个数,可以分为以下3种情况:

1)rank(A) < n,也就是说方程个数小于未知数的个数,约束不够,方程存在无数组解,

2)  rank(A) =  n  方程个数等于未知数的个数, 方程存在唯一的精确解,解法通常有我们熟悉的消元法,LU分解法

3)  rank(A) > n,方程个数多于未知数个数,这个时候约束过于严格,没有精确解,这种方程又称之为超定方程。通常工程应用都会遇到这种情况,找不到精确解的情况下,我们选取最优解。这个最优解,又称之为最小二乘解。

前面2种情况是比较好理解的,我们在这里就不多说了,我们重点研究的是第3种情况,也是我们应用中碰到最多最常见的情况。


这个超定方程的最优解是怎么求的呢?常规的消元法是无解的,于是有人提出并证明了这样一个理论:


以下是定理3的证明:

我们把Ax=b的问题直接转化成A'A x = A'b的求解,那么求超定线性方程组的方法,应该就转换成(A'*A)x = (A'*b)咯。而这个新的方程又具有什么样的特性呢?



那么,这个应该是常规线性方程求解啦,为什么不能直接LU分解或是用消元法呢,这个文档里说了,也确实是可以的
http://wenku.baidu.com/link?url=bTW3JfQzwzXtMWA2JvF4fCS_sXmWYelI2Yx7jKyquo-P8vyKwBb2qxYYJyIgnMFV_rc-PF6yQQaDEmNOR7jGSowVpShTMDg9W_1S_t3Uv7G

update(2017.5.8):这是有前提的,必须是R(A) = n时,AtAx = Atb才有唯一解,否则,我们求的还是最小二乘解。

而在solve函数的代码中,用特征值分解(Jacobi)呢?

Jacobi方法用于求解对称矩阵的特征值,对称矩阵不一定是满秩矩阵,不一定能够顺利的LU分解,但是可以作SVD分解!如果是调用cvSolve的话,求最小二乘解,

那么最后一项要传入CV_SVD.不管是SVD还是jacobi都是跟特征值相关。Jacobi求奇异值分解的方法

详情参考http://blog.csdn.net/k531623594/article/details/50628163.

代码片段加注解:

template<typename _Tp> bool
JacobiImpl_( _Tp* A, size_t astep, _Tp* W, _Tp* V, size_t vstep, int n, uchar* buf )
{
    const _Tp eps = std::numeric_limits<_Tp>::epsilon();
    int i, j, k, m;

    astep /= sizeof(A[0]);
    if( V )
    {
        vstep /= sizeof(V[0]);
        for( i = 0; i < n; i++ )
        {
            for( j = 0; j < n; j++ )
                V[i*vstep + j] = (_Tp)0;
            V[i*vstep + i] = (_Tp)1;
        }
    }

    int iters, maxIters = n*n*30;

    int* indR = (int*)alignPtr(buf, sizeof(int));
    int* indC = indR + n;
    _Tp mv = (_Tp)0;

    for( k = 0; k < n; k++ )
    {
        W[k] = A[(astep + 1)*k];
        if( k < n - 1 )
        {
            for( m = k+1, mv = std::abs(A[astep*k + m]), i = k+2; i < n; i++ )
            {
                _Tp val = std::abs(A[astep*k+i]);
                if( mv < val )
                    mv = val, m = i;
            }
            indR[k] = m; //第a[k][k]右边最大的非对角元素的列下标
        }
        if( k > 0 )
        {
            for( m = 0, mv = std::abs(A[k]), i = 1; i < k; i++ )
            {
                _Tp val = std::abs(A[astep*i+k]);
                if( mv < val )
                    mv = val, m = i;
            }
            indC[k] = m;//第a[k][k]上边最大的非对角元素的行下标
        }
    }

    if( n > 1 ) for( iters = 0; iters < maxIters; iters++ )
    {
        // find index (k,l) of pivot p
        for( k = 0, mv = std::abs(A[indR[0]]), i = 1; i < n-1; i++ )
        {
            _Tp val = std::abs(A[astep*i + indR[i]]);
            if( mv < val )
                mv = val, k = i;
        }
        int l = indR[k];
        for( i = 1; i < n; i++ )
        {
            _Tp val = std::abs(A[astep*indC[i] + i]);
            if( mv < val )
                mv = val, k = indC[i], l = i;
        }

        _Tp p = A[astep*k + l];
        if( std::abs(p) <= eps )
            break;
        _Tp y = (_Tp)((W[l] - W[k])*0.5);
        _Tp t = std::abs(y) + hypot(p, y);
        _Tp s = hypot(p, t);
        _Tp c = t/s;
        s = p/s; t = (p/t)*p;
        if( y < 0 )
            s = -s, t = -t;
        A[astep*k + l] = 0;

        W[k] -= t;
        W[l] += t;

        _Tp a0, b0;

#undef rotate
#define rotate(v0, v1) a0 = v0, b0 = v1, v0 = a0*c - b0*s, v1 = a0*s + b0*c

        // rotate rows and columns k and l
        for( i = 0; i < k; i++ )
            rotate(A[astep*i+k], A[astep*i+l]);
        for( i = k+1; i < l; i++ )
            rotate(A[astep*k+i], A[astep*i+l]);
        for( i = l+1; i < n; i++ )
            rotate(A[astep*k+i], A[astep*l+i]);

        // rotate eigenvectors
        if( V )
            for( i = 0; i < n; i++ )
                rotate(V[vstep*k+i], V[vstep*l+i]);

#undef rotate

        for( j = 0; j < 2; j++ )
        {
            int idx = j == 0 ? k : l;
            if( idx < n - 1 )
            {
                for( m = idx+1, mv = std::abs(A[astep*idx + m]), i = idx+2; i < n; i++ )
                {
                    _Tp val = std::abs(A[astep*idx+i]);
                    if( mv < val )
                        mv = val, m = i;
                }
                indR[idx] = m;
            }
            if( idx > 0 )
            {
                for( m = 0, mv = std::abs(A[idx]), i = 1; i < idx; i++ )
                {
                    _Tp val = std::abs(A[astep*i+idx]);
                    if( mv < val )
                        mv = val, m = i;
                }
                indC[idx] = m;
            }
        }
    }
	//降序排列特征值和相应的特征向量
    // sort eigenvalues & eigenvectors
    for( k = 0; k < n-1; k++ )
    {
        m = k;
        for( i = k+1; i < n; i++ )
        {
            if( W[m] < W[i] )
                m = i;
        }
        if( k != m )
        {
            std::swap(W[m], W[k]);
            if( V )
                for( i = 0; i < n; i++ )
                    std::swap(V[vstep*m + i], V[vstep*k + i]);
        }
    }

    return true;
}


      值得一提的是,当b = 0时,超定齐次线性方程 A*X =0;求解最小二乘解,在||X||=1的约束下,其最小二乘解为矩阵A'A最小特征值所对应的特征向量。

参考http://blog.csdn.net/ccwwff/article/details/45912671

简单证明:

min ||Ax|| 
s.t    ||x||=1
目标函数:||Ax|| = x'A'Ax = x'lamda x=lamda||x||=lamda,其中lamda是A'A的特征值。
于是可知,得到了A'A的最小特征值,就得到了最优值,而其最小特征值对应的特征向量就是最优解.




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv CvSolve函数深度解析 的相关文章

  • 归并排序,自顶向下,自底向上

    http blog csdn net cjf iceking article details 7920153
  • 动态规划算法的优化技巧

    关键词 动态规划 时间复杂度 优化 状态 摘要 动态规划是信息学竞赛中一种常用的程序设计方法 本文着重讨论了运用动态规划思想解题时时间效率的优化 全文分为四个部分 首先讨论了动态规划时间效率优化的可行性和必要性 接着给出了动态规划时间复杂度
  • 【NOIP 2004 提高组】合并果子

    题就自己找啦 各大OJ上应该都有 题目 题目描述 在一个果园里 多多已经将所有的果子打了下来 而且按果子的不同种类分成了不同的堆 多多决定把所有的果子合成一堆 每一次合并 多多可以把两堆果子合并到一起 消耗的体力等于两堆果子的重量之和 可以
  • 几种常用激活函数的简介

    1 sigmod函数 函数公式和图表如下图 在sigmod函数中我们可以看到 其输出是在 0 1 这个开区间内 这点很有意思 可以联想到概率 但是严格意义上讲 不要当成概率 sigmod函数曾经是比较流行的 它可以想象成一个神经元的放电率
  • 编程珠玑第三章习题5——英语中的连字符问题

    编程珠玑第三章习题5 英语中的连字符问题 问题 本问题将处理一小部分用连字符连接的英语单词方面的问题 下面的规则列表描述了一些以字母c结尾的单词的有效连字符连接 et ic al is tic s tic p tic lyt ic ot i
  • 图 深度优先遍历 广度优先遍历 非递归遍历 图解算法过程

    图的邻接矩阵表示 通常图的表示有两种方法 邻接矩阵 邻接表 本文用邻接矩阵实现 一是代码量更少 二是代码风格也更贴近C语言 但不论是图的哪种实现方式 其基本的实现思想是不变的 1 节点的信息 我们用一维数组a n 来存储 假设图共有n个节点
  • 编写一个"banner"函数,该函数的输入为大写字母

    编写一个 banner 函数 该函数的输入为大写字母 题目 编写一个 banner 函数 该函数的输入为大写字母 输出为一个字符数组 该数组以图像化的方式表示该字母 编程 珠玑 上提到当要 输入 的 数据 很多 且没有 规律 时 可以 考虑
  • strassen矩阵乘法

    Strassen矩阵乘法简要解析 Strassen矩阵乘法具体描述如下 两个n n 阶的矩阵A与B的乘积是另一个n n 阶矩阵C C可表示为假如每一个C i j 都用此公式计算 则计算C所需要的操作次数为n3 m n2 n 1 a 其中m表
  • 程序员面试题精选100题(04)-二元树中和为某一值的所有路径

    程序员面试题精选100题 04 二元树中和为某一值的所有路径 题目 输入一个整数和一棵二元树 从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径 打印出和与输入整数相等的所有路径 例如输入整数22和如下二元树 10 5 12
  • 【数学基础】 线性代数以及符号编总

    1基本概念和符号 线性代数可以对一组线性方程进行简洁地表示和运算 例如 对于这个方程组 这里有两个方程和两个变量 如果你学过高中代数的话 你肯定知道 可以为x1 和x2找到一组唯一的解 除非方程可以进一步简化 例如 如果第二个方程只是第一个
  • 程序员面试题精选100题(48)-二叉树两结点的最低共同父结点

    程序员面试题精选100题 48 二叉树两结点的最低共同父结点 题目 二叉树的结点定义如下 struct TreeNode int m nvalue TreeNode m pLeft TreeNode m pRight 输入二叉树中的两个结点
  • Java算法基础:使用递归算法实现,平方相加1^2 + 2^2 + 3^2 +...+ n^2。

    package algorithm recursion public class RecursionTest public static void main String args int m 5 int sumOfSquares sumO
  • 程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表

    程序员面试题精选100题 01 把二元查找树转变成排序的双向链表 参见博客 http zhedahht blog 163 com blog static 254111742007127104759245 http www cnblogs c
  • opencv CvSolve函数深度解析

    Opencv CvSolve函数主要是用来求解线性系统Ax b的方程 X的解 solve函数跟它的算法是一样的 也是用来求解线性系统 设方程Ax b 根据有效的方程个数和未知数的个数 可以分为以下3种情况 1 rank A lt n 也就是
  • 中文分词之HMM模型详解

    关于HMM模型的介绍 网上的资料已经烂大街 但是大部分都是在背书背公式 本文在此针对HMM模型在中文分词中的应用 讲讲实现原理 尽可能的撇开公式 撇开推导 结合实际开源代码作为例子 争取做到雅俗共赏 童叟无欺 没有公式 就没有伤害 模型介绍
  • 快速排序之“采取“尾递归”和“三数取中”技术的快速排序”

    快速排序之 采取 尾递归 和 三数取中 技术的快速排序 下面针对快速排序进行一些优化 QUICKSORT算法包含两个对其自身的递归调用 即调用PARTITION后 左边的子数组和右边的子数组分别被递归排序 QUICKSORT中的第二次递归调
  • 【滑动窗口】算法实战

    文章目录 一 算法原理 二 算法实战 1 leetcode209 长度最小的子数组 2 leetcode3 无重复字符的最长子串 3 leetcode1004 最大连续1的个数 4 leetcode1685 将x减到0的最小操作数 5 le
  • 二分查找及二分答案

    一 二分思想 二分是一种常用且非常精妙的算法 常常是我们解答问题的突破口 二分的基本用途是在单调序列或单调函数中做查找操作 因此当问题的答案具有单调性时 就可以通过二分把求解转化为判定 根据复杂度理论 可知判定的难度小于求解 这使得二分的应
  • 归并排序(分析与模板)

    归并排序 思路 1 确定分界元素mid left right 2 2 递归分解数组 两两组合组成两个有序数组 3 归并 合二为一 int temp 100010 merge sort int num int l int r if l gt
  • 程序员面试题精选100题(30)-赋值运算符重载函数[C/C++/C#]

    程序员面试题精选100题 30 赋值运算符重载函数 C C C 问题 给出如下CMyString的声明 要求为该类型添加赋值运算符函数 class CMyString public CMyString char pData NULL CMy

随机推荐

  • c++ 之 shared_ptr

    shared ptr shared ptr 是一种智能指针 smart pointer 作用有如同指针 但会记录有多少个 shared ptrs 共同指向一个对象 这便是所谓的引用计数 reference counting 一旦最后一个这样
  • oracle字符串生成唯一数字,在C#中生成唯一的字符串和数字【GUID】转

    当我们想要获得一个唯一的key的时候 通常会想到GUID 这个key非常的长 虽然我们在很多情况下这并不是个问题 但是当我们需要将这个36个字符的字符串放在URL中时 会使的URL非常的丑陋 想要缩短GUID的长度而不牺牲它的唯一性是不可能
  • Spark常见错误剖析与应对策略

    问题一 日志中出现 org apache spark shuffle MetadataFetchFailedException Missing an output location for shuffle 0 原因分析 shuffle分为s
  • 第2章 PyTorch基础(1/2)

    第2章 PyTorch基础 PyTorch是Facebook团队于2017年1月发布的一个深度学习框架 虽然晚于TensorFlow Keras等框架 但自发布之日起 其关注度就在不断上升 目前在GitHub上的热度已超过Theano Ca
  • iterator 怎么使用甀_Iterator的理解和使用

    es6成员之一的Iterator 遍历器 Iterator 它是一种接口 为各种不同的数据结构提供统一的访问机制 任何数据结构只要部署Iterator接口 就可以完成遍历操作 即依次处理该数据结构的所有成员 Iterator 的作用有三个
  • 记一次edusrc的漏洞挖掘

    一 前言 在fofa上闲逛的时候发现这个系统 其实之前也碰到过这个系统 当时可能觉得没什么漏洞点就没有管 正好闲着没事又碰到了这个系统 然后就拿过来简单的测试了一下 二 漏洞挖掘 1 信息收集 由于我是在fofa上发现的这个系统 所以也谈不
  • 软件系统设计-15-架构设计

    1 设计架构 Design Architecture 1 1 设计策略 Design Strategies Abstraction Generate Test Decomposition Reusable Elements Iteratio
  • python(数据分析)第5天:图例

    图例 plt legend import matplotlib pyplot as plt import random import matplotlib from matplotlib import cycler from matplot
  • Kafka练习

    需求 写一个生产者 不断的去生产用户行为数据 写入到kafka的一个topic中 生产的数据格式 造数据 guid 1 eventId pageview timestamp 1637868346789 isNew 1 guid 1 even
  • fastjson自定义字段命名规则

    文章首发于个人博客 欢迎访问关注 https www lin2j tech 前置知识 fastjson 在将对象转变为 JSON 字符串时 字段默认使用 CamelCase 规则命名 在1 2 15版本之后 fastjson 支持配置 Pr
  • vue2 ajax异步请求,数据嵌套层数过多,导致页面无法正常通过数据驱动渲染

    数据层数过多的小坑 初入门vue2 在开发项目过程中因为用到了vue echarts v3 涉及图表的数据 难免数据就有过多的层数 导致出现了这么一个坑 其实归根结底是自己没有按照vue2官方的方法进行对象数据修改 首先 数据结构大致是这样
  • 精美简历生成器(Nice_Resume_Builder)

    文章目录 前言 功能演示 后记 前言 写简历有时候是个比较麻烦的事情 不管是用Word还是用别的设计工具 如果内容经常需要修改的话 那么修改后通常有需要花时间去调整格式排版 这个过程令我烦躁 毫无意义的浪费时间 所以稍微花点时间弄了这个东西
  • 超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制了嵌套更新的数量以防

    超过最大更新深度 当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时 可能会发生这种情况 React 限制了嵌套更新的数量以防止无限循环 有没用像我这样报错的 这个报
  • 每天Leetcode 刷题 初级算法篇-设计问题-最小栈

    题目要求 力扣题解 代码 program mydemo description 设计问题 最小栈 author Mr zeng create 2021 02 19 09 49 public class MinStack private St
  • linux获取主板温度电压_穷人省钱技巧揭秘!200元技嘉主板竟可满血英特尔I9处理器?...

    其实 这是一个意外 有一个粉丝 手里置闲了一块技嘉Z270芯片组的主板 本来他以为的型号是GA Z270X UD3 结果 发过来的却是GA Z370 HD3 本来UD3的供电就够乞丐的了 HD3则更加低端 更要命的是 粉丝想搭配的处理器 竟
  • java--基础--26--模块化

    java 基础 26 模块化 代码 https gitee com DanShenGuiZu learnDemo tree mysql mybaties DB java model learn 1 模块化概述 无论是运行一个大型的软件系统
  • MOS管和三极管区别-对比很显然

    在电路设计当中假设我们想要对电流中止控制 那就少不了三极管的帮助 我们俗称的三极管其全称为半导体三极管 它的主要作用就是将微小的信号中止放大 MOS管与三极管有着许多相近的地方 这就使得一些新手不断无法明白两者之间的区别 这里就将为大家引见
  • uniapp 各种兼容,优化等问题记录

    对于ios自带的上下拉 进行禁用 橡皮筋回弹 1 pages json中加入如下配置 path pages my my style navigationBarTitleText 个人中心 disableScroll true 禁止滑动 en
  • xss-labs/level5

    输入 查看回显 如下所示 能够发现script被恶意替换为scr ipt 查看源代码 第一个输出点被转义了 所以没有利用价值了 第二个输出点如同刚才所言被进行了关键字的恶意替换操作 那没办法 我们只能继续尝试一下在标签内部构造一个新属性然后
  • opencv CvSolve函数深度解析

    Opencv CvSolve函数主要是用来求解线性系统Ax b的方程 X的解 solve函数跟它的算法是一样的 也是用来求解线性系统 设方程Ax b 根据有效的方程个数和未知数的个数 可以分为以下3种情况 1 rank A lt n 也就是