目录
一,Mat类、图像核心信息
1,客观信息
(1)维数
(2)行列
2,主观信息
(1)通道数
(2)位深
3,Mat类坐标
4,Mat对象创建
5,Mat类型转换
二,基本操作
1,存储和读取
2,显示图像 imshow
3,显示信息
三,图片截取
1,Rect
2,Range
四,图片尺寸 resize
五,窗口控制 namedWindow
Mat类用一个对象对应一张图,除了数据域还有各种重要信息。
Opencv源码解析
Mat类中默认的坐标是以左上角为原点,向下和向右是正方向。
至于哪个是x,哪个是y,Mat中两种坐标都用到。
而行和列这2个词应该是没有歧义的,所以有些地方我会用行坐标和列坐标来描述。
可以读取图片文件创建Mat对象,也可以用数组创建Mat对象
char c[] = "123456789";
int row = 3, col = 3;
Mat image = Mat(row, col, CV_8U, c);
修改Mat对象的值,原数组的值会改变。
int main()
{
char c[] = "123456789";
int row = 3, col = 3;
Mat image = Mat(row, col, CV_8U, c);
image.at(1, 1) = 56;
for(int i=0;i<9;i++)cout << (c[i])<<" ";
return 0;
}
输出:1 2 3 4 8 6 7 8 9
如果把8位图像转成32位图像,会重新分配内存:
int main()
{
char c[] = "123456789";
int row = 3, col = 3;
Mat image = Mat(row, col, CV_8U, c);
image.convertTo(image, CV_32F);
image.at(1, 1) = 56;
for(int i=0;i<9;i++)cout << (c[i])<<" ";
return 0;
}
输出:1 2 3 4 5 6 7 8 9
即使是CV_32S转成CV_32F 也是一样,会重新分配内存。
Opencv存图读图
imshow("img", image);
waitKey(0);
本地文件:
windows自带软件显示是宽582像素,高266像素
我的程序运行结果:
文件名还有bug,连英文字母都乱码了。
如果读取参数是IMREAD_GRAYSCALE,那么显示的结果:
打印每个像素点的像素值:
cout << "rows=" << image.rows << endl;
cout << "cols=" << image.cols << endl;
cout << "channels=" << image.channels() << endl;
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
cout << int(image.at(i, j)[0])<<" ";
}
cout << endl;
}
at是模板函数,返回值类型就是模板参数的类型。
如类型参数Vec3b对应三通道的图,返回的就是Vec3b,它是一个长为3的向量,获取其中一个通道的像素值可以用[0]、[1]、[2],类型是uchar,转化成int就是0-255
其实有Vec3i的类型,直接就是int类型,但是用这个直接报内存错误,不知道为啥。
如果是单通道的图,那么参数类型就是uchar:
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
cout << int(image.at(i, j))<<" ";
}
cout << endl;
}
初始化Rectangle矩形对象,依次提供四个参数:列坐标,行坐标,宽度,高度
int main()
{
string path = "D:\im.jpg";
Mat image = imread(path, IMREAD_COLOR);
namedWindow("1", WINDOW_GUI_NORMAL);
Rect area(0, 50, 200, 350);
Mat image2 = image(area);
imshow("img", image);
imshow("img2", image2);
waitKey(0);
return 0;
}
输出:
Range的2个参数就是坐标的区间范围
Mat image2 = image(Range(0,200),Range(50,400));
第一个Range是选择行的范围,第二个是选择列的范围。
就感觉两种方式的参数顺序的反的!
先给出要变成的大小,Size类根据(宽度,高度)生成对象,
然后用resize函数得到一个新尺寸的Mat对象,原对象不影响。
resize的第五个参数是插值算法的类型。
Size dsize = Size(round(0.3 * image.cols), round(0.6 * image.rows));
Mat shrink;
resize(image, shrink, dsize, 0, 0, INTER_AREA);
imshow("shrink", shrink);
waitKey(0);
namedWindow("1", WINDOW_GUI_NORMAL);
第二个参数是用来控制窗口的属性,主要是位置和尺寸能否改变。
加上这句话之后,会多显示一个黑框,imshow输出的窗口也能移动了。
否则,imshow输出的窗口是不能移动的。
这个结果有点奇怪,我理解namedWindow函数应该就是用来控制imshow输出的窗口的属性才对。