Opencv暑期历程--Day3 Opencv里面的几个常见的数据结构 CV_8UC3,->Mat 操作的copyTo函数以及clone函数

 这几天开始实习了,比较少时间来学习Opencv,不过还是得坚持下去啊!!!

今天,比较少操作,首先就先来讲讲Opencv里面常见的几种数据类型吧,因为很多地方都有见到,也知道怎么操作这些结构的数据,不过呢,还是想记录下,以免以后看起来的时候忘记了。

先说说啥是Vector吧。

什么是Vector

vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.

用法:
1.文件包含:     
           首先在程序开头处加上#include以包含所需要的类文件vector,还有一定要加上using namespace std;

2.声明一个int向量以替代一维的数组:vector a;(等于声明了一个int数组a[],大小没有指定,可以动态的向里面添加删除。

比如Vec
其实这句就是定义一个uchar类型的数组,长度为3而已,例如 8U 类型的 RGB 彩色图像可以使用 ,3 通道 float 类型的矩阵可以使用 。对于 Vec 对象,可以使用[]符号如操作数组般读写其元素,如:Vec3b color; //用 color 变量描述一种 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;
}

 Opencv暑期历程--Day3 Opencv里面的几个常见的数据结构 CV_8UC3,<Vec3b>->Mat 操作的copyTo函数以及clone函数_第1张图片

所以,如果要复制一个图片赋值给另一个Mat对象,最好就用Mat的clone()函数或者copyTo()函数,这是深层次拷贝,还有一种方法是新建一个和原来图像一样格式和大小的空图片,然后一个像素点一个像素点复制过去。

后者就那样吧,就是对图像的遍历,两个循环就完事了。感觉看看这两个函数比较有意思。

该演示下Mat操作的clone函数和copyTo函数了。

copyTo():

Opencv暑期历程--Day3 Opencv里面的几个常见的数据结构 CV_8UC3,<Vec3b>->Mat 操作的copyTo函数以及clone函数_第2张图片

 

 img1.clone():

Opencv暑期历程--Day3 Opencv里面的几个常见的数据结构 CV_8UC3,<Vec3b>->Mat 操作的copyTo函数以及clone函数_第3张图片

 

 

 

// 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; //两个矩形求并集

 

你可能感兴趣的:(视觉处理)