使用opencv-python一段时间了,因为此前未曾大气触及过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类的目的用于表示3个多维度的单通道或然多通道稠密数组,它能够用来储存以下东西)
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,方今自笔者用的是 二.3版,里面包车型大巴文书档案提议 CvMat 和 CvMatND 弃用了,在C++封装中用 Mat
代替,其余旧版还有八个 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 其实就是行,一行一行也正是y 啦。height中度也便是y啦。

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

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

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

    rows 其实便是行,1行壹行约等于y 啦。height中度也正是y啦。

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

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

OpenCV提供了八个转移函数,cv2.warpAffine和cv贰.warpPerspective,通过他们你能够打开各类转变,cv二.warpAffine经受二x叁的转移矩阵2cv贰.warpPerspective收受三x3的转换矩阵做为输入。

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

  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 * 5
的为3维
channels:通道,矩阵中的每贰个矩阵成分具备的值的个数,比如说 三 * 4矩阵中一共 1二 个因素,假如每一个成分有四个值,那么就说那个矩阵是 三通道的,即 channels = 三。常见的是一张彩色图片有红、绿、蓝三个通道。
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:是四个数组,定义了矩阵的布局,具体见上面图片分析,其它注意 step一(step / elemSize1),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 的轻重
图片分析1:思索贰维情状(stored row by row)按行存款和储蓄

缩放

OpenCV有三个函数cv2.resize()来干那几个,图片的高低能够人工钦定,恐怕您能够钦定缩放因子。有例外的差值情势能够动用,推荐的插值方法是压缩时用cv二.INTEMurano_AREA,放大用cv2.INTER_CUBIC(慢)和cv2.INTER_LINEACR-V。私下认可境况下差值使用cv二.INTE大切诺基_LINEATiggo。你能够动用下边三种艺术来退换图片大小:

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中分歧,上面简单的解析一下最不一致的地方

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

   二)对于具有一样效果的函数的两样调用方法,例如

 

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

 

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

    当然对于各个具体的函数的切实可行用法,可以自动上网寻找

   叁)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中采用cv2.方法名或变量名来调用方法/变量

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

 

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

 

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

    当然对于每一个具体的函数的具体用法,能够自行上网物色

   三)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中的1些组别和底蕴的文化,
使用opencv-python1段时间了,因为事先未有大气触及过c++下的opencv,在网上看c++的有的程序…

 

平移

一举手一投足是退换物体的职责。假设您理解在(x, y)方向的变动是(tx,
ty),你能够创设调换矩阵M:

金沙注册送58 1

您能够把它形成Numpy的数组,类型是np.float32的,然后把它传给cv二.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 四 的矩阵,假诺其数据类型为 CV_捌U,也正是单通道的 uchar
类型

旋转

对多少个图片旋转七个θ角是通过上边这么些格局的转变矩阵完成的:

金沙注册送58 2

然而OpenCV提供了可选主题的缩放旋转,所以你能够按任意点旋转。转变矩阵变为:

金沙注册送58 3

其中:

金沙注册送58 4

要找到那几个转变矩阵,OpenCV提供了3个函数,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))

结果:

金沙注册送58 5

仿射转变

在仿射调换里,全数原始图片里的平行线在输出的图形里还是平行,要找到转变矩阵,大家必要输入图片的多少个点,和他们在出口图片里的对应地点,然后cv二.getAffineTransform会创造3个二x3的矩阵,然后把这几个矩阵传给cv二.warpAffine.

看上面包车型客车例子,注意本人选的多少个点(藏蓝的点)

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

pts1 = np.float32([[50,50],[200,50],[50,200]]opencv中的一些区分和底蕴的文化,elemSize和数量地址总计的接头。)
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个二维矩阵,那么维度为 二 (M.dims == 二);
M.rows == 3; M.cols == 4;
sizeof(uchar) = 一,那么每一个多少成分大小为 1 (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_8UC3,也正是三通道

金沙注册送58 6

M.dims == 2; M.channels() == 3;M.depth() == 0;
M.elemSize() == 三 (每1个成分包蕴一个uchar值) M.elemSize壹() == 1(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)按面存款和储蓄

透视转换

对此透视调换,你须求3个三x三的改变矩阵。调换后直线照旧维持直线。要获得这几个转变矩阵,你需求输入图片上的多少个点,以及出口图片上相应的点。在这多个点中,二个无法同线。然后cv贰.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()

金沙注册送58 7

END

 

地点是四个 三 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八 / 二 == 九陆(第二维度(即面包车型客车因素个数) * 通道数);
M.step1(1) == M.step[1] / M.elemSize() == 1二 / 二 ==
24(第一维度(即行的要素个数/列宽) * 通道数);
M.step1(2) == M.step[2] / M.elemSize() == M.channels() ==
4(第四个维度度(即成分) * 通道数);
End :

Author : Ggicci

本文疏解Mat 的一对着力的早先化

// m为3*5的矩阵,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型的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为八,则原来帕杰罗GB每一种通道的25七种颜色收缩为3二种。

若div为64,则原来瑞虎GB每一个通道的25八种颜色减弱为四种,此时3通道全体能表示的颜色有4×四×4= 6四 种

首先,大家来看三个函数

C++: uchar* Mat::ptr(int i=0)
i 是行号,重回的是该行数据的指针。
在OpenCV中,一张三通道图像的1个像素点是按BG福睿斯的顺序存款和储蓄的。
先来看望第二种访问方案
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里的积存机制难点,行与行之间或然有空落落单元。这几个空白单元对图像来讲是从未有过意思的,只是为了在1些架构上能够更有功效,比如intel
MMX能够更实用的处理那种4或是8倍数的行。是因为质量方面包车型地铁设想,在图像每一行的最后可能会填充1些像素,那样图像的数目就不是接贰连叁的了

**
我们得以用函数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中矩阵数据的拜会(贰)(Learning OpenCV第二章三) 

二〇〇八-0八-14 2壹:45:19|  分类: 应用探讨学习 |字号 订阅
上壹篇小说提到了拜访矩阵七月素的前两种艺术,上面讲第三种格局:正确的拜会矩阵中多少的章程:

不错的不二等秘书籍
前方介绍的一部分读取和写入矩阵数据的诀要,实际上,你也许很少会选取它们。因为,在大多情景下,你须要动用最有功能的艺术来拜访矩阵中的数据。假设使用上述的函数分界面来访问数据,效用相当的低,你应当使用指针格局来直接待上访问矩阵中多少。尤其是,假如您想遍历矩阵中颇具因素时,就更须要那样做了。
在用指针直接待上访问矩阵成分时,就要求相当留意矩阵结构体中的step成员。该成员是以字节为单位的每行的尺寸。而矩阵结构体的cols或width就不切合此时使用,因为为了访问功能,矩阵中的内部存款和储蓄器分配上,是以每多少个字节做为最小单位的。因而一旦1个矩阵的大幅是多少个字节,那么就会在宽窄上分红三个字节,而那时候每行最终叁个字节会被忽视掉。所以大家用step则会准确地按行访问数据。
我们得以经过以下例子,看一下rows,cols,height,width,step的数额,你可以因此转移矩阵的因素类型定义,来查阅step的改造:
#pragma comment(lib,”cxcore.lib”)
#include”cv.h”
#include<stdio.h>
void main()
{
    //矩阵成分为3通道柒人浮点数
    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类型指针每挪动二个单位正是几个字节长度。
比方大家的矩阵存款和储蓄的是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()
{
    //矩阵元素为③通道七位浮点数
    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()
{
    //矩阵成分为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”);
    }
}

金沙注册送58 ,最终要留意一下,大家在每行都要选取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的方案。

另3个索要明白的情状是,大家供给精晓二个多维数组(矩阵)和二个一维,可是包含高维数据的数组之间的区分。借使,你有n个点(每一种点有x,y,z坐标值)供给保留到CvMat*中,你其实有多样格局得以使用,但那二种方法的储存方式各异。你可能选取一个2维矩阵,矩阵大小为n行三列,数据类型为CV3二FC1。你还足以选择1个二维矩阵,矩阵大小为三行n列,数据类型为CV3二FC1;第三种大概性是,你利用三个一维矩阵,n行一列,数据类型为CV3二FC3;最终,你还是能够动用一行三列,数据类型为CV32FC叁.那二种格局,在内部存款和储蓄器分配上,某个是一律的,有个别是例外的,如下所示:

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行叁列时(数据类型CV3二FC一)内部存款和储蓄器分配情状
x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

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

我们得以看看,前三种的内部存款和储蓄器分配景况同样,但谈到底壹种的内部存款和储蓄器分配区别。更复杂的是,假如有n维数组,每一种数组的因素是c维(c也许是通道数)时。所以,多维数组(矩阵)和二个1维但分包多维数据的数组壹般是差异的。

对于二个Rows行Cols列,通道数为Channels的矩阵,访问个中第row行,第col列,第channel坦途的数额,能够动用如下公式:
数码地址偏移量=row*Cols*Channels+col*Channels+channel**

相关文章

网站地图xml地图