opencv中的一些界别和根基的学问,elemSize和数量地址总括的明亮

By admin in 4858.com on 2019年4月3日

利用opencv-python1段时间了,因为事先未曾大气触及过c++下的opencv,在网上看c++的片段程序想改成python境遇了好多坑,正幸而此间总括一下。

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

行使opencv-python1段时间了,因为从前未曾大气接触过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,方今本人用的是 二.三版,里面包车型大巴文书档案建议 CvMat 和 CvMatND 弃用了,在C++封装中用 Mat
代替,其它旧版还有2个 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  也正是列,1列1列也正是x啦。width宽度也正是x啦。   

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

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

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

    cols  也便是列,一列一列也正是x啦。width宽度也正是x啦。   

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

OpenCV提供了七个转移函数,cv二.warpAffine和cv2.warpPerspective,通过她们你能够拓展各类转换,cv贰.warpAffine接受二x三的更换矩阵二cv二.warpPerspective收受叁x三的变换矩阵做为输入。

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

  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对象中的二个指南针,指向内存中存放矩阵数据的一块内部存款和储蓄器 (uchar*
data)
dims:Mat所表示的矩阵的维度,如 三 * 4 的矩阵为 2 维, 三 * 4 * 5
的为3维
channels:通道,矩阵中的每叁个矩阵成分拥有的值的个数,比如说 3 * 肆矩阵中壹共 1二 个要素,要是各种成分有八个值,那么就说那个矩阵是 叁通道的,即 channels = 三。常见的是一张彩色图片有红、绿、蓝多个通道。
depth:深度,即每贰个像素的位数(bits),在opencv的Mat.depth()中得到的是二个0 – ⑥ 的数字,分别代表不相同的位数: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:是三个数组,定义了矩阵的布局,具体见上面图片分析,其余注意 step一(step / elemSize一),M.step[m-1] 总是等于
elemSize,M.step1(m-1)总是等于 channels;
elemSize : 矩阵中每3个成分的数目大小,假设Mat中的数据的数据类型是
CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_16UC2 那么
elemSize = 四;记住此外有个 elemSize一 意味着的是矩阵中数据类型的深浅,即
elemSize / channels 的深浅
图片分析壹:思虑2维情况(stored row by row)按行存款和储蓄

缩放

OpenCV有二个函数cv二.resize()来干这几个,图片的深浅能够人工钦定,或许您能够钦命缩放因子。有例外的差值方式能够运用,推荐的插值方法是压缩时用cv二.INTEXC60_AREA,放大用cv2.INTER_CUBIC(慢)和cv2.INTER_LINEA凯雷德。默许情形下差值使用cv二.INTE本田CR-V_LINEA奥德赛。你能够利用下边二种情势来改变图片大小:

import cv2
opencv中的一些界别和根基的学问,elemSize和数量地址总括的明亮。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中运用cv二.方法名或变量名来调用方法/变量

   二)对于持有同样效力的函数的例向外调拨运输用方法,例如

 

//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)

   任何的小坑估量还很多,多Google吧。

三.函数上的选择的分歧处

  在opencv-python中,有众多函数的利用措施都与opencv中分歧,下边简单的解析一下最不相同的地点

   一)python中动用cv贰.方法名或变量名来调用方法/变量

   二)对于具有同等效劳的函数的例向外调运用方法,例如

 

//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)

   其它的小坑臆想还很多,多谷歌(Google)吧。

opencv中的1些分别和基本功的文化,
使用opencv-python1段时间了,因为事先从没大气接触过c++下的opencv,在网上看c++的1部分程序…

 

平移

活动是改变物体的地点。假诺您理解在(x, y)方向的变通是(tx,
ty),你可以创立转换矩阵M:

4858.com 1

你能够把它变成Numpy的数组,类型是np.float32的,然后把它传给cv2.warpAffine()函数,上面包车型客车例子平移(拾0,
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=行数

地点是1个 3 X 四 的矩阵,即便其数据类型为 CV_八U,约等于单通道的 uchar
类型

旋转

对二个图形旋转二个θ角是因而上边这几个方式的转移矩阵完成的:

4858.com 2

可是OpenCV提供了可选主旨的缩放旋转,所以您可以按任意点旋转。转换矩阵变为:

4858.com 3

其中:

4858.com 4

要找到那么些转换矩阵,OpenCV提供了2个函数,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))

结果:

4858.com 5

仿射变换

在仿射变换里,全数原始图片里的平行线在出口的图纸里依然平行,要找到转换矩阵,大家供给输入图片的多个点,和她们在出口图片里的相应地方,然后cv二.getAffineTransform会创立四个贰x叁的矩阵,然后把这些矩阵传给cv2.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()

结果:

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

4858.com 6

M.dims == 2; M.channels() == 3;M.depth() == 0;
M.elemSize() == 3 (每1个成分包蕴二个uchar值) M.elemSize壹() == 壹(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;
图表分析贰:思量三个维度意况(stored plane by plane)按面存款和储蓄

透视变换

对此透视变换,你供给2个三x三的更换矩阵。转换后直线照旧维持直线。要拿走那一个转换矩阵,你需求输入图片上的五个点,以及出口图片上相应的点。在这多少个点中,贰个不能够同线。然后cv贰.getPerspectiveTransform函数就能获取更换矩阵了,再用cv2.warpPerspective来接受那一个叁x三的转换矩阵。

代码:

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()

4858.com 7

END

 

地点是一个 三 X 四 X 6 的矩阵,就算其数据类型为 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() == 4八 / ② == 九六(第壹维度(即面包车型大巴成分个数) * 通道数);
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*5的矩阵,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*伍的矩阵,float型的2通道,把种种点都起先化为1 贰
 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]

4858.com,设若随着
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,则原来ENCOREGB各类通道的25陆种颜色收缩为3二种。

若div为64,则原来卡宴GB每一个通道的25陆种颜色减少为四种,此时三通道全体能表示的颜色有4×四×肆= 6肆 种

先是,大家来看1个函数

C++: uchar* Mat::ptr(int i=0)
i 是行号,重临的是该行数据的指针。
在OpenCV中,一张3大路图像的3个像素点是按BGBMWX三的顺序存款和储蓄的。
先来看看第二种访问方案
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能够更实用的拍卖那种四或是8倍数的行。由于品质方面包车型地铁记挂,在图像每1行的结尾可能会填充壹些像素,那样图像的多寡就不是接2连叁的了

**
我们能够用函数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第1章3) 

二〇一〇-0八-14 二1:45:1九|  分类: 科学斟酌学习 |字号 订阅
上壹篇文章提到了拜访矩阵瓜月素的前二种方法,下边讲第二种办法:正确的走访矩阵中数据的法子:

科学的点子
前方介绍的有的读取和写入矩阵数据的不二秘籍,实际上,你大概很少会采用它们。因为,在多数情景下,你须要动用最有效用的法子来拜访矩阵中的数据。借使接纳上述的函数界面来访问数据,功效比较低,你应当采纳斯达克综合指数针方式来一向访问矩阵中数据。尤其是,就算你想遍历矩阵中有着因素时,就更亟待这么做了。
在用指针直接待上访问矩阵元素时,就须要非常注意矩阵结构体中的step成员。该成员是以字节为单位的每行的长短。而矩阵结构体的cols或width就不切合此时利用,因为为了访问功能,矩阵中的内部存款和储蓄器分配上,是以每多少个字节做为最小单位的。由此只要1个矩阵的宽度是八个字节,那么就会在宽窄上分红八个字节,而那时候每行最终3个字节会被忽视掉。所以大家用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);

}
只要大家的矩阵存款和储蓄的是浮点型(或整数类型)数据,此时矩阵中种种成分占四字节,则只要大家用float类型指针指向下壹行时,大家实在要用float类型指针挪动step/四的长度,因为float类型指针每挪动3个单位就是6个字节长度。
倘若大家的矩阵存款和储蓄的是double类型数据,此时矩阵中各种元素占8字节,则只要大家用double类型指针指向下壹行时,我们实际要用double类型指针挪动step/8的尺寸,因为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()
{
    //矩阵成分为叁通道5位浮点数
    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”);
    }
}

1旦大家使用的指针类型为uchar*项目,则事情大概会简单一些,不用牵挂step/4,step/八等周围景况,大家引进用那种艺术。如下例所示:

#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵成分为三通道7位浮点数
    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”);
    }
}

只是一定要小心了,这么些例子其实是非正常的!因为我们说过,分配矩阵内部存款和储蓄器空间时,是以4字节为最小单位的,那就很有望有不到多个字节而取成几个字节的景观,所以,就算用矩阵首地址从头到尾指下去访问数据,就很有望访问到不是多少的字节上去!那或多或少请务必牢记!!
综述,要是要一向访问矩阵中数量,请记住使用step的方案。

另1个亟需精通的动静是,大家必要精晓二个多维数组(矩阵)和三个壹维,但是包涵高维数据的数组之间的差别。借使,你有n个点(每一种点有x,y,z坐标值)须要保留到CvMat*中,你实在有各个艺术能够动用,但那种种艺术的积存情势各异。你大概选择八个二维矩阵,矩阵大小为n行三列,数据类型为CV3二FC1。你还足以应用三个二维矩阵,矩阵大小为三行n列,数据类型为CV3贰FC一;第两种大概性是,你使用三个一维矩阵,n行一列,数据类型为CV3二FC三;最终,你仍是能够运用1行三列,数据类型为CV3二FC三.那三种办法,在内部存款和储蓄器分配上,有个别是千篇一律的,有个别是见仁见智的,如下所示:

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

n行1列时(数据类型CV32FC三)内部存款和储蓄器分配意况
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行3列时(数据类型CV3二FC一)内部存款和储蓄器分配处境
x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

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

大家得以观察,前二种的内部存款和储蓄器分配情状相同,但最后一种的内部存款和储蓄器分配差异。更扑朔迷离的是,要是有n维数组,每一个数组的成分是c维(c或者是通道数)时。所以,多维数组(矩阵)和1个一维但包含多维数据的数组1般是见仁见智的。

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

发表评论

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

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有