iplimage运算加法时用什么在进行无符号数加法运算时

篇一:OpenCV矩阵运算总结

商业转载请聯系作者获得授权非商业转载请注明出处。

转载请注明出处(本文更新链接)


    • OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口其效率与OpenCV一样.
    • OpenCV将向量作为1维矩阵处理.
    • 矩阵按行存储,每行有4字节的校整.
    • //由于opencv的矩阵式一位数组或者一位指针所以我们只能利用opencv的函数对矩阵元素进行操作(当然这样也是最安全的做法,- -!太不习惯了)
    cvCreateMat(4,4,CV_32FC1)//这个函数用来初始化Mat不初始化虽然昰会报warrying,但是运行时会报错由于Mat和IplImage的类型不太一样,所以做两者之间转换的时候想改变数据类型很难(大概可以先转换矩阵类型再转換数据类型,这就麻烦了还没找到好方法),还需要注意这个分配空间并不管理数据的初始化最好利用cvSet对数据进行初始化。
    矩阵加法A+B的更高级形式,支持mask
    矩阵减法A-B的更高级形式,支持mask
    矩阵逐元素乘法同Mat::mul()函数,与A*B区别支持mask
    一个广义的矩阵乘法操作
    矩阵逐元素除法,与A/B区别支持mask
    求每个矩阵元素的平方根
    定位矩阵中最小值、最大值的位置
    返回逐个元素比较结果的矩阵
    每个元素进行位运算,分别是和、非、或、异或
    从旧版数据中提取指定的通道矩阵给新版数据Mat
    随机打乱一个一维向量的元素顺序
    矩阵拷贝的时候指定按x/y方向重复
    多通道矩陣分解成多个单通道矩阵
    多个单通道矩阵合成一个多通道矩阵
    为矩阵的每行或每列元素排序
    检查元素的取值范围是否在另两个矩阵的元素取值之间返回验证矩阵
    检查矩阵的每个元素的取值是否在最小值与最大值之间,返回验证结果bool
    笛卡尔坐标与极坐标之间的转换
    矩阵的特征值和特征向量
    相位计算即两个向量之间的夹角
    求范数,1-范数、2-范数、无穷范数
    先缩放元素再取绝对值最后转换格式为8bit型
    求解多项式嘚实根和重根
    返回一个优化过的DFT大小
    两个傅立叶频谱间逐元素的乘法
 //这个函数可以初始化对角线上的元素,这个是单位阵不是所有元素嘟赋1,这个函数需要第二个函数虽然有默认值,但是这个变量和我之前的理解有点不对也没有实验,贴个原型吧: 
  • 假设需要存取一个2維浮点矩阵的第(i,j)个元素.
  • 直接存取假设使用4-字节校正:
  • 直接存取,校正字节任意:
  • 直接存取一个初始化的矩阵元素:
  • 
        

    注意 Va, Vb, Vc 在向量积中向量元素个數须相同.

    
        
  • 特征值分析(针对对称矩阵):
  • 
        

    标号使得 U 和 V 返回时被转置(若没有转置标号则有问题不成功!!!).//这个函数解释比较少,首先这个函数不能接受IplImage类型的输入变量其次必须是浮点型,原文中这个问题我没有遇到,我使用时最后一个参数用的是默认值0

    1,首先是初始化的问题opencv提供了初始化Mat和初始化MatHead两种方法,文档中介绍都不分配内存存储数据但实际上cvCreateMat这个函数是分配空间的,类推IplImage也是这样不初始化会在运荇时报错。

要转化的矩阵是CV_32FC1,第二个函数不会复制文件头另外要注意,Mat类型中的type包含很多信息不光有矩阵的数据类型,不要尝试在矩阵复制后更改type达到上面的目的。更改type会导致release不成功

    3,opencv不支持不同大小的矩阵相加我又初始化一个载体大小的图像,将水印的奇异徝矩阵复制过去这是我程序为数不多的几次自己编写的程序块,注意更改单个矩阵值的函数是cvmSet和cvmGet不要自己找啊。

     我们有多种方法可以獲得从现实世界的数字图像:数码相机、扫描仪、计算机体层摄影或磁共振成像就是其中的几种在每种情况下我们(人类)看到了什么昰图像。但是转换图像到我们的数字设备时我们的记录是图像的每个点的数值。

      例如在上图中你可以看到车的镜子只是一个包含所有强喥值的像素点矩阵现在,我们如何获取和存储像素值可能根据最适合我们的需要而变化最终可能减少计算机世界内的所有图像数值矩陣和一些其他的信息的描述基质本身。OpenCV 是一个计算机视觉库其主要的工作是处理和操作,进一步了解这些信息因此,你需要学习和开始熟悉它的第一件事是理解OpenCV 是如何存储和处理图像

      OpenCV 自 2001 年出现以来。在那些日子里库是围绕C接口构建的在那些日子里,他们使用名为IplImage C 的結构在内存中存储图像这是您将在大多数较旧的教程和教材中看到的那个。使用这个结构的问题是将 C 语言的所有负面效果都摆到了桌面仩最大的问题是手动管理。它是建立在用户来负责处理内存分配和解除分配的假设之上的当程序规模较小时,这是没有问题的一旦玳码基开始变得越来越大它将会越来越挣扎着处理所有这一切而不是着眼于实际解决自己的开发目标。

      自动内存管理 (或多或少)好消息是,c + +如果完全兼容 C 所以进行更改时没有兼容性问题产生。因此 OpenCV其2.0 版本引入一个新的c + + 接口,通过利用这些优点将为你的工作提供新的方法某种程度上,在其中您不需要拨弄内存管理让你的代码简洁 (写得更少实现的更多)。C + + 接口的唯一主要缺点在于目前许多嵌入式的开发系统支持仅 C.因此,除非您的目标是这一平台否则就没有理由再使用旧的方法(除非你是个受虐狂程序员和喜欢自讨苦吃)。

      你需要知道的关于Mat的第一件事是你不再需要手动分配其大小并且当你不需要它的时候你不再需要手动释放它虽然这样做仍然是可能的,大哆数 OpenCV 函数将手动分配其输出数据还有一个额外的好处是如果传递一个已存在Mat对象,它已经为矩阵分配所需的空间这段空间将被重用。吔就是说我们在任何时候只使用与我们执行任务时所必须多的内存一样多的内存

的矩阵头和一个指针,指向包含了像素值的矩阵(可根據选择用于存储的方法采用任何维度存储数据)矩阵头部的大小是恒定的。然而矩阵本身的大小因图像的不同而不同,通常是较大的數量级因此,当你在您的程序中传递图像并在有些时候创建图像副本您需要花费很大的代价生成图像矩阵本身而不是图像的头部。OpenCV 是圖像处理库它包含大量的图像处理函数。若要解决的计算挑战最终大部分时间你会使用库中的多个函数。由于这一原因图像传给库中嘚函数是一种常见的做法我们不应忘记我们正在谈论往往是计算量相当大的图像处理算法。我们想要做的最后一件事是通过制作不必要嘚可能很大的图像的拷贝进一步降低您的程序的速度

      为了解决这一问题 OpenCV 使用引用计数系统。其思想是Mat的每个对象具有其自己的头但可能他们通过让他们矩阵指针指向同一地址的两个实例之间共享该矩阵。此外拷贝运算符将只能复制矩阵头部,也还将复制指针到大型矩陣但不是矩阵本身。

      上文中的所有对象以相同的单个数据矩阵的结束点。他们头不同但是使用的其中任何一个对矩阵进行任何修改,也将影响所有其他的在实践中的不同对象只是提供相同的底层数据不同的访问方法,然而它们的头部是不同的。真正有趣的部分是您可以创建仅指向完整数据的一小部分的头例如,要在图像中创建兴趣区域 ( ROI) 您只需创建一个新头设置新边界:

现在你可能会问是否矩陣的本身可以属于多个Mat对象在不再需要时负责清理数据。简短的回答是:最后一个使用它的对象这对于使用引用计数的机制,每当有人複制Mat对象的头矩阵的计数器被增加。每当一个头被清除此计数器被下调。当该计数器变为零矩阵也就被释放了。因为有时会仍然也偠复制矩阵的本身存在着 clone() 或 copyTo() 函数。

      这是关于你是如何存储的像素值您可以选择的颜色空间和使用的数据类型。色彩空间是指我们如何結合为了代码指定的颜色的颜色分量最简单的是灰色的规模。在这里我们所掌握的颜色是黑色和白色组合的这些让我们能创造很多的咴度级。

     对于彩色的方法我们有很多方法可供选择。不过每一就是将他们拆解成三个或四个基本组成部分,这些部分就会组合给所有其他的方法最受欢迎的这一个 RGB,主要是因为这也是我们的眼睛如何建立中我们的眼睛的颜色其基准的颜色是红、 绿、 蓝。编写代码的┅种颜色的透明度有时第四个元素: 添加 alpha (A)但是,它们很多颜色系统每个具有自身的优势:

           · 单纯疱疹和合肥分解颜色到他们的色相、 饱囷度和亮度值/组件这是我们来描述颜色更自然的方式。您使用例如可驳回的最后一个组件,使你不那么明智的输入图像的光照条件的算法

      现在,每个建筑构件都自己有效的域这会导致使用的数据类型。我们如何存储组件的定义只是如何精细的控制我们已于其域。朂小的数据类型可能是 char 类型这意味着一个字节或 8 位。这可能是有在进行无符号数加法运算时(值-127 到 + 127)或无在进行无符号数加法运算时(鉯便可以存储从 0 到 255 之间的值)虽然这三个组件的情况下已经给 16 万可能的颜色来表示 (如 RGB 的情况下) 我们可能通过使用浮点数 (4 字节 = 32 位) 戓double(8 字节 = 64 位) 数据类型的每个组件获得甚至更精细的控制。然而请记住增加组件的大小也会增加在内存中的整张图片的大小。

函数将一個矩阵写到一个图像文件中然而,出于调试目的显示的实际值就方便得多您可以实现此通过Mat的 <<运算符。不过请注意这仅适用于二维矩阵。

     虽然Mat是一个伟大的图像容器类它也是一般矩阵类。因此利用Mat创建和操作多维矩阵是可能的。您可以通过多种方式创建Mat的对象:

     嘫后我们需要指定的数据类型用于存储元素和每个矩阵点通道的数量。为此我们根据以下的约定可以作出多个定义:

CV_ [每一项的位数] [有茬进行无符号数加法运算时或无在进行无符号数加法运算时] [类型前缀] C [通道数]

例如,CV_8UC3 意味着我们使用那些长的 8 位无在进行无符号数加法运算時的 char 类型和每个像素都有三个项目的这三个通道的形成这是预定义的四个通道数字。Scalar 是四个元素短向量指定此和可以初始化所有矩阵點与自定义的值。但是如果你需要更多您可以创建与上部宏和频道号码放在括号中您可以看到下面的类型。

上例为我们展示了如何创建┅个二维以上的矩阵首先指定其维度数,然后传入一个包含了尺寸每个维度信息的指针其他都保持不变。

?为一个已经存在的IplImage创建一個头:

你不能通过这个构造来初始化矩阵中的数值它只会在新的居住尺寸与旧的矩阵尺寸不合时重新分配矩阵的数据空间。

:eyes().指定使用嘚尺寸和数据类型

?对于小的矩阵来说你可以使用逗号隔开的初始化函数:

?为一个已有的Mat对象创建一个新的头然后clone()或者copyTo()这个头.

注意:你鈳以通过用randu()函数产生的随机值来填充矩阵你需要给定一个上限和下限来确保随机值在你期望的范围内:

在上一个例子中你可以看到默认嘚格式选项。尽管如此OpenCV允许你在符合以下规则的同时格式化你的输出:

OpenCV 通过<<操作符也为其他常用OpenCV数据结构提供打印输出的支持,如:

这裏大多数的例程都是在一个小控制台程序里运行你可以在这里下载或是在cpp示例文件夹下找到。

你可以在YouTube.上找到一个快速的实例演示

m – 被賦值的右侧的矩阵 矩阵的赋值是一个复杂度为O(1) 的操作。 这就意味着没有数据段复制并且有数量的递增两矩阵将使用同一引用计数器在給矩阵赋新数据之前先由Mat::release()释放引用。

expr –被赋值的矩阵表达式对象 作为第一种赋值方式的逆操作第二种形式可以被重新用到具有适当大小囷尺寸的已分配空间的矩阵上以适应表达式的结果。矩阵表达式扩展得到的实函数将自动处理这个分配过程例如:

s – 标量赋值给每一个矩阵元,矩阵的大小和类型将不会改变有现成的赋值运算符。由于他们各不相同请阅读运算符参数说明

创建一个指定行数的矩阵头。.

該方法创建一个具有指定了行数的新矩阵头的矩阵并返回它这是一个复杂度为O(1) 的操作,无须考虑矩阵的尺寸新矩阵和原矩阵共享一份基础数据。这是一个典型基本矩阵处理操作的例子, axpy是LU和许多其它算法都使用的一个函数

Note:在当前实现中下面的代码不会无法按预期的效果工作:

发生这种情况是因为 A.row(i) 形成临时矩阵头进一步分配给另一个矩阵头。请记住每个操作复杂度为O(1),即没有复制任何数据因此,如果你预期第 j行被复制到第 i行那么上述赋值不成立。要做到这一点应该把这种简单的赋值转换到表达式中或使用 Mat::copyTo() 方法:

/ / 可行,但看仩去有点目的不明确

/ / 这是有点儿长,但这是推荐的方法

创建一个具有指定了矩阵头中列数这个参数的矩阵

j –一个0基(从0开始)的列索引

该方法创建一个具有指定了矩阵头中列数这个参数的新矩阵并作为函数返回值。这是一种复杂度为O(1)的操作不用考虑矩阵的尺寸大小。噺矩阵和原始矩阵共享一份基础数据参看Mat::row()说明信息。

为指定的行span创建一个新的矩阵头

r – Range 结构包含着起始和终止的索引值。该方法给矩陣指定的行span创建了新的头 与Mat::row() 和 Mat::col()相类似这是一个复杂度为O(1)的操作。

为指定的行span创建一个矩阵头

r –Range 结构包含着起始和终止的索引值。该方法给矩阵指定的列span创建了新的头 与Mat::row() 和 Mat::col()相类似这是一个复杂度为O(1)的操作。

提取或创建矩阵对角线

d – 对角线的索引值,可以是以下的值:

– d=0 是主对角线

– d>0表示下半部的对角线例如:d=1对角线是紧挨着住对角线并位于矩阵下方。

– d<0表示来自矩阵上半部的对角线例如:d= 1表示对角线被设置在对角线的上方并紧挨着。

matD – 单列用于形成矩阵对角线的列

该方法为指定的矩阵创建一个新的头。然后新矩阵被分割为单独嘚列矩阵类似于Mat::row() 和Mat::col() ,它是复杂度为O(1)操作。

创建一个数组及其基础数据的完整副本

该方法创建了一个完整的数组副本。原始的step[]不会被考虑茬内的因此数组的副本是一占用total()*elemSize()字节的连续阵列。

把矩阵复制到另一个矩阵中

m – 目标矩阵。如果它的尺寸和类型不正确在操作之前会重新分配。

mask – 操作掩码它的非零元素表示矩阵中某个要被复制。

该方法把矩阵的复制到另一个新的矩阵中在复制之前该方法會调用

因此目标矩阵会在必要的情况下重新分配

尽管m.copyTo(m) works ?awlessly,该函数并不处理源矩阵和目标矩阵之间有重叠的部分的情况。当操作掩码指定以忣上述的Mat::create重新分配矩阵新分配的矩阵在数据复制到里面之前全都被初始化为0。

在缩放或不缩放的情况下转换为另一种数据类型

m – 目標矩阵。如果它的尺寸和类型不正确在操作之前会重新分配。

rtype – 要求是目标矩阵的类型或者在当前通道数与源矩阵通道数相同的情况丅的depth。如果rtype 为负目标矩阵与源矩阵类型相同。

该方法将源像素值转化为目标类型saturate_cast<> 要放在最后以避免溢出

提供了一个convertTo的功能形式

type – 要求昰目标阵列depth或-1(如果阵列的类型和源矩阵类型相同)

将阵列中所有的或部分的元素设置为指定的值。

s – 把标量赋给阵列并转化到阵列嘚实际类型

在无需复制数据的前提下改变2D矩阵的形状和通道数或其中之一。

cn – 新的通道数若cn=0,那么通道数就保持不变

该方法为*this元素創建新的矩阵头。这新的矩阵头尺寸和通道数或其中之一发生改变在以下的情况任意组合都是有可能的:

ü 新的矩阵没有新增或减少元素。通常rows*cols*channels()在转换过程中保持一致。.

ü 无数据的复制也就是说,这是一个复杂度为 O(1)的操作通常,如果该操作改变行数或透过其他方式妀变元素行索引那么矩阵必定是连续的。参见Mat::isContinuous()

例如,有一存储了STL向量的三维点集你想用3xN的矩阵来完成下面的操作:

//同样是复杂度为O(1)嘚运算

//这个过程要复制所有的元素

method – 反转矩阵的方法。有以下几种可能的值:

– DECOMP_CHOLESKY 是 Cholesky LLT只适用于对称正矩阵的分解该类型在处理大的矩阵时嘚速度是LU的两倍左右。

– DECOMP_SVD是 SVD 分解如果矩阵是单数或甚至不是2维,函数就会计算伪反转矩阵

该方法执行矩阵的反转矩阵表达。这意味着該方法返回一个临时矩阵反转对象并可进一步用于更复杂的矩阵表达式的中或分配给一个矩阵

执行两个矩阵按元素相乘或这两个矩阵的除法。

m – 与*this具有相同类型和大小的矩阵,或矩阵表达式

该方法返回一个用可选的缩放比率编码了每个元素的数组乘法的临时的对象。 注意:这不是一个对应“*”运算符的简单的矩阵乘法.

计算3元素向量的一个叉乘积。

m –另一个叉乘操作对象

该方法计算了两个3元素向量的叉乘的积被操作向量必须是3元素浮点型的具有相同形状和尺寸的向量。结果也是一语被操作对象的具有相同形状和大小的浮点型3元素姠量

m –另一个点积操作对象。

方法计算两个矩阵的点积如果矩阵不单列或单行的向量,用顶部到底部从左到右扫描次序将它们视为 1 D向量这些向量必须具有相同的大小和类型。如果矩阵有多个通道从所有通道得到的点积会被加在一起。

返回指定的大小和类型的零数组

sizes– 指定数组的形状的整数数组。

type– 创建的矩阵的类型

该方法返回一个 Matlab 式的零数组初始值设定项。它可以用于快速形成一个常数数组作為函数参数作为矩阵的表达式或矩阵初始值设定项的一部分。

在上面的示例中只要A不是 3 x 3浮点矩阵它就会被分配新的矩阵。否则为现有嘚

返回一个指定的大小和类型的全为1的数组

sizes –指定数组的形状的整数数组。

该方法返回一个 Matlab 样式 1 的数组初始值设定项类似Mat::zeros()。请注意這种方法中你可以使用任意一个值和Matlab 语法初始化数组如下:

上述操作不会形成一个 100 x 100 1 的矩阵,然后乘以 3相反,它只是记住

缩放因子(在本唎中 3)在实际调用矩阵初始值设定项时使用它


了解过html的都知道提交数据用的昰form表单,表单中的内容是被发送出去的内容

大部分开发都是这样的,先画ui后考虑功能所以我们先用代码表示出这个界面:

然后我们考慮我们的逻辑代码:

解释一下,因为在jsp中request属于9个内置函数中的一员,所以不用实例化(即不用创建对象)这是属于jsp的内置对象,所以進行纯java开发的时候不能这么写


我们观看出错信息(红色划线处)可以知道:变量被赋予了null值 ( 这是新手最最最最容易犯的错 )

原来是因為 jsp 刚运行的时候,输入框内都是没有值的所以这时候直接输出a+b就会输出null+null。

为了解决这个错误我们必须设置 if 语句判断值是否为空,所以唍整代码如下:

还有另一种实现方式通过按钮的点击事件:

举一反三,我们可以融合一些以前学过的html的知识加强我们的页面:

我要回帖

更多关于 在进行无符号数加法运算时 的文章

 

随机推荐