这几天开始实习了,比较少时间来学习Opencv,不过还是得坚持下去啊!!!
今天,比较少操作,首先就先来讲讲Opencv里面常见的几种数据类型吧,因为很多地方都有见到,也知道怎么操作这些结构的数据,不过呢,还是想记录下,以免以后看起来的时候忘记了。
先说说啥是Vector吧。
vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.
用法:
1.文件包含:
首先在程序开头处加上#include
2.声明一个int向量以替代一维的数组:vector
比如Vec
其实这句就是定义一个uchar类型的数组,长度为3而已,例如 8U 类型的 RGB 彩色图像可以使用
color[0]=255; //0通道的B 分量
color[1]=0; //1通道的G 分量
color[2]=0; //2通道的R 分量
说到这,不得不提下在Opencv中怎么访问一张图片的像素。
cv::mat的成员函数: .at(int y, int x)可以用来存取图像中对应坐标为(x,y)的元素坐标。但是在使用它时要注意,在编译期必须要已知图像的数据类型,这是因为cv::mat可以存放任意数据类型的元素。因此at方法的实现是用模板函数来实现的。假设提前已知一幅图像img的数据类型为 unsigned char型灰度图(单通道),要对坐标为(14,25)的像素重新赋值为25,则对应操作如下:
src.at(14,25) = 25;
彩色的图:
img.at(14,25) [0]= 25;//B
img.at< Vec3b >(14,25) [1]= 25;//G
img.at< Vec3b >(14,25 [2]= 25;//R
还有一个,像这样下面的赋值会造成大祸
Mat img1 = imread("i.png");
Mat img2 = img1;
img1.at(14,25)[0] = 0; //设置彩色图片横坐标=14,纵坐标=15的像素点上的b,g,r,蓝绿红三色通道里的蓝色通道的值为0
乍一看,好像没啥问题,改变的只是Img1的像素啊,其实不然,这个Mat赋值过去的时候只是复制信息头过去了,
你可以把它理解成指针吧,,,要是改了img1里面的东西,img2也是会改变的,因为img1和img2是共享一个数据区的不信看看代码喽。
// opencv_day3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat img1(400,400, CV_8UC3, Scalar(0, 0, 255));/*声明一个400*400像素的,CV_8UC3(8位,无符号3通道的),三个颜色通道的值分别为b=0,g=0,r=255的位图*/
cvNamedWindow("img1", WINDOW_AUTOSIZE);
cvNamedWindow("img2", WINDOW_AUTOSIZE);
cvNamedWindow("changed_img1", WINDOW_AUTOSIZE);
cvNamedWindow("changed_img2", WINDOW_AUTOSIZE);
imshow("img1", img1);
Mat img2 = img1;
imshow("img2", img2);
int i, j;
for (i = 0; i < 400; i++)//把img1图片变为蓝色
{
for (j = 0; j < 400; j++)
{
img1.at(i, j)[0] = 255;//把img1图片每个像素点的蓝色通道值设为255
img1.at(i,j)[2] = 0;//把img1图片每个像素点的红色通道的值设为0
}
}
imshow("changed_img1", img1);
imshow("changed_img2", img2);
waitKey(0);
return 0;
}
所以,如果要复制一个图片赋值给另一个Mat对象,最好就用Mat的clone()函数或者copyTo()函数,这是深层次拷贝,还有一种方法是新建一个和原来图像一样格式和大小的空图片,然后一个像素点一个像素点复制过去。
后者就那样吧,就是对图像的遍历,两个循环就完事了。感觉看看这两个函数比较有意思。
该演示下Mat操作的clone函数和copyTo函数了。
copyTo():
img1.clone():
// opencv_day3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat img1 = imread("1.png");
Mat img_copy;
img1.copyTo(img_copy);//用copyTo函数将img1的图片信息深度拷贝到img_copy空的mat对象里
//img_copy = img1.clone();
cvNamedWindow("原图", WINDOW_AUTOSIZE);
cvNamedWindow("复制图", WINDOW_AUTOSIZE);
imshow("原图", img1);
imshow("复制图", img_copy);
waitKey(0);
return 0;
}
Mat image = imread("1.png" , 0) ;
//Mat image1(image) ;//仅是创建了Mat的头部分,image1与image共享数据区
//Mat image1 = image ;//仅是创建了Mat的头部分,image1与image共享数据区
//Mat image1 = image.clone() ;//完全拷贝,把image中的所有信息拷贝到image1中
Mat image1 ;
image.copyTo(image1) ;//拷贝image的数据区到image1中,在拷贝数据前会有一步:image1.create(this->size , this->type)
这里讲讲CV_8UC3,一般来说彩色图片就是这个格式了哈。
一般的图像文件格式使用的是 Unsigned 8bits吧,CvMat矩阵对应的参数类型就是
CV_8UC1,CV_8UC2,CV_8UC3。
(最后的1、2、3表示通道数,譬如RGB3通道就用CV_8UC3)
而float 是32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3...
double是64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3等。
Mat m1(2, 2, CV_8UC3, Scalar(0, 0, 255)); //其中的宏的解释:CV_[位数][带符号与否][类型前缀]C[通道数]
//点的表示:Point
Point p;
p.x = 1; //x坐标
p.y = 1; //y坐标
//或者
Point p2(1, 1);
//颜色的表示:Scalar(b,g,r);注意不是rgb,注意对应关系
Scalar(1, 1, 1);
//尺寸的表示:Size
Size(5, 5);// 宽度和高度都是5
//矩形的表示:Rect,成员变量有x,y,width,height
Rect r1(0, 0, 100, 60);
Rect r2(10, 10, 100, 60);
Rect r3 = r1 | r2; //两个矩形求交集
Rect r4 = r1 & r2; //两个矩形求并集