opencv中的1些界别和基础的知识,图片的几何转变

应用opencv-python1段时间了,因为事先从未大气触及过c++下的opencv,在网上看c++的片段程序想改成python境遇了累累坑,正幸而那里计算一下。

opencv-python与c++ opencv中的一些区分和基本功的学识,

动用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类的指标用于表示2个多维度的单通道大概多通道稠密数组,它能够用来储存以下东西)
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.三版,里面包车型地铁文书档案建议 CvMat 和 CvMatND 弃用了,在C++封装中用 Mat
替代,此外旧版还有三个 IplImage,一样用 Mat 代替(能够参报考博士大学生文
OpenCV中的结构体、类与Emgu.CV的对应表).
矩阵 (M) 中数据成分的地点计算公式:
addr(Mi0,i1,…im-1) = M.data + M.step[0]opencv中的1些界别和基础的知识,图片的几何转变。 * i0 + M.step[1] * i1 + …

转换

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

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

    rows 其实就是行,壹行一行也正是y 啦。height高度也正是y啦。

    cols  也正是列,壹列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经受2x三的转移矩阵2cv二.warpPerspective接受三x三的更动矩阵做为输入。

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

  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对象中的3个指南针,指向内部存款和储蓄器中存放矩阵数据的1块内部存款和储蓄器 (uchar*
data)
dims:Mat所代表的矩阵的维度,如 叁 * 4 的矩阵为 二 维, 3 * 4 * 5
的为3维
channels:通道,矩阵中的每3个矩阵成分具有的值的个数,比如说 三 * 四矩阵中1共 1二 个要素,假诺每一种成分有两个值,那么就说那么些矩阵是 3通道的,即 channels = 叁。常见的是一张彩色图片有红、绿、蓝八个通道。
depth:深度,即每三个像素的位数(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:是二个数组,定义了矩阵的布局,具体见上面图片分析,其它注意 step壹(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 = 肆;记住其余有个 elemSize壹 代表的是矩阵中数据类型的分寸,即
elemSize / channels 的分寸
图片分析一:记挂2维情形(stored row by row)按行存储

缩放

OpenCV有2个函数cv贰.resize()来干这些,图片的分寸能够人工钦定,恐怕您能够钦赐缩放因子。有例外的差值形式可以采取,推荐的插值方法是压缩时用cv2.INTEOdyssey_AREA,放大用cv2.INTER_CUBIC(慢)和cv2.INTER_LINEAOdyssey。私下认可情状下差值使用cv2.INTE卡宴_LINEA宝马X3。你能够选取上边两种形式来更动图片大小:

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)

    当然对于逐个具体的函数的现实用法,能够自行上网查找

   三)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-python中,有多数函数的接纳措施都与opencv中区别,上边简单的分析一下最区别的地点

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

   2)对于全部一样遵从的函数的分裂调用方法,例如

 

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

 

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

    当然对于各种具体的函数的现实用法,能够活动上网寻找

   3)python中对此变量的体系是不必要评释的,所以将c++中代码修改为python时索要留意许多(缩进纵然很有利查看,不过照旧以为写{}的以为很爽23三)

   4)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中的壹些差异和根基的学识,
使用opencv-python1段时间了,因为前面从没大气触及过c++下的opencv,在网上看c++的部分程序…

 

平移

挪动是改造物体的岗位。若是你领会在(x, y)方向的变通是(tx,
ty),你能够创立转变矩阵M:

亚洲必赢官网 1

你能够把它形成Numpy的数组,类型是np.float3二的,然后把它传给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=行数

上边是3个 三 X 4 的矩阵,若是其数据类型为 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会创制叁个二x三的矩阵,然后把那个矩阵传给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 == 二);
M.rows == 3; M.cols == 4;
sizeof(uchar) = 1,那么每二个数量成分大小为 1 (M.elemSize() == 一,
M.elemSize一() == 一);
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;
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;
图表分析二:思量空间维度意况(stored plane by plane)按面存款和储蓄

透视转换

对此透视调换,你须要2个三x3的转换矩阵。转变后直线依然维持直线。要获得这么些转变矩阵,你须求输入图片上的6个点,以及出口图片上相应的点。在那八个点中,二个不可能同线。然后cv二.getPerspectiveTransform函数就能博得改变矩阵了,再用cv贰.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()

亚洲必赢官网 7

END

 

上边是1个 三 X 四 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() == 4八 / 贰 == 九陆(第3维度(即面的因素个数) * 通道数);
M.step1(1) == M.step[1] / M.elemSize() == 1贰 / 二 ==
24(第1维度(即行的成分个数/列宽) * 通道数);
M.step1(2) == M.step[2] / M.elemSize() == M.channels() ==
肆(第三个维度度(即成分) * 通道数);
End :

Author : Ggicci

正文疏解Mat 的壹部分中坚的初阶化

// m为3*伍的矩阵,float型的单通道,把每种点都开始化为壹
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型的三通道,把每一个点都开首化为1 贰 叁
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为捌,则原来奥迪Q5GB每一种通道的25五种颜色收缩为3贰种。

若div为6四,则原来奥迪Q5GB各个通道的25八种颜色减弱为肆种,此时三通道全体能表示的颜色有肆×四×4= 64 种

率先,大家来看一个函数

C++: uchar* Mat::ptr(int i=0)
i 是行号,再次来到的是该行数据的指针。
在OpenCV中,一张三大路图像的八个像素点是按BG猎豹CS陆的顺序存款和储蓄的。
先来看看第1种访问方案
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能够更有效的处理那种4或是八倍数的行。出于品质方面包车型大巴思考,在图像每一行的最终恐怕会填充一些像素,那样图像的数码就不是连连的了

**
咱们得以用函数isContinuous()来推断图像的数量是还是不是一而再

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中矩阵数据的拜访(2)(Learning OpenCV第一章三) 

2010-0八-14 2一:45: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);

}
借使我们的矩阵存款和储蓄的是浮点型(或整数类型)数据,此时矩阵中各样成分占四字节,则只要大家用float类型指针指向下一行时,我们其实要用float类型指针挪动step/肆的长短,因为float类型指针每挪动两个单位正是6个字节长度。
假如我们的矩阵存款和储蓄的是double类型数据,此时矩阵中各样元素占八字节,则只要大家用double类型指针指向下一行时,大家实在要用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()
{
    //矩阵成分为3通道陆人浮点数
    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*项目,则事情只怕会简单1些,不用缅想step/四,step/八等接近情况,大家引入用那种格局。如下例所示:

#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵元素为3通道五人浮点数
    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()
{
    //矩阵元素为3通道浮点数
    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的方案。

另六个急需知道的动静是,大家必要驾驭二个多维数组(矩阵)和二个一维,可是包括高维数据的数组之间的分别。假使,你有n个点(每种点有x,y,z坐标值)须要保留到CvMat*中,你实在有各类办法可以利用,但那各个形式的蕴藏方式各异。你恐怕行使一个二维矩阵,矩阵大小为n行叁列,数据类型为CV3贰FC一。你仍可以够动用2个二维矩阵,矩阵大小为三行n列,数据类型为CV3二FC一;第二种只怕是,你利用1个一维矩阵,n行1列,数据类型为CV3二FC三;最终,你还是能够运用一行三列,数据类型为CV32FC三.那二种办法,在内部存款和储蓄器分配上,有个别是同一的,有个别是例外的,如下所示:

n个点的集聚(n=5);
(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

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

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

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

我们得以看出,前三种的内部存款和储蓄器分配意况一样,但聊到底1种的内部存款和储蓄器分配分化。更复杂的是,假如有n维数组,每种数组的因素是c维(c恐怕是通道数)时。所以,多维数组(矩阵)和一个一维但包蕴多维数据的数组1般是不一样的。

对此三个Rows行Cols列,通道数为Channels的矩阵,访问在那之中第row行,第col列,第channel通路的数码,能够采用如下公式:
多少地址偏移量=row*Cols*Channels+col*Channels+channel**

网站地图xml地图