威尼斯人线上娱乐

【威尼斯人线上娱乐】opencv中的壹些有别于和根基的学问,elemSize和数目地址总括的明白

18 4月 , 2019  

动用opencv-python一段时间了,因为事先从未大气触及过c++下的opencv,在网上看c++的部分程序想改成python遇到了广大坑,正幸而此处总括一下。

opencv-python与c++ opencv中的1些分别和根基的学问,

使用opencv-python一段时间了,因为事先从未大气触及过c++下的opencv,在网上看c++的有的先后想改成python遭受了成百上千坑,正万幸此处总计一下。

cv::Mat
depth/dims/channels/step/data/elemSize
The class Mat represents an n-dimensional dense numerical single-channel
or multi-channel array. It can be used to store
(Mat类的指标用于表示四个多维度的单通道也许多通道稠密数组,它能够用来储存以下东西)
real or complex-valued vectors or matrices (实数值或复合值向量、矩阵)
grayscale or color images (灰度图恐怕彩色图)
voxel volumes (立体成分)
vector fields (矢量场)
point clouds (点云)
tensors (张量)
histograms (though, very high-dimensional histograms may be better
stored in a SparseMat ) (直方图,北齐灵炀帝度的最棒存放在SparseMat中)
旧版本的OpenCV中的C结构体有 CvMat 和 CvMatND,近年来本人用的是 2.3版,里面包车型大巴文书档案提出 CvMat 和 CvMatND 弃用了,在C++封装中用 Mat
替代,其余旧版还有3个 IplImage,同样用 Mat 取代(能够参报考博士硕士文
OpenCV中的结构体、类与Emgu.CV的对应表).
矩阵 (M) 中数量成分的地点总结公式:
addr(Mi0,i1,…im-1) = M.data + M.step[0] * i0 + M.step[1] * i1 + …

转换

1.opencv 中x,y,height, width,rows,cols 的关系(转自

    opencv中图像的x,y 坐标以及 height, width,rows,cols
他们的关联平时混淆。

    rows 其实正是行,一行1行也正是y 啦。height中度也正是y啦。

    cols  相当于列,壹列一列也等于x啦。width宽度也正是x啦。   

1.opencv 中x,y,height, width,rows,cols 的关系(转自

    opencv中图像的x,y 坐标以及 height, width,rows,cols
他们的关联平时混淆。

【威尼斯人线上娱乐】opencv中的壹些有别于和根基的学问,elemSize和数目地址总括的明白。    rows 其实正是行,1行壹行也正是y 啦。height中度也便是y啦。

    cols  也正是列,1列壹列也正是x啦。width宽度相当于x啦。   

  • M.step[m-1] * im-1 (其中 m = M.dims M的维度)

OpenCV提供了多少个转移函数,cv贰.warpAffine和cv2.warpPerspective,通过他们你能够拓展种种转变,cv二.warpAffine经受二x3的转移矩阵②cv贰.warpPerspective接受3x三的更改矩阵做为输入。

二.补偿(以下均为原创):

  1. opencv python中的rows
    cols分别为img.shape[0](height)和img.shape[1](width)
  2. opencv c++中的图像对象访问像素可使用.at :cv::mat的分子函数:
    .at(int y, int
    x),能够用来存取图像中对应坐标为(x,y)的因素坐标。然而在选取它时要小心,在编译期必供给已知图像的数额类型.但在opencv-python中做客像素可平昔使用诸如img[x][y]
    的点子开展落实

  原因:和opencv不相同,近来opencv-python中的数组均为numpy array方式。

二.补给(以下均为原创):

  原因:和opencv不相同,近年来opencv-python中的数组均为numpy array格局。

data:Mat对象中的1个指针,指向内存中存放矩阵数据的壹块内部存储器 (uchar*
data)
dims:Mat所表示的矩阵的维度,如 叁 * 四 的矩阵为 二 维, 3 * 4 * 5
的为3维
channels:通道,矩阵中的每多少个矩阵元素具有的值的个数,比如说 叁 * 4矩阵中一共 1二 个要素,倘使每一种成分有三个值,那么就说那个矩阵是 叁通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝八个通道。
depth:深度,即每3个像素的位数(bits),在opencv的Mat.depth()中取得的是三个0 – 6 的数字,分别表示差异的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2,
CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位,
2和3都代表16位,4和5代表32位,6代表64位;
step:是3个数组,定义了矩阵的布局,具体见上面图片分析,其余注意 step1(step / elemSize一),M.step[m-1] 总是等于
elemSize,M.step一(m-一)总是等于 channels;
elemSize : 矩阵中每三个要素的多寡大小,如若Mat中的数据的数据类型是
CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_1六UC二 那么
elemSize = 四;记住此外有个 elemSize1 代表的是矩阵中数据类型的高低,即
elemSize / channels 的大小
图形分析一:思量二维情况(stored row by row)按行存款和储蓄

缩放

OpenCV有二个函数cv贰.resize()来干那个,图片的大小可以人工钦点,或然你能够钦赐缩放因子。有两样的差值格局得以采纳,推荐的插值方法是压缩时用cv2.INTELacrosse_AREA,放大用cv2.INTER_CUBIC(慢)和cv2.INTER_LINEARAV四。暗中同意意况下差值使用cv二.INTE纳瓦拉_LINEACR-V。你能够行使上边三种艺术来更换图片大小:

import cv2
import numpy as np

img = cv2.imread(‘messi5.jpg’)
res = cv2.resize(img, None, fx=2, fy=2,
interpolation=cv2.INTER_CUBIC)

#OR

height, width = img.shape[:2]
res = cv2.resize(img, (2*width, 2*height),
interpolation=cv2.INTER_CUBIC)

三.函数上的使用的分歧处

  在opencv-python中,有过多函数的采取措施都与opencv中分歧,下边轻巧的分析一下最差异的地点

   1)python中选用cv2.方法名或变量名来调用方法/变量

   贰)对于全数相同效果的函数的例外调用方法,例如

 

//c++
cvtColor(srcImg, binaryImg, COLOR_BGR2GRAY);

 

#python
binaryImg = cv2.cvtColor(srcImg,cv2.COLOR_BGR2GRAY)

    当然对于种种具体的函数的切实用法,能够自动上网搜索

   3)python中对此变量的花色是不须求表明的,所以将c++中代码修改为python时索要留意多数(缩进即便很有利查看,不过依然以为写{}的感到很爽23三)

   四)python中函数参数可以为array格局,所以c++
opencv中的许多类型都以不存在的,切记使用cv二.类型名()去选择,例如

//c++
circle(srcImg, Point(x, y), 3, Scalar(255, 0, 255), 2, 8, 0);

#python
cv2.circle(srcImg, (x, y), 3, (255, 100, 255), 1, 8, 0)

   任何的小坑推测还广大,多谷歌吧。

三.函数上的利用的分化处

  在opencv-python中,有众多函数的运用措施都与opencv中不一样,上边轻松的剖析一下最分裂的地方

   壹)python中应用cv二.方法名或变量名来调用方法/变量

   2)对于有所同等效果的函数的不等调用方法,例如

 

//c++
cvtColor(srcImg, binaryImg, COLOR_BGR2GRAY);

 

#python
binaryImg = cv2.cvtColor(srcImg,cv2.COLOR_BGR2GRAY)

    当然对于各种具体的函数的实际用法,能够自动上网找出

   叁)python中对此变量的门类是不需求申明的,所以将c++中代码修改为python时索要专注许多(缩进尽管很方便查看,然而仍旧感到到写{}的觉获得很爽23三)

   四)python中等学校函授数参数可感到array方式,所以c++
opencv中的繁多项目都以不设有的,切忌采取cv2.类型名()去采纳,例如

//c++
circle(srcImg, Point(x, y), 3, Scalar(255, 0, 255), 2, 8, 0);

#python
cv2.circle(srcImg, (x, y), 3, (255, 100, 255), 1, 8, 0)

   别的的小坑测度还大多,多谷歌(Google)吧。

opencv中的1些界别和根基的学问,
使用opencv-python壹段时间了,因为事先并未有大气接触过c++下的opencv,在网上看c++的1些程序…

 

平移

一举手一投足是改造物体的职责。如若您精晓在(x, y)方向的浮动是(tx,
ty),你能够创建调换矩阵M:

威尼斯人线上娱乐 1

你能够把它变成Numpy的数组,类型是np.float3二的,然后把它传给cv二.warpAffine()函数,上面包车型地铁事例平移(100,
50):

import cv2
import numpy as np

img = cv2.imread(‘messi5.jpg’, 0)
rows, cols = img.shape

M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img, M, (cols,rows))

cv2.imshow(‘img’, dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

警告:
cv二.warpAffine()函数的第柒个参数是出口图片的大大小小,应该是(width,
height)的格局,记住width=列数,height=行数

地方是一个 三 X 四 的矩阵,尽管其数据类型为 CV_八U,也正是单通道的 uchar
类型

旋转

对一个图纸旋转三个θ角是经过上边那一个方式的调换矩阵落成的:

威尼斯人线上娱乐 2

唯独OpenCV提供了可选中心的缩放旋转,所以您能够按任意点旋转。调换矩阵变为:

威尼斯人线上娱乐 3

其中:

威尼斯人线上娱乐 4

要找到这几个转变矩阵,OpenCV提供了叁个函数,cv二.getRotationMatrix二D。看上面包车型地铁例子,把图纸旋转了90度

img = cv2.imread(‘messi5.jpg’, 0)
rows, cols = img.shape

M = cv2.getRotationMatrix2D((cols/2,rows/2), 90, 1)
dst = cv2.warpAffine(img, M, (cols, rows))

结果:

威尼斯人线上娱乐 5

仿射调换

在仿射调换里,全数原始图片里的平行线在出口的图纸里依旧平行,要找到转变矩阵,大家须求输入图片的几个点,和她俩在出口图片里的附和地点,然后cv二.getAffineTransform会创设贰个2×3的矩阵,然后把那些矩阵传给cv二.warpAffine.

看上面的例子,注意自身选的几个点(天青的点)

img = cv2.imread(‘drawing.png’)
rows, cols, ch = img.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])

M = cv2.getAffineTransform(pts1, pts2)

dst = cv2.warpAffine(img,M,(cols, rows))

plt.subplot(121), plt.imshow(img), plt.title(‘Input’)
plt.subplot(122), plt.imshow(dst), plt.title(‘Output’)
plt.show()

结果:

那是二个2维矩阵,那么维度为 二 (M.dims == 2);
M.rows == 3; M.cols == 4;
sizeof(uchar) = 一,那么每三个数据成分大小为 1 (M.elemSize() == 一,
M.elemSize1() == 一);
CV_8U 得到 M.depth() == 0, M.channels() == 1;
因为是2维矩阵,那么 step 数组只有多少个值, step[0] 和 step[1]
分别表示①行的多寡大小和一个要素的数据大小,则 M.step[0] == 4,
M.step[1] == 1;
M.step1(0) == M.cols = 4; M.step1(1) == 1;
若是下边包车型地铁矩阵数据类型是 CV_八UC三,也正是三通道

威尼斯人线上娱乐 6

M.dims == 2; M.channels() == 3;M.depth() == 0;
M.elemSize() == 叁 (每三个因素包罗一个uchar值) M.elemSize1() == 一(elemSize / channels)
M.step[0] == M.cols * M.elemSize() == 12, M.step[1] == M.channels()
* M.elemSize1() == M.elemSize() == 3;
M.step(0) == M.cols * M.channels() == 12 ; M.step(1) == M.channels() ==
3;
图形分析2:怀想三个维度景况(stored plane by plane)按面存款和储蓄

透视转换

对此透视转换,你供给二个3x三的改动矩阵。转变后直线如故维持直线。要取得那些变换矩阵,你要求输入图片上的七个点,以及出口图片上相应的点。在那八个点中,三个无法同线。然后cv2.getPerspectiveTransform函数就能得到更动矩阵了,再用cv2.warpPerspective来抽出这么些3x三的转变矩阵。

代码:

img = cv2.imread(‘sudokusmall.png’)
rows, cols, ch = img.shape

pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img, M,(300,300))

plt.subplot(121), plt.imshow(img), plt.title(‘Input’)
plt.subplot(122), plt.imshow(dst), plt.title(‘Output’)
plt.show()

威尼斯人线上娱乐 7

END

 

地点是1个 三 X 4 X 六 的矩阵,假诺其数据类型为 CV_16SC4,也就是 short
类型

M.dims == 3 ; M.channels() == 4 ; M.elemSize1() == sizeof(short) == 2
;
M.rows == M.cols == –1;
M.elemSize() == M.elemSize1() * M.channels() == M.step[M.dims-1] ==
M.step[2] == 2 * 4 == 8;
M.step[0] == 4 * 6 * M.elemSize() == 192;
M.step[1] == 6 * M.elemSize() == 48;
M.step[2] == M.elemSize() == 8;
M.step1(0) == M.step[0] / M.elemSize() == 48 / 2 == 96(第一维度(即面包车型大巴要素个数) * 通道数);
M.step1(1) == M.step[1] / M.elemSize() == 1二 / 二 ==
二④(第二维度(即行的要素个数/列宽) * 通道数);
M.step1(2) == M.step[2] / M.elemSize() == M.channels() ==
4(第三个维度度(即成分) * 通道数);
End :

Author : Ggicci

正文讲解Mat 的局地中坚的起首化

// m为3*伍的矩阵,float型的单通道,把各样点都开始化为1
Mat m(3, 5, CV_32FC1, 1);
或者 Mat m(3, 5, CV_32FC1, Scalar(1));
cout<<m;
输出为:
[1, 1, 1, 1, 1;
  1, 1, 1, 1, 1;
  1, 1, 1, 1, 1]

// m为3*5的矩阵,float型的贰通道,把各类点都初阶化为一 二
 Mat m(3, 5, CV_32FC2, Scalar(1, 2));
cout<<m;
输出为
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2;
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2;
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

// m为3*伍的矩阵,float型的3大路,把每一种点都开端化为一 二 三
Mat m(3, 5, CV_32FC3, Scalar(1, 2, 3));
cout << m;
输出为
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3;
  1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3;
  1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

// 从已某些数据源开头化
double *data = new double[15];
for (int i = 0; i < 15; i++)
{
   data[i] = 1.2;
}
Mat m(3, 5, CV_32FC1, data);
cout << m;
输出为:
[1.2, 1.2, 1.2, 1.2, 1.2;
  1.2, 1.2, 1.2, 1.2, 1.2;
  1.2, 1.2, 1.2, 1.2, 1.2]

假定随着
delete [] data;
cout << m;
输出为:
[-1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144;
  -1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144;
  -1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144, -1.456815990147463e+144,
-1.456815990147463e+144]
看得出,那里只是实行了浅拷贝,当数据源不在的时候,Mat里的数额也正是乱码了。

// 从图像初叶化
 Mat m = imread(“1.jpg”, CV_LOAD_IMAGE_GRAYSCALE);
 cout<< “channels =”<<m.channels()<<endl;
 cout << “cols =”<<m.cols<<endl;
 cout << “rows =”<<m.rows<<endl;
 cout << m;
输出为:
channels =1
cols =13
rows =12
[179, 173, 175, 189, 173, 163, 148, 190, 68, 14, 19, 31, 22;
  172, 172, 172, 180, 172, 177, 162, 190, 64, 13, 19, 30, 17;
  177, 180, 176, 175, 169, 184, 165, 181, 58, 12, 23, 38, 25;
  181, 183, 178, 178, 170, 181, 163, 182, 52, 8, 23, 37, 23;
  176, 173, 173, 184, 175, 178, 164, 195, 60, 14, 24, 35, 16;
  179, 175, 176, 187, 176, 175, 158, 191, 70, 21, 28, 37, 20;
  182, 183, 180, 184, 174, 179, 155, 174, 54, 1, 5, 15, 2;
  173, 182, 178, 176, 173, 191, 165, 169, 157, 101, 100, 107, 93;
  181, 182, 180, 177, 177, 177, 171, 162, 183, 185, 186, 185, 182;
  178, 180, 179, 177, 178, 179, 174, 167, 172, 174, 175, 174, 172;
  175, 178, 179, 178, 180, 182, 179, 173, 172, 174, 175, 175, 174;
  175, 179, 181, 180, 181, 183, 181, 177, 178, 180, 182, 183, 182]

剧情出自《OpenCV ② Computer Vision Application Programming Cookbook》

OpenCV二 拜访图像的逐壹像素有各样办法

作者们来用各类情势来完结收缩图像的水彩数量

color = color/div*div +div/2;

若div为8,则原来KugaGB每一个通道的256种颜色收缩为3二种。

若div为6肆,则原来锐界GB各样通道的25陆种颜色收缩为四种,此时3通道全部能表示的水彩有四×4×4= 6四 种

先是,我们来看一个函数

C++: uchar* Mat::ptr(int i=0)
i 是行号,重返的是该行数据的指针。
在OpenCV中,一张3通道图像的三个像素点是按BGRubicon的顺序存款和储蓄的。
先来探望第3种访问方案
void colorReduce1(cv::Mat& image, cv::Mat& result, int div=64){
    int nrow = image.rows;
    int ncol = image.cols * image.channels();
    for(int i=0; i<nrow; i++){
        uchar* data = image.ptr<uchar>(i);
        uchar* data_out = result.ptr<uchar>(i);
        for(int j=0; j<ncol; j++){
            data_out[j] = data[j]/div*div +div/2;
        }
    }
}

第三种方案:

先来看如下函数:

C++: bool Mat::isContinuous() const

C++: Mat Mat::reshape(int cn, int rows=0) const

因为图像在OpenCV里的储存机制难点,行与行以内大概有空白单元。这几个空白单元对图像来说是向来不意思的,只是为了在某个框架结构上能够更有效能,比如intel
MMX能够更实惠的处理那种四或是八倍数的行。鉴于质量方面包车型大巴思考,在图像每一行的终极只怕会填充1些像素,那样图像的多少就不是接连的了

**
小编们能够用函数is孔蒂nuous()来推断图像的数目是不是延续

reshape函数的意义如下:

Changes the shape and/or the number of channels of a 2D matrix without
copying the data.

那般,大家就建议了对第二种方法的革新

void colorReduce2(cv::Mat& image, cv::Mat& result, int div){
    if(image.isContinuous()){
        image.reshape(1,image.cols*image.rows);**

    }
    int nrow = image.rows;
    int ncol = image.cols * image.channels();
    for(int i=0; i<nrow; i++){
        uchar* data = image.ptr<uchar>(i);
        uchar* data_out = result.ptr<uchar>(i);
        for(int j=0; j<ncol; j++){
            data_out[j] = data[j]/div*div +div/2;
        }
    }
}

或:

1 void colorReduce(const Mat& image,Mat& outImage,int div)
 2 {
 3     int nr=image.rows;
 4     int nc=image.cols;
 5     outImage.create(image.size(),image.type());
 6     if(image.isContinuous()&&outImage.isContinuous())
 7     {
 8         nr=1;
 9         nc=nc*image.rows*image.channels();
10     }
11     for(int i=0;i<nr;i++)
12     {
13         const uchar* inData=image.ptr<uchar>(i);
14         uchar* outData=outImage.ptr<uchar>(i);
15         for(int j=0;j<nc;j++)
16         {
17             *outData++=*inData++/div*div+div/2;
18         }
19     }
20 }

*
其二种方案:
先来探望上面的函数
C++: template<typename T> T& Mat::at(int i, int j)
其效果是Returns a reference to the specified array element.
void colorReduce3(cv::Mat& image, cv::Mat& result, int div){
    int nrow = image.rows;
    int ncol = image.cols \
image.channels();
    for(int i=0; i<nrow; i++){
        for(int j=0; j<ncol; j++){
            image.at<cv::Vec3b>(j,i)[0]=
image.at<cv::Vec3b>(j,i)[0]/div*div + div/2;
            image.at<cv::Vec3b>(j,i)[1]=
image.at<cv::Vec3b>(j,i)[1]/div*div + div/2;
            image.at<cv::Vec3b>(j,i)[2]=
image.at<cv::Vec3b>(j,i)[2]/div*div + div/2;
        }
    }
}
第伍种方案是使用迭代器
会动用到如下函数:
C++: template<typename _Tp> MatIterator_<_Tp>
Mat::begin()
C++: MatIterator_<_Tp> Mat::end()
void colorReduce4(cv::Mat& image, cv::Mat& result, int div){
    cv::Mat_<cv::Vec3b>::iterator it =
image.begin<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::iterator itend =
image.end<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::iterator itout =
result.begin<cv::Vec3b>();
    for(; it!=itend; ++it,++itout){
        (*itout)[0] = (*it)[0]/div*div + div/2;
        (*itout)[1] = (*it)[威尼斯人线上娱乐 ,1]/div*div + div/2;
        (*itout)[2] = (*it)[2]/div*div + div/2;
    }
}
OpenCV中矩阵数据的拜访(二)(Learning OpenCV第二章叁) 

200九-08-1四 贰一:四5:1玖|  分类: 调研学习 |字号 订阅
上一篇文章提到了拜访矩阵兰秋素的前二种方法,上边讲第②种方法:正确的访问矩阵中数量的方法:

没有错的办法
前边介绍的1部分读取和写入矩阵数据的不二等秘书籍,实际上,你或然很少会选择它们。因为,在大部情景下,你须要选取最有成效的方法来拜访矩阵中的数据。借使接纳上述的函数分界面来访问数据,作用相比较低,你应当运用指针方式来一直访问矩阵中数据。越发是,借使你想遍历矩阵中具有因素时,就更亟待这么做了。
在用指针直接待上访问矩阵成分时,就必要丰富上心矩阵结构体中的step成员。该成员是以字节为单位的每行的长短。而矩阵结构体的cols或width就不相符此时利用,因为为了访问成效,矩阵中的内部存款和储蓄器分配上,是以每五个字节做为最小单位的。由此只要二个矩阵的大幅度是三个字节,那么就会在步长上分红多个字节,而此刻每行最终一个字节会被忽视掉。所以大家用step则会规范地按行访问数据。
小编们能够透过以下例子,看一下rows,cols,height,width,step的数码,你能够通过改换矩阵的因素类型定义,来查看step的转移:
#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵成分为三通道六个人浮点数
    CvMat *mat=cvCreateMat(3,3,CV_32FC3 );
    printf(“rows=%d,cols=%d,height=%d,width=%d,step=%d\n”,mat->rows,mat->cols,mat->height,mat->width,mat->step);

}
如果大家的矩阵存储的是浮点型(或整数类型)数据,此时矩阵中各个成分占4字节,则只要大家用float类型指针指向下一行时,大家实际要用float类型指针挪动step/4的长短,因为float类型指针每挪动一个单位正是五个字节长度。
尽管大家的矩阵存款和储蓄的是double类型数据,此时矩阵中各类成分占8字节,则只要大家用double类型指针指向下1行时,大家实际上要用double类型指针挪动step/八的长短,因为double类型指针每挪动二个单位正是几个字节长度。
我们再一次看一下CvMat类型的数据结构定义,当中,data正是数据部分,指向data的指针能够是二种数据类型的:
typedef struct CvMat {
    int type;
    int step;
    int* refcount;     // for internal use only
    union {
         uchar* ptr;
         short* s;
         int*    i;
         float* fl;
         double* db;
    } data;//数据部分
    union {
         int rows;
         int height;
    };
    union {
         int cols;
         int width;
    };
} CvMat;

咱俩得以由此为矩阵赋值,和读取的例证,查看怎么样利用step:
#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵元素为三通道五人浮点数
    CvMat *mat=cvCreateMat(3,3,CV_32FC3 );
    float *p;
    int row,col;
    for(row=0; row< mat->rows; row++)
    {
        p = mat->data.fl + row * (mat->step/4);
        for(col = 0; col < mat->cols; col++)
        {
            *p = (float) row+col;
            *(p+1) = (float) row+col+1;
            *(p+2) =(float) row+col+2;
            p+=3;
        }
    }

    for(row = 0; row < mat->rows; row++)
    {
        p = mat->data.fl + row * (mat->step/4);
        for(col = 0; col < mat->cols; col++)
        {
            printf(“%f,%f,%f\t”,*p,*(p+1),*(p+2));
            p+=3;
        }
        printf(“\n”);
    }
}

一旦大家应用的指针类型为uchar*品种,则事情可能会轻巧一些,不用考虑step/四,step/八等接近景况,大家引入用这种办法。如下例所示:

#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵成分为三通道6个人浮点数
    CvMat *mat=cvCreateMat(3,3,CV_32FC3 );
    float *p;
    int row,col;
    for(row=0; row< mat->rows; row++)
    {
        p = (float*)(mat->data.ptr + row * mat->step);
        for(col = 0; col < mat->cols; col++)
        {
            *p = (float) row+col;
            *(p+1) = (float) row+col+1;
            *(p+2) =(float) row+col+2;
            p+=3;
        }
    }

    for(row = 0; row < mat->rows; row++)
    {
        p = (float*)(mat->data.ptr + row * mat->step);
        for(col = 0; col < mat->cols; col++)
        {
            printf(“%f,%f,%f\t”,*p,*(p+1),*(p+2));
            p+=3;
        }
        printf(“\n”);
    }
}

最终要小心一下,大家在每行都要使用step重新计算一下指南针的地点,那好象不及从首指针从头到尾一贯指下去,如大家上一文章的事例一样


#pragma comment( lib, “cxcore.lib” )
#include “cv.h”
#include <stdio.h>
void main()
{
    //矩阵成分为三通道浮点数
    CvMat* mat = cvCreateMat(3,3,CV_32FC3);
    cvZero(mat);//将矩阵置0
    //为矩阵成分赋值

    //获得矩阵成分(0,0)的指针
    float *p = (float*)cvPtr2D(mat, 0, 0);
    //为矩阵赋值
    for(int i = 0; i < 9; i++)
    {
        //为每种通道赋值
        *p = (float)i*10;   
        p++;
        *p = (float)i*10+1;
        p++;
        *p = (float)i*10+2;
        p++;
    }

    //打字与印刷矩阵的值
    p =  (float*)cvPtr2D(mat, 0, 0);

    for(i = 0; i < 9; i++)
    {
        printf(“%2.1f,%2.1f,%2.1f\t”,*p,*(p+1),*(p+2));
        p+=3;
        if((i+1) % 3 == 0)
            printf(“\n”);
    }
}

不过毫无疑问要注意了,那么些例子其实是有格外态的!因为我们说过,分配矩阵内存空间时,是以四字节为最小单位的,那就很有希望有不到多少个字节而取成五个字节的意况,所以,如若用矩阵首地址从头到尾指下去访问数据,就很有望访问到不是数量的字节上去!那或多或少请务必牢记!!
归结,若是要一贯访问矩阵中多少,请记住使用step的方案。

另1个亟需了然的图景是,大家要求驾驭1个多维数组(矩阵)和1个一维,可是包罗高维数据的数组之间的差别。即便,你有n个点(每一个点有x,y,z坐标值)须要保留到CvMat*中,你实在有八种艺术能够动用,但那五种艺术的囤积格局各异。你恐怕选拔三个二维矩阵,矩阵大小为n行叁列,数据类型为CV3二FC一。你仍是能够应用3个二维矩阵,矩阵大小为三行n列,数据类型为CV3贰FC1;第三种或者性是,你使用一个壹维矩阵,n行一列,数据类型为CV3二FC3;最终,你仍是能够运用一行三列,数据类型为CV3二FC三.这两种办法,在内部存款和储蓄器分配上,有个别是千篇壹律的,有个别是见仁见智的,如下所示:

n个点的集结(n=伍);
(x0 y0 z0) (x1 y1 z1) (x2 y2 z2) (x3 y3 z3) (x4 y4 z4)

n行壹列时(数据类型CV32FC三)内部存款和储蓄器分配情状
x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

一行n列时(数据类型CV3二FC③)内部存款和储蓄器分配景况
x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

n行三列时(数据类型CV32FC1)内存分配情形
x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

3行n列时(数据类型CV32FC一)内部存款和储蓄器分配情状
x0 x1 x2 x3 x4 y0 y1 y2 y3 y4 z0 z1 z2 z3 z4

我们能够看出,前二种的内部存款和储蓄器分配景况一样,但最后一种的内部存款和储蓄器分配分化。更复杂的是,若是有n维数组,各类数组的要素是c维(c恐怕是通道数)时。所以,多维数组(矩阵)和2个一维但包蕴多维数据的数组1般是见仁见智的。

对此一个Rows行Cols列,通道数为Channels的矩阵,访问当中第row行,第col列,第channel通路的多寡,能够接纳如下公式:
数码地址偏移量=row*Cols*Channels+col*Channels+channel**


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图